All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Harald Nordgren <haraldnordgren@gmail.com>,
	Harald Nordgren <haraldnordgren@gmail.com>
Subject: [PATCH 2/2] remote: allow a list of remotes in remote.pushDefault
Date: Fri, 02 Oct 2026 07:17:52 +0000	[thread overview]
Message-ID: <955709d4ef3aa43a6fb15cf5007daf094b76d427.1790925472.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2423.git.git.1790925472.gitgitgadget@gmail.com>

From: Harald Nordgren <haraldnordgren@gmail.com>

Someone who pushes to a personal fork in some repositories and to
origin in others cannot set remote.pushDefault globally. Repositories
without the named remote fail to push, because git takes the missing
name for a URL.

Let remote.pushDefault hold a space separated list of remote names and
push to the first one that is configured in the repository. When none
of them is configured, fall back to branch.<name>.remote as if the
variable was not set. A single name keeps working as before, and a
value set in the repository still overrides one set globally.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
---
 Documentation/config/remote.adoc |  7 +++++++
 remote.c                         | 29 ++++++++++++++++++++++---
 t/t5516-fetch-push.sh            | 36 ++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/Documentation/config/remote.adoc b/Documentation/config/remote.adoc
index 3a20d0f752..6a67c97fe8 100644
--- a/Documentation/config/remote.adoc
+++ b/Documentation/config/remote.adoc
@@ -2,6 +2,13 @@ remote.pushDefault::
 	The remote to push to by default.  Overrides
 	`branch.<name>.remote` for all branches, and is overridden by
 	`branch.<name>.pushRemote` for specific branches.
++
+The value may be a space separated list of remote names, in which case
+the first one that is configured in the repository is used. If none of
+them is configured, `branch.<name>.remote` is used as if
+`remote.pushDefault` was not set. This allows setting a list such as
+`fork origin` globally and have repositories without a `fork` remote
+push to `origin`.
 
 remote.<name>.url::
 	The URL of a remote repository.  See linkgit:git-fetch[1] or
diff --git a/remote.c b/remote.c
index 6567ec91cc..3cad0673b9 100644
--- a/remote.c
+++ b/remote.c
@@ -700,6 +700,25 @@ const char *remote_for_branch(struct branch *branch, int *explicit)
 					 explicit);
 }
 
+static const char *pushdefault_candidate(struct remote_state *remote_state)
+{
+	const char *p = remote_state->pushremote_name;
+
+	if (!strchr(p, ' '))
+		return p;
+
+	while (*p) {
+		size_t len = strcspn(p, " ");
+		struct remote *remote = find_remote(remote_state, p, len);
+
+		if (remote && valid_remote(remote))
+			return remote->name;
+		p += len;
+		p += strspn(p, " ");
+	}
+	return NULL;
+}
+
 static const char *
 remotes_pushremote_for_branch(struct remote_state *remote_state,
 			      struct branch *branch, int *explicit)
@@ -710,9 +729,13 @@ remotes_pushremote_for_branch(struct remote_state *remote_state,
 		return branch->pushremote_name;
 	}
 	if (remote_state->pushremote_name) {
-		if (explicit)
-			*explicit = 1;
-		return remote_state->pushremote_name;
+		const char *name = pushdefault_candidate(remote_state);
+
+		if (name) {
+			if (explicit)
+				*explicit = 1;
+			return name;
+		}
 	}
 	return remotes_remote_for_branch(remote_state, branch, explicit);
 }
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index b982b209bf..7a0cdafd65 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -591,6 +591,42 @@ test_expect_success 'push with remote.pushdefault' '
 	check_push_result down_repo $the_commit heads/main
 '
 
+test_expect_success 'push with remote.pushdefault list picks first existing remote' '
+	mk_test up_repo heads/main &&
+	mk_test down_repo heads/main &&
+	test_config remote.up.url up_repo &&
+	test_config remote.down.url down_repo &&
+	test_config branch.main.remote up &&
+	test_config remote.pushdefault "missing down up" &&
+	test_config push.default matching &&
+	git push &&
+	check_push_result up_repo $the_first_commit heads/main &&
+	check_push_result down_repo $the_commit heads/main
+'
+
+test_expect_success 'push with remote.pushdefault list of missing remotes' '
+	mk_test up_repo heads/main &&
+	test_config remote.up.url up_repo &&
+	test_config branch.main.remote up &&
+	test_config remote.pushdefault "missing also-missing" &&
+	test_config push.default matching &&
+	git push &&
+	check_push_result up_repo $the_commit heads/main
+'
+
+test_expect_success 'repository remote.pushdefault overrides global list' '
+	mk_test up_repo heads/main &&
+	mk_test down_repo heads/main &&
+	test_config remote.up.url up_repo &&
+	test_config remote.down.url down_repo &&
+	test_config_global remote.pushdefault "down up" &&
+	test_config remote.pushdefault up &&
+	test_config push.default matching &&
+	git push &&
+	check_push_result up_repo $the_commit heads/main &&
+	check_push_result down_repo $the_first_commit heads/main
+'
+
 test_expect_success 'push with config remote.*.pushurl' '
 	mk_test testrepo heads/main &&
 	git checkout main &&
-- 
gitgitgadget

      parent reply	other threads:[~2026-10-02  7:17 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-02  7:17 [PATCH 0/2] remote: allow a list of remotes in remote.pushDefault Harald Nordgren via GitGitGadget
2026-10-02  7:17 ` [PATCH 1/2] remote: factor out lookup of a remote by name Harald Nordgren via GitGitGadget
2026-10-02  7:17 ` Harald Nordgren via GitGitGadget [this message]

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=955709d4ef3aa43a6fb15cf5007daf094b76d427.1790925472.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@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.