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

[PATCH 5/5] implement @{publish} shorthand

From
Jeff King <peff@peff.net>
Date
Jan 8, 2014, 09:37 UTC
Message-ID
<20140108093716.GE15720@sigill.intra.peff.net>
In-Reply-To
<20140108093338.GA15659@sigill.intra.peff.net>

In a triangular workflow, you may have a distinct @{upstream} that you pull changes from, but publish by default (if you typed "git push") to a different remote (or a different branch on the remote). It may sometimes be useful to be able to quickly refer to that publishing point (e.g., to see which changes you have that have not yet been published).

This patch introduces the <branch>@{publish} shorthand (or "@{pu}" to be even shorter). It refers to the tracking branch of the remote branch to which you would push if you were to push the named branch. That's a mouthful to explain, so here's an example:

  $ git checkout -b foo origin/master
  $ git config remote.pushdefault github
  $ git push
Signed-off-by: Jeff King <peff@peff.net>
---
The implementation feels weird, like the "where do we push to" code
should be factored out from somewhere else. I think what we're doing
here is not _wrong_, but I don't like repeating what "git push" is doing
elsewhere. And I just punt on "simple" as a result. :)
 sha1_name.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)
diff --git a/sha1_name.c b/sha1_name.c
index 50df5d4..59ffa93 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -435,6 +435,12 @@ static inline int upstream_mark(const char *string, int len)
 	return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
 }
 
+static inline int publish_mark(const char *string, int len)
+{
+	const char *suffix[] = { "@{publish}" };
+	return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
+}
+
 static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
 static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf);
 
@@ -481,7 +487,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 					nth_prior = 1;
 					continue;
 				}
-				if (!upstream_mark(str + at, len - at)) {
+				if (!upstream_mark(str + at, len - at) &&
+				    !publish_mark(str + at, len - at)) {
 					reflog_len = (len-1) - (at+2);
 					len = at;
 				}
@@ -1100,6 +1107,69 @@ static int interpret_upstream_mark(const char *name, int namelen,
 	return len + at;
 }
 
+static const char *get_publish_branch(const char *name_buf, int len)
+{
+	char *name = xstrndup(name_buf, len);
+	struct branch *b = branch_get(*name ? name : NULL);
+	struct remote *remote = b->pushremote;
+	const char *dst;
+	const char *track;
+
+	free(name);
+
+	if (!remote)
+		die(_("branch '%s' has no remote for pushing"), b->name);
+
+	/* Figure out what we would call it on the remote side... */
+	if (remote->push_refspec_nr)
+		dst = apply_refspecs(remote->push, remote->push_refspec_nr,
+				     b->refname);
+	else
+		dst = b->refname;
+	if (!dst)
+		die(_("unable to figure out how '%s' would be pushed"),
+		    b->name);
+
+	/* ...and then figure out what we would call that remote here */
+	track = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, dst);
+	if (!track)
+		die(_("%s@{publish} has no tracking branch for '%s'"),
+		    b->name, dst);
+
+	return track;
+}
+
+static int interpret_publish_mark(const char *name, int namelen,
+				  int at, struct strbuf *buf)
+{
+	int len;
+
+	len = publish_mark(name + at, namelen - at);
+	if (!len)
+		return -1;
+
+	switch (push_default) {
+	case PUSH_DEFAULT_NOTHING:
+		die(_("cannot use @{publish} with push.default of 'nothing'"));
+
+	case PUSH_DEFAULT_UNSPECIFIED:
+	case PUSH_DEFAULT_MATCHING:
+	case PUSH_DEFAULT_CURRENT:
+		set_shortened_ref(buf, get_publish_branch(name, at));
+		break;
+
+	case PUSH_DEFAULT_UPSTREAM:
+		set_shortened_ref(buf, get_upstream_branch(name, at));
+		break;
+
+	case PUSH_DEFAULT_SIMPLE:
+		/* ??? */
+		die("@{publish} with simple unimplemented");
+	}
+
+	return at + len;
+}
+
 /*
  * This reads short-hand syntax that not only evaluates to a commit
  * object name, but also can act as if the end user spelled the name
@@ -1150,6 +1220,10 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
 	if (len > 0)
 		return len;
 
+	len = interpret_publish_mark(name, namelen, cp - name, buf);
+	if (len > 0)
+		return len;
+
 	return -1;
 }
 
-- 
1.8.5.2.500.g8060133
Previous: Jeff KingNext: Junio C Hamano
Message 19 of 37 in “format-patch: introduce branch.*.forkedFrom”
  1. format-patch: introduce branch.*.forkedFromRamkumar Ramachandra, Jan 7, 2014
  2. Ramkumar RamachandraJan 7, 2014
  3. Jeff KingJan 7, 2014
  4. Junio C HamanoJan 7, 2014
  5. Ramkumar RamachandraJan 7, 2014
  6. Jeff KingJan 7, 2014
  7. Ramkumar RamachandraJan 7, 2014
  8. 0/5 <branch>@{publish} shorthandJeff King, Jan 8, 2014
  9. 1/5 sha1_name: refactor upstream_markJeff King, Jan 8, 2014
  10. 2/5 interpret_branch_name: factor out upstream handlingJeff King, Jan 8, 2014
  11. Ramkumar RamachandraJan 8, 2014
  12. 3/5 branch_get: return early on errorJeff King, Jan 8, 2014
  13. 4/5 branch_get: provide per-branch pushremote pointersJeff King, Jan 8, 2014
  14. Jeff KingJan 8, 2014
  15. t5531: further "matching" fixupsJeff King, Jan 8, 2014
  16. Junio C HamanoJan 10, 2014
  17. Jeff KingJan 11, 2014
  18. Jeff KingJan 8, 2014
  19. 5/5 implement @{publish} shorthandJeff King, Jan 8, 2014
  20. Junio C HamanoJan 8, 2014
  21. Jeff KingJan 9, 2014
  22. Junio C HamanoJan 9, 2014
  23. Philip OakleyJan 9, 2014
  24. Jeff KingJan 9, 2014
  25. Junio C HamanoJan 9, 2014
  26. Junio C HamanoJan 24, 2014
  27. Jeff KingJan 24, 2014
  28. Ramkumar RamachandraJan 24, 2014
  29. Junio C HamanoJan 24, 2014
  30. Philip OakleyFeb 15, 2014
  31. Jeff KingFeb 18, 2014
  32. Johan HerlandFeb 18, 2014
  33. Junio C HamanoFeb 18, 2014
  34. Ramkumar RamachandraJan 8, 2014
  35. Junio C HamanoJan 7, 2014
  36. Ramkumar RamachandraJan 7, 2014
  37. Junio C HamanoJan 7, 2014

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.