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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox