git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC/PATCH 3/3] push: add separate 'downstream' branch

From
Felipe Contreras <felipe.contreras@gmail.com>
Date
May 16, 2013, 03:43 UTC
Message-ID
<1368675828-27418-4-git-send-email-felipe.contreras@gmail.com>
In-Reply-To
<1368675828-27418-1-git-send-email-felipe.contreras@gmail.com>

It doesn't make sense to push to the upstream branch, so create new configurations for the notion of 'downstream' branch, which is basically the branch to push to by default.

The upstream branch is remote+merge, the downstream branch is pushremote+push.

  [branch "master"]
	  remote = origin
	  merge = refs/heads/master
	  pushremote = github
	  push = refs/heads/master
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 builtin/push.c | 65 ++++++++++++++++++++++++++++++++++++----------------------
 remote.c       |  8 ++++++--
 remote.h       |  3 +++
 3 files changed, 50 insertions(+), 26 deletions(-)
diff --git a/builtin/push.c b/builtin/push.c
index 909c34d..c062fa5 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -76,21 +76,23 @@ static int push_url_of_remote(struct remote *remote, const char ***url_p)
 	return remote->url_nr;
 }
 
-static NORETURN int die_push_simple(struct branch *branch, struct remote *remote) {
+static NORETURN int die_push_simple(struct branch *branch, struct remote *remote,
+		const char *kind, const char *related)
+{
 	/*
 	 * There's no point in using shorten_unambiguous_ref here,
 	 * as the ambiguity would be on the remote side, not what
 	 * we have locally. Plus, this is supposed to be the simple
 	 * mode. If the user is doing something crazy like setting
-	 * upstream to a non-branch, we should probably be showing
+	 * upstream/downstream to a non-branch, we should probably be showing
 	 * them the big ugly fully qualified ref.
 	 */
 	const char *advice_maybe = "";
-	const char *short_upstream =
-		skip_prefix(branch->merge[0]->src, "refs/heads/");
+	const char *short_upstream = skip_prefix(related, "refs/heads/");
 
 	if (!short_upstream)
-		short_upstream = branch->merge[0]->src;
+		short_upstream = related;
+
 	/*
 	 * Don't show advice for people who explicitely set
 	 * push.default.
@@ -99,8 +101,8 @@ static NORETURN int die_push_simple(struct branch *branch, struct remote *remote
 		advice_maybe = _("\n"
 				 "To choose either option permanently, "
 				 "see push.default in 'git help config'.");
-	die(_("The upstream branch of your current branch does not match\n"
-	      "the name of your current branch.  To push to the upstream branch\n"
+	die(_("The %s branch of your current branch does not match\n"
+	      "the name of your current branch.  To push to the %s branch\n"
 	      "on the remote, use\n"
 	      "\n"
 	      "    git push %s HEAD:%s\n"
@@ -109,6 +111,7 @@ static NORETURN int die_push_simple(struct branch *branch, struct remote *remote
 	      "\n"
 	      "    git push %s %s\n"
 	      "%s"),
+	    kind, kind,
 	    remote->name, short_upstream,
 	    remote->name, branch->name, advice_maybe);
 }
@@ -117,6 +120,8 @@ static void setup_push_upstream(struct remote *remote, int simple)
 {
 	struct strbuf refspec = STRBUF_INIT;
 	struct branch *branch = branch_get(NULL);
+	const char *related, *kind, *pushremote_name;
+
 	if (!branch)
 		die(_("You are not currently on a branch.\n"
 		    "To push the history leading to the current (detached HEAD)\n"
@@ -124,26 +129,38 @@ static void setup_push_upstream(struct remote *remote, int simple)
 		    "\n"
 		    "    git push %s HEAD:<name-of-remote-branch>\n"),
 		    remote->name);
-	if (!branch->merge_nr || !branch->merge || !branch->remote_name)
-		die(_("The current branch %s has no upstream branch.\n"
-		    "To push the current branch and set the remote as upstream, use\n"
-		    "\n"
-		    "    git push --set-upstream %s %s\n"),
-		    branch->name,
-		    remote->name,
-		    branch->name);
-	if (branch->merge_nr != 1)
-		die(_("The current branch %s has multiple upstream branches, "
-		    "refusing to push."), branch->name);
-	if (strcmp(branch->remote_name, remote->name))
-		die(_("You are pushing to remote '%s', which is not the upstream of\n"
+
+	if (branch->push) {
+		kind = _("downstream");
+		related = branch->push;
+		pushremote_name = branch->pushremote_name;
+	} else {
+		if (!branch->merge_nr || !branch->merge || !branch->remote_name)
+			die(_("The current branch %s has no upstream branch.\n"
+			    "To push the current branch and set the remote as upstream, use\n"
+			    "\n"
+			    "    git push --set-upstream %s %s\n"),
+			    branch->name,
+			    remote->name,
+			    branch->name);
+		if (branch->merge_nr != 1)
+			die(_("The current branch %s has multiple upstream branches, "
+			    "refusing to push."), branch->name);
+
+		kind = _("upstream");
+		related = branch->merge[0]->src;
+		pushremote_name = branch->remote_name;
+	}
+
+	if (strcmp(pushremote_name, remote->name))
+		die(_("You are pushing to remote '%s', which is not the %s of\n"
 		      "your current branch '%s', without telling me what to push\n"
 		      "to update which remote branch."),
-		    remote->name, branch->name);
-	if (simple && strcmp(branch->refname, branch->merge[0]->src))
-		die_push_simple(branch, remote);
+		    remote->name, kind, branch->name);
+	if (simple && strcmp(branch->refname, related))
+		die_push_simple(branch, remote, kind, related);
 
-	strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
+	strbuf_addf(&refspec, "%s:%s", branch->name, related);
 	add_refspec(refspec.buf);
 }
 
diff --git a/remote.c b/remote.c
index 322a1b6..f057b5f 100644
--- a/remote.c
+++ b/remote.c
@@ -365,13 +365,17 @@ static int handle_config(const char *key, const char *value, void *cb)
 				explicit_default_remote_name = 1;
 			}
 		} else if (!strcmp(subkey, ".pushremote")) {
+			if (git_config_string(&branch->pushremote_name, key, value))
+				return -1;
 			if (branch == current_branch)
-				if (git_config_string(&pushremote_name, key, value))
-					return -1;
+				pushremote_name = xstrdup(branch->pushremote_name);
 		} else if (!strcmp(subkey, ".merge")) {
 			if (!value)
 				return config_error_nonbool(key);
 			add_merge(branch, xstrdup(value));
+		} else if (!strcmp(subkey, ".push")) {
+			if (git_config_string(&branch->push, key, value))
+				return -1;
 		}
 		return 0;
 	}
diff --git a/remote.h b/remote.h
index cf56724..24433af 100644
--- a/remote.h
+++ b/remote.h
@@ -138,6 +138,9 @@ struct branch {
 	struct refspec **merge;
 	int merge_nr;
 	int merge_alloc;
+
+	const char *pushremote_name;
+	const char *push;
 };
 
 struct branch *branch_get(const char *name);
-- 
1.8.3.rc1.579.g184e698
Previous: Felipe ContrerasNext: Junio C Hamano
Message 14 of 28 in “New kind of upstream branch: downstream branch”
  1. 0/3 New kind of upstream branch: downstream branchFelipe Contreras, May 16, 2013
  2. 1/3 remote: don't override default if cur head remote is '.'Felipe Contreras, May 16, 2013
  3. 2/3 pull: trivial cleanupsFelipe Contreras, May 16, 2013
  4. Ramkumar RamachandraMay 16, 2013
  5. Felipe ContrerasMay 16, 2013
  6. Ramkumar RamachandraMay 16, 2013
  7. Felipe ContrerasMay 16, 2013
  8. Ramkumar RamachandraMay 16, 2013
  9. Felipe ContrerasMay 16, 2013
  10. Ramkumar RamachandraMay 16, 2013
  11. Felipe ContrerasMay 16, 2013
  12. Antoine PelisseMay 16, 2013
  13. Felipe ContrerasMay 16, 2013
  14. 3/3 push: add separate 'downstream' branchFelipe Contreras, May 16, 2013
  15. Junio C HamanoMay 16, 2013
  16. Felipe ContrerasMay 16, 2013
  17. Junio C HamanoMay 16, 2013
  18. Junio C HamanoMay 16, 2013
  19. Ramkumar RamachandraMay 16, 2013
  20. Felipe ContrerasMay 16, 2013
  21. Ramkumar RamachandraMay 16, 2013
  22. Felipe ContrerasMay 16, 2013
  23. Ramkumar RamachandraMay 16, 2013
  24. Felipe ContrerasMay 16, 2013
  25. Ramkumar RamachandraMay 16, 2013
  26. Felipe ContrerasMay 16, 2013
  27. Ramkumar RamachandraMay 16, 2013
  28. Felipe ContrerasMay 16, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.