From: "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "D. Ben Knoble" <ben.knoble@gmail.com>,
Harald Nordgren <haraldnordgren@gmail.com>
Subject: [PATCH v3 0/2] remote: url-based pushRemote with renamed remotes
Date: Tue, 21 Jul 2026 20:14:17 +0000 [thread overview]
Message-ID: <pull.2358.v3.git.git.1784664859.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2358.v2.git.git.1784624306.gitgitgadget@gmail.com>
Fix git status not showing the push branch after remotes are renamed, when
branch.<name>.pushRemote is a URL matching exactly one configured remote.
Changes in v4:
* Match against the actual push URL, including pushurl and pushInsteadOf.
* Clarify how rearranging remotes exposes the git status tracking problem.
* Simplify and correct the documentation for URL-valued pushRemote.
Changes in v3:
* Revamp commit messages to clarify motivation.
Changes in v2:
* Clarify that URL push destinations already work and that this change only
restores their tracking information.
* Document URL values for branch.<name>.pushRemote and their @{push}
behavior.
Harald Nordgren (2):
remote: pass repository to push tracking helper
remote: find tracking branches for URL push destinations
Documentation/config/branch.adoc | 1 +
Documentation/revisions.adoc | 3 +
remote.c | 43 +++++++++--
remote.h | 2 +
t/t5505-remote.sh | 124 +++++++++++++++++++++++++++++++
transport.c | 5 +-
6 files changed, 172 insertions(+), 6 deletions(-)
base-commit: 48bbf81c29ca9a4479ec7850fe206518682cdb2f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2358%2FHaraldNordgren%2Fremote-resolve-url-push-tracking-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2358/HaraldNordgren/remote-resolve-url-push-tracking-v3
Pull-Request: https://github.com/git/git/pull/2358
Range-diff vs v2:
1: b1ac49de87 = 1: b1ac49de87 remote: pass repository to push tracking helper
2: 6e924a7fec ! 2: a343af9d50 remote: find tracking branches for URL push destinations
@@ Metadata
## Commit message ##
remote: find tracking branches for URL push destinations
- Git already accepts a repository URL as branch.<name>.pushRemote and
- can push to it. When a configured remote has the same URL, however,
- "git status" cannot show that remote's push branch.
+ Git accepts a repository URL as branch.<name>.pushRemote and can push
+ to it. This branch setting takes precedence over remote.pushDefault.
- This can happen in fork workflows when the original remote is renamed
- to "upstream", the fork is added as "origin", and an existing
- pushRemote value still contains the fork URL. The URL still points to
- the right repository, so pushing works. However, @{push} is unavailable
- because Git does not connect the URL to "origin". As a result,
+ A branch can be configured with a URL-valued pushRemote before any push
+ occurs. If the remotes are later rearranged with "git remote rename" and
+ "git remote add", the newly added remote may use that URL. The URL value
+ is unaffected by the rename and continues to take precedence over
+ remote.pushDefault. The URL and the remote then point to the same
+ repository, but Git does not connect them for tracking. Pushing works,
+ but @{push} cannot identify the remote's tracking branch. As a result,
"git status" cannot show the push branch, and an up-to-date push can
- leave its local tracking information stale.
+ leave its tracking information stale.
- When exactly one configured remote has the URL as one of its
- remote.<name>.url values, use its fetch refspec to find and refresh the
- push branch. Keep the URL as the push destination so the configured
- remote's push settings do not change existing behavior. Keep the
- current behavior when no remote matches or multiple remotes match.
+ When exactly one configured remote uses the push destination URL, use
+ that remote for push tracking. Continue to push to the URL so the
+ configured remote's push settings do not change existing behavior. Keep
+ the current behavior when no remote matches or multiple remotes match.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
@@ Documentation/config/branch.adoc: This option defaults to `never`.
repository), you would want to set `remote.pushDefault` to
specify the remote to push to for all branches, and use this
option to override it for a specific branch.
-+ The value may be the name of a configured remote or a repository
-+ URL. A URL is used directly as the push destination.
++ The value may be the name of a configured remote or a repository URL.
`branch.<name>.merge`::
Defines, together with `branch.<name>.remote`, the upstream branch
@@ Documentation/revisions.adoc: some output processing may assume ref names in UTF
`git push` were run while `branchname` was checked out (or the current
`HEAD` if no branchname is specified). Like for '@\{upstream\}', we report
the remote-tracking branch that corresponds to that branch at the remote.
-+ If the push destination is a URL and exactly one configured remote has the
-+ same `remote.<name>.url`, '@\{push}' reports the remote-tracking branch for
-+ that remote.
++ If the push destination is a URL and exactly one configured remote has
++ that URL among its `remote.<name>.url` values, '@\{push}' reports that
++ remote's remote-tracking branch.
+
Here's an example to make it more clear:
+
@@ remote.c: const char *branch_get_upstream(struct branch *branch, struct strbuf *
+struct remote *repo_remote_for_push_tracking(struct repository *repo,
+ struct remote *remote)
+{
++ const struct strvec *push_urls;
+ struct remote *first_match = NULL;
+ struct remote_state *remote_state = repo->remote_state;
++ const char *check_url;
+
-+ if (remote->origin != REMOTE_UNCONFIGURED || remote->url.nr != 1)
++ if (remote->origin != REMOTE_UNCONFIGURED)
+ return remote;
+
++ push_urls = push_url_of_remote(remote);
++ if (push_urls->nr != 1)
++ return remote;
++ check_url = push_urls->v[0];
++
+ for (int i = 0; i < remote_state->remotes_nr; i++) {
+ struct remote *candidate = remote_state->remotes[i];
+
+ if (!candidate || candidate == remote ||
+ !remote_is_configured(candidate, 0) ||
-+ !remote_has_url(candidate, remote->url.v[0]))
++ !remote_has_url(candidate, check_url))
+ continue;
+ if (first_match)
+ return remote;
@@ t/t5505-remote.sh: setup_repository () {
+ rm -rf fork.git client &&
+ git clone --bare one fork.git &&
+ git clone one client &&
-+ fork_url="$TRASH_DIRECTORY/fork.git" &&
++ fork_url="file://$TRASH_DIRECTORY/fork.git" &&
+ (
+ cd client &&
+ git checkout -b topic --track origin/main &&
@@ t/t5505-remote.sh: test_expect_success 'rename a remote renames repo remote.push
+ EOF
+'
+
-+test_expect_success 'adding fork remote makes URL-valued pushRemote trackable' '
++test_expect_success 'adding matching remote makes URL-valued pushRemote trackable' '
+ setup_url_pushremote &&
+
+ (
@@ t/t5505-remote.sh: test_expect_success 'rename a remote renames repo remote.push
+ EOF
+'
+
++test_expect_success 'pushInsteadOf URL pushRemote is trackable' '
++ setup_url_pushremote &&
++ (
++ cd client &&
++ git remote rename origin upstream &&
++ git remote add -f origin "$fork_url" &&
++ git config "url.$fork_url.pushInsteadOf" fork: &&
++ git config branch.topic.pushRemote fork:
++ ) &&
++
++ check_status <<-EOF
++ On branch topic
++ Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
++
++ Your branch is up to date with ${SQ}origin/topic${SQ}.
++
++ nothing to commit, working tree clean
++ EOF
++'
++
+test_expect_success 'up-to-date URL push refreshes stale tracking branch' '
+ setup_url_pushremote &&
+ (
--
gitgitgadget
next prev parent reply other threads:[~2026-07-21 20:14 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-20 9:10 [PATCH 0/2] remote: resolve url push tracking Harald Nordgren via GitGitGadget
2026-07-20 9:10 ` [PATCH 1/2] remote: pass repository to push tracking helper Harald Nordgren via GitGitGadget
2026-07-20 18:23 ` Junio C Hamano
2026-07-20 9:10 ` [PATCH 2/2] remote: resolve URL-valued push tracking remotes Harald Nordgren via GitGitGadget
2026-07-20 18:49 ` Junio C Hamano
2026-07-20 19:56 ` Harald Nordgren
2026-07-20 23:49 ` Junio C Hamano
2026-07-21 16:11 ` Junio C Hamano
2026-07-21 8:58 ` [PATCH v2 0/2] remote: renamed remote push tracking Harald Nordgren via GitGitGadget
2026-07-21 8:58 ` [PATCH v2 1/2] remote: pass repository to push tracking helper Harald Nordgren via GitGitGadget
2026-07-21 8:58 ` [PATCH v2 2/2] remote: find tracking branches for URL push destinations Harald Nordgren via GitGitGadget
2026-07-21 14:28 ` [PATCH v2 0/2] remote: renamed remote push tracking D. Ben Knoble
2026-07-21 20:10 ` Harald Nordgren
2026-07-21 20:14 ` Harald Nordgren via GitGitGadget [this message]
2026-07-21 20:14 ` [PATCH v3 1/2] remote: pass repository to push tracking helper Harald Nordgren via GitGitGadget
2026-07-21 20:14 ` [PATCH v3 2/2] remote: find tracking branches for URL push destinations Harald Nordgren via GitGitGadget
2026-07-21 22:15 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.2358.v3.git.git.1784664859.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=ben.knoble@gmail.com \
--cc=git@vger.kernel.org \
--cc=haraldnordgren@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.