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

[PATCH 7/9] remote.c: teach branch_get() to treat symrefs other than HEAD

From
Ramkumar Ramachandra <artagnon@gmail.com>
Date
May 2, 2013, 13:39 UTC
Message-ID
<1367501974-6879-8-git-send-email-artagnon@gmail.com>
In-Reply-To
<1367501974-6879-1-git-send-email-artagnon@gmail.com>

Broadly, there are two ways to resolve a command-line argument. The first approach is to treat it as a revision and resolve it using the revision-parsing mechanism get_sha1(). The other approach is to treat it as a ref, and use a reduced mechanism like branch_get().

Compare and contrast the implementations of @{N} and @{u} in sha1_name.c to see where exactly branch_get() is useful:

In <...>@{N}, the <...> is passed through dwim_log() which first calls substitute_branch_name() and then resolve_ref_unsafe() on that. The resolved ref could be any ref (symbolic/ non-symbolic), and not just a refs/heads/* ref (branch).

However, in the <...>@{u} case, the <...> can only be a ref/heads/* ref or a symbolic ref pointing to a refs/heads/* ref. It uses branch_get() to find the relevant ref.

Unfortunately, branch_get() doesn't call resolve_ref_unsafe() on what is passed to it at all. Instead it hard-codes the special four-letter word "HEAD" (which is resolved by read_config() which is called first), and rejects any other symbolic ref. This is a historical mistake because of which some callers of branch_get() suffer. To put it another way, the commands that accept "HEAD" (and resolve it into a branch) can benefit from accepting any other symbolic ref that resolves to a branch. For example, the following fail:

    $ git symbolic-ref M refs/heads/master
    $ git show M@{u}
    $ git branch -u ram/master M
This patch fixes branch_get() directly, making these work.

Notice that branch_get() calls read_config(), which in turn preemptively calls resolve_ref_unsafe() on "HEAD", when the caller might not even be requesting the current branch. After copying out two critical tasks that are required for make_remote() to work properly:

    git_config(handle_config, NULL);
    alias_all_urls();

we can remove read_config() and call resolve_ref_unsafe() on the argument that is passed ourselves. HEAD is therefore not a special case anymore.

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 remote.c                   | 23 ++++++++++++++++++++---
 t/t1508-at-combinations.sh |  2 +-
 2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/remote.c b/remote.c
index 68eb99b..3ac302f 100644
--- a/remote.c
+++ b/remote.c
@@ -1463,13 +1463,30 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
 
 struct branch *branch_get(const char *name)
 {
-	struct branch *ret;
+	struct branch *ret = NULL;
+
+	/* Setup */
+	git_config(handle_config, NULL);
+	alias_all_urls();
 
-	read_config();
 	if (!name || !*name || !strcmp(name, "HEAD"))
-		ret = current_branch;
+		name = "HEAD";
 	else
 		ret = make_branch(name, 0);
+
+	if (!ret || !ret->remote_name) {
+		/* Is this a symbolic-ref like HEAD, pointing to a
+		 * valid branch?
+		 */
+		const char *this_ref;
+		unsigned char sha1[20];
+		int flag;
+
+		this_ref = resolve_ref_unsafe(name, sha1, 0, &flag);
+		if (this_ref && (flag & REF_ISSYMREF) &&
+			!prefixcmp(this_ref, "refs/heads/"))
+			ret = make_branch(this_ref + strlen("refs/heads/"), 0);
+	}
 	if (ret && ret->remote_name) {
 		ret->remote = remote_get(ret->remote_name);
 		if (ret->merge_nr) {
diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh
index bb86c79..424caf5 100755
--- a/t/t1508-at-combinations.sh
+++ b/t/t1508-at-combinations.sh
@@ -63,7 +63,7 @@ nonsense "@{-1}@{-1}"
 git symbolic-ref H HEAD
 check "H@{1}" commit new-one
 check "H@{now}" commit new-two
-check "H@{u}" ref refs/heads/upstream-branch failure
+check "H@{u}" refs/heads/upstream-branch
 
 # To make sure that the @-parser isn't buggy, check things with the
 # symbolic-ref @
-- 
1.8.3.rc0.40.g09a0447
Previous: Ramkumar RamachandraNext: Ramkumar Ramachandra
Message 16 of 24 in “A natural solution to the @ -> HEAD problem”
  1. 0/9 A natural solution to the @ -> HEAD problemRamkumar Ramachandra, May 2, 2013
  2. 1/9 t1508 (at-combinations): simplify setupRamkumar Ramachandra, May 2, 2013
  3. 2/9 t1508 (at-combinations): test branches separatelyRamkumar Ramachandra, May 2, 2013
  4. Felipe ContrerasMay 2, 2013
  5. Ramkumar RamachandraMay 2, 2013
  6. Felipe ContrerasMay 2, 2013
  7. 3/9 t1508 (at-combinations): improve nonsense()Ramkumar Ramachandra, May 2, 2013
  8. 4/9 t1508 (at-combinations): increase coverageRamkumar Ramachandra, May 2, 2013
  9. Eric SunshineMay 2, 2013
  10. 5/9 t1508 (at-combinations): document @{N} versus HEAD@{N}Ramkumar Ramachandra, May 2, 2013
  11. Felipe ContrerasMay 2, 2013
  12. Ramkumar RamachandraMay 2, 2013
  13. Felipe ContrerasMay 2, 2013
  14. Ramkumar RamachandraMay 2, 2013
  15. 6/9 t1508 (at-combinations): test with symbolic refsRamkumar Ramachandra, May 2, 2013
  16. 7/9 remote.c: teach branch_get() to treat symrefs other than HEADRamkumar Ramachandra, May 2, 2013
  17. Ramkumar RamachandraMay 2, 2013
  18. Ramkumar RamachandraMay 2, 2013
  19. Felipe ContrerasMay 2, 2013
  20. 8/9 sha1_name.c: fix @-parsing bug in interpret_branch_name()Ramkumar Ramachandra, May 2, 2013
  21. 9/9 refs.c: make @ a pseudo-ref alias to HEADRamkumar Ramachandra, May 2, 2013
  22. Ramkumar RamachandraMay 2, 2013
  23. Felipe ContrerasMay 2, 2013
  24. Ramkumar RamachandraMay 2, 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.