Re: default behaviour for `gitmerge` (no arguments)

9 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: default behaviour for `gitmerge` (no arguments)

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:00

Jeff King [off-list ref] writes:
Hmm. If we had the oft-discussed-but-never-agreed-upon shorthand for
"the upstream of" then we wouldn't need a special merge option. You
could just do:

  git merge %HEAD ;# (or git merge %, IIRC the proposal correctly)
I don't think "whatever _HEAD_ tracks" makes sense at the semantic level
(i.e. you don't do "branch.HEAD.merge") but a syntax for "whatever the
named _branch_ tracks" with "if a branch is not named, the current branch
is implied" (i.e. the one in parentheses) would.

It is an entirely different matter what the special syntax to trigger that
"upstream-ness" should be.  I vaguely recall @{upstream} or @{u} were the
concensus?

Re: default behaviour for `gitmerge` (no arguments)

From: Jeff King <hidden>
Date: 2016-06-15 22:48:00

On Tue, Jan 12, 2010 at 10:11:26AM -0800, Junio C Hamano wrote:
Jeff King [off-list ref] writes:
quoted
Hmm. If we had the oft-discussed-but-never-agreed-upon shorthand for
"the upstream of" then we wouldn't need a special merge option. You
could just do:

  git merge %HEAD ;# (or git merge %, IIRC the proposal correctly)
I don't think "whatever _HEAD_ tracks" makes sense at the semantic level
(i.e. you don't do "branch.HEAD.merge") but a syntax for "whatever the
named _branch_ tracks" with "if a branch is not named, the current branch
is implied" (i.e. the one in parentheses) would.
The patch that Dscho provided would actually convert HEAD@{upstream}
into the upstream of whatever HEAD pointed at. Which I think makes
sense. We don't do it for reflogs, but that is because it is useful to
distinguish between the reflog for a symref and the thing it points to.
But since one would presumably not make such a configuration for a
symref, that distinction is not useful.
It is an entirely different matter what the special syntax to trigger that
"upstream-ness" should be.  I vaguely recall @{upstream} or @{u} were the
concensus?
Ah, right. I remembered hating "%" even as I typed it, but I had
forgotten about the followup discussion. Looking at it again, I note:

  1. The last posted patch still has a misplaced free() (patch below),
     but I think otherwise is not buggy.

  2. We don't complain on "git show @{usptream}" and we probably should.
     I remember there being some complications because the contents of
     @{} were passed to approxidate, but I think we can get around that
     by letting approxidate complain if _nothing_ in the date was
     useful. So "git show @{2.weeks.and.7.hot.dogs.ago}" would still
     work, but "git show @{totally.bogus.input}" would complain.

  3. I have actually been running with Dscho's patch for the last couple
     of months, and I don't remember using it once. So perhaps it is not
     as useful as I might have thought. :)

Anyway, fixup patch is below. I don't expect you to pick up the topic or
anything, but since I went to the trouble to find the bug once upon a
time, I thought I would post the fix for anybody who does want to pick
it up.
diff --git a/sha1_name.c b/sha1_name.c
index b73b93e..da90ebe 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -275,9 +275,9 @@ static char *substitute_branch_name(const char **string, int *len)
 		char *ref = xstrndup(*string, *len - ret);
 		struct branch *tracking = branch_get(*ref ? ref : NULL);
 
-		free(ref);
 		if (!tracking)
 			die ("No tracking branch found for '%s'", ref);
+		free(ref);
 		if (tracking->merge && tracking->merge[0]->dst) {
 			*string = xstrdup(tracking->merge[0]->dst);
 			*len = strlen(*string);

Re: default behaviour for `gitmerge` (no arguments)

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:00

Jeff King [off-list ref] writes:
Ah, right. I remembered hating "%" even as I typed it, but I had
forgotten about the followup discussion. Looking at it again, I note:

  1. The last posted patch still has a misplaced free() (patch below),
     but I think otherwise is not buggy.

  2. We don't complain on "git show @{usptream}" and we probably should.
     I remember there being some complications because the contents of
     @{} were passed to approxidate, but I think we can get around that
     by letting approxidate complain if _nothing_ in the date was
     useful. So "git show @{2.weeks.and.7.hot.dogs.ago}" would still
     work, but "git show @{totally.bogus.input}" would complain.

  3. I have actually been running with Dscho's patch for the last couple
     of months, and I don't remember using it once. So perhaps it is not
     as useful as I might have thought. :)
I presume we are discussing this patch?

    http://article.gmane.org/gmane.comp.version-control.git/128121

I'll squash the free() fix; thanks.

I wondered why it doesn't hook into interpret_branch_name(), and instead
adds itself to the static substitute_branch_name(); it forbids the use of
the syntax from by callers of strbuf_branchname().

I agree with your point #2 above.

Regarding your point #3, I don't think the notation should be that useful
if your workflow is sane.  The original use case that triggered the
resurrection of the patch went like this:

        git fetch &&
        for local in my set of local branches
        do
                git checkout $local &&
                git merge $local@{upstream} || {
                        echo failed to merge on $local
                        break
                }
        done

and the new notation might look useful in the scenario.  But the thing is,
constantly merging with the other side, even if you haven't added anything
of value since you merged from there last time, is a bad practice to begin
with.  I added one use case that is sane _and_ will be helped by the new
notation to the rewritten version of Dscho's patch (below).

Just to refresh our memory from the old thread and make sure we are
discussing the same patch, here is what I am planning to queue.  The log
message and documentation are somewhat updated to avoid the word "track"
because it seems that everybody gets confused and starts talking different
things whenever that word is used.  For the same reason, the test script
was renamed.

In this set-up, for example:

    [remote "filfre"]
        url = ...
        fetch = +refs/heads/nitfol:refs/heads/rezrov
    [branch "frotz"]
        remote = filfre
        merge = refs/heads/nitfol

some people say rezrov tracks nitfol from filfre but Dscho's patch says
frotz tracks nitfol from filfre.  They _may_ both track, but they "track"
the other in a quite differently way, so the word has become meaningless.

I've been trying to be careful and used different words to disambiguate
whenever I had to talk about these concepts:

 - The purpose of rezrov is to keep a tab on the progress of the nitfol
   branch at the remote end.  We say rezrov is a remote tracking branch
   for nitfol from filfre.

 - On the other hand, we have branch frotz that forked from nitfol that
   came from filfre.  It builds on top of that history by occasionally
   merging with it at key points in the history.  So we say frotz builds
   on top of nitfol from filfre.  We also say nitfol at filfre is the
   upstream of frotz.

-- >8 --
Date: Thu, 10 Sep 2009 17:25:57 +0200
Subject: [PATCH] Introduce <branch>@{upstream} notation

A new notation '<branch>@{upstream}' refers to the branch <branch> is set
to build on top of.  Missing <branch> (i.e. '@{upstream}') defaults to the
current branch.

This allows you to run, for example,

	for l in list of local branches
	do
		git log --oneline --left-right $l...$l@{upstream}
	done

to inspect each of the local branches you are interested in for the
divergence from its upstream.

Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
---
 Documentation/git-rev-parse.txt |    4 ++
 sha1_name.c                     |   39 ++++++++++++++++++++--
 t/t1506-rev-parse-upstream.sh   |   69 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 109 insertions(+), 3 deletions(-)
 create mode 100755 t/t1506-rev-parse-upstream.sh
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 82045a2..923b56a 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -231,6 +231,10 @@ when you run 'git-merge'.
 * The special construct '@\{-<n>\}' means the <n>th branch checked out
   before the current one.
 
+* The suffix '@{upstream}' to a ref (short form 'ref@{u}') refers to
+  the branch the ref is set to build on top of.  Missing ref defaults
+  to the current branch.
+
 * A suffix '{caret}' to a revision parameter means the first parent of
   that commit object.  '{caret}<n>' means the <n>th parent (i.e.
   'rev{caret}'
diff --git a/sha1_name.c b/sha1_name.c
index 44bb62d..fb4e214 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -5,6 +5,7 @@
 #include "blob.h"
 #include "tree-walk.h"
 #include "refs.h"
+#include "remote.h"
 
 static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
 {
@@ -238,9 +239,24 @@ static int ambiguous_path(const char *path, int len)
 	return slash;
 }
 
+static inline int tracked_suffix(const char *string, int len)
+{
+	const char *suffix[] = { "@{upstream}", "@{u}" };
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(suffix); i++) {
+		int suffix_len = strlen(suffix[i]);
+		if (len >= suffix_len && !memcmp(string + len - suffix_len,
+					suffix[i], suffix_len))
+			return suffix_len;
+	}
+	return 0;
+}
+
 /*
  * *string and *len will only be substituted, and *string returned (for
- * later free()ing) if the string passed in is of the form @{-<n>}.
+ * later free()ing) if the string passed in is of the form @{-<n>} or
+ * of the form <branch>@{upstream}.
  */
 static char *substitute_branch_name(const char **string, int *len)
 {
@@ -254,6 +270,21 @@ static char *substitute_branch_name(const char **string, int *len)
 		return (char *)*string;
 	}
 
+	ret = tracked_suffix(*string, *len);
+	if (ret) {
+		char *ref = xstrndup(*string, *len - ret);
+		struct branch *tracking = branch_get(*ref ? ref : NULL);
+
+		if (!tracking)
+			die ("No tracking branch found for '%s'", ref);
+		free(ref);
+		if (tracking->merge && tracking->merge[0]->dst) {
+			*string = xstrdup(tracking->merge[0]->dst);
+			*len = strlen(*string);
+			return (char *)*string;
+		}
+	}
+
 	return NULL;
 }
 
@@ -340,8 +371,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 	if (len && str[len-1] == '}') {
 		for (at = len-2; at >= 0; at--) {
 			if (str[at] == '@' && str[at+1] == '{') {
-				reflog_len = (len-1) - (at+2);
-				len = at;
+				if (!tracked_suffix(str + at, len - at)) {
+					reflog_len = (len-1) - (at+2);
+					len = at;
+				}
 				break;
 			}
 		}
diff --git a/t/t1506-rev-parse-upstream.sh b/t/t1506-rev-parse-upstream.sh
new file mode 100755
index 0000000..5abdc13
--- /dev/null
+++ b/t/t1506-rev-parse-upstream.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='test <branch>@{upstream} syntax'
+
+. ./test-lib.sh
+
+
+test_expect_success 'setup' '
+
+	test_commit 1 &&
+	git checkout -b side &&
+	test_commit 2 &&
+	git checkout master &&
+	git clone . clone &&
+	test_commit 3 &&
+	(cd clone &&
+	 test_commit 4 &&
+	 git branch --track my-side origin/side)
+
+'
+
+full_name () {
+	(cd clone &&
+	 git rev-parse --symbolic-full-name "$@")
+}
+
+commit_subject () {
+	(cd clone &&
+	 git show -s --pretty=format:%s "$@")
+}
+
+test_expect_success '@{upstream} resolves to correct full name' '
+	test refs/remotes/origin/master = "$(full_name @{upstream})"
+'
+
+test_expect_success '@{u} resolves to correct full name' '
+	test refs/remotes/origin/master = "$(full_name @{u})"
+'
+
+test_expect_success 'my-side@{upstream} resolves to correct full name' '
+	test refs/remotes/origin/side = "$(full_name my-side@{u})"
+'
+
+test_expect_success 'my-side@{u} resolves to correct commit' '
+	git checkout side &&
+	test_commit 5 &&
+	(cd clone && git fetch) &&
+	test 2 = "$(commit_subject my-side)" &&
+	test 5 = "$(commit_subject my-side@{u})"
+'
+
+test_expect_success 'not-tracking@{u} fails' '
+	test_must_fail full_name non-tracking@{u} &&
+	(cd clone && git checkout --no-track -b non-tracking) &&
+	test_must_fail full_name non-tracking@{u}
+'
+
+test_expect_success '<branch>@{u}@{1} resolves correctly' '
+	test_commit 6 &&
+	(cd clone && git fetch) &&
+	test 5 = $(commit_subject my-side@{u}@{1})
+'
+
+test_expect_success '@{u} without specifying branch fails on a detached HEAD' '
+	git checkout HEAD^0 &&
+	test_must_fail git rev-parse @{u}
+'
+
+test_done
-- 
1.6.6.280.ge295b7.dirty

Re: default behaviour for `gitmerge` (no arguments)

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:48:00

Hi,

On Tue, 12 Jan 2010, Junio C Hamano wrote:
I wondered why it doesn't hook into interpret_branch_name(), and instead 
adds itself to the static substitute_branch_name(); it forbids the use 
of the syntax from by callers of strbuf_branchname().
I _think_ it was to allow something like

	git log -g @{u}

but frankly, this is so long ago, I do not remember, I reconstructed this 
reasoning as being the most likely.

Ciao,
Dscho

[PATCH 0/2] @{u} updates

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:04

Earlier I wondered if the approach Dscho's patch takes to teach the new
@{upstream} syntax to substitute_branch_name() (hence dwim_ref()) without
teaching it to interpret_branch_name() (hence strbuf_branchname()) was a
bad idea.  I thought about this a bit more; there are some downsides for
not doing so.

The first patch adds a handful of tests that show why strbuf_branchname()
callers may also want to learn about the new syntax.  The second patch
moves the logic to interpret_branch_name() to make them happier.

The name of the key function was changed from tracked_suffix() to
upstream_mark(), not only because the syntax talks about @{upstream}, but
because the parsing needs to recognize the @{u}/@{upstream} mark at the
beginning of the given string (that is a suffix to some other string), and
strip it (the earlier code wanted @{u} to be at the very end but the
callers need to have it at the beginning).


Junio C Hamano (2):
  t1506: more test for @{upstream} syntax
  Teach @{upstream} syntax to strbuf_branchanme()

 sha1_name.c                   |  116 ++++++++++++++++++++++++++---------------
 t/t1506-rev-parse-upstream.sh |   41 ++++++++++++++
 2 files changed, 115 insertions(+), 42 deletions(-)

[PATCH 1/2] t1506: more test for @{upstream} syntax

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:04

This adds a few more tests that exercises @{upstream} syntax by commands
that operate differently when they are given branch name as opposed to a
refname (i.e. where "master" and "refs/heads/master" makes a difference).

Signed-off-by: Junio C Hamano <redacted>
---
 t/t1506-rev-parse-upstream.sh |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/t/t1506-rev-parse-upstream.sh b/t/t1506-rev-parse-upstream.sh
index 5abdc13..a2c7f92 100755
--- a/t/t1506-rev-parse-upstream.sh
+++ b/t/t1506-rev-parse-upstream.sh
@@ -66,4 +66,45 @@ test_expect_success '@{u} without specifying branch fails on a detached HEAD' '
 	test_must_fail git rev-parse @{u}
 '
 
+test_expect_success 'checkout -b new my-side@{u} forks from the same' '
+(
+	cd clone &&
+	git checkout -b new my-side@{u} &&
+	git rev-parse --symbolic-full-name my-side@{u} >expect &&
+	git rev-parse --symbolic-full-name new@{u} >actual &&
+	test_cmp expect actual
+)
+'
+
+test_expect_failure 'merge my-side@{u} records the correct name' '
+(
+	sq="'\''" &&
+	cd clone || exit
+	git checkout master || exit
+	git branch -D new ;# can fail but is ok
+	git branch -t new my-side@{u} &&
+	git merge -s ours new@{u} &&
+	git show -s --pretty=format:%s >actual &&
+	echo "Merge remote branch ${sq}origin/side${sq}" >expect &&
+	test_cmp expect actual
+)
+'
+
+test_expect_failure 'branch -d other@{u}' '
+	git checkout -t -b other master &&
+	git branch -d @{u} &&
+	git for-each-ref refs/heads/master >actual &&
+	>expect &&
+	test_cmp expect actual
+'
+
+test_expect_failure 'checkout other@{u}' '
+	git branch -f master HEAD &&
+	git checkout -t -b another master &&
+	git checkout @{u} &&
+	git symbolic-ref HEAD >actual &&
+	echo refs/heads/master >expect &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.6.6.513.g63f4c

[PATCH 2/2] Teach @{upstream} syntax to strbuf_branchanme()

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:04

This teaches @{upstream} syntax to interpret_branch_name(), instead
of dwim_ref() machinery.

There are places in git UI that behaves differently when you give a local
branch name and when you give an extended SHA-1 expression that evaluates
to the commit object name at the tip of the branch.  The intent is that
the special syntax such as @{-1} can stand in as if the user spelled the
name of the branch in such places.

The name of the branch "frotz" to switch to ("git checkout frotz"), and
the name of the branch "nitfol" to fork a new branch "frotz" from ("git
checkout -b frotz nitfol"), are examples of such places.  These places
take only the name of the branch (e.g. "frotz"), and they are supposed to
act differently to an equivalent refname (e.g. "refs/heads/frotz"), so
hooking the @{upstream} and @{-N} syntax to dwim_ref() is insufficient
when we want to deal with cases a local branch is forked from another
local branch and use "forked@{upstream}" to name the forkee branch.

The "upstream" syntax "forked@{u}" is to specify the ref that "forked" is
configured to merge with, and most often the forkee is a remote tracking
branch, not a local branch.  We cannot simply return a local branch name,
but that does not necessarily mean we have to returns the full refname
(e.g. refs/remotes/origin/frotz, when returning origin/frotz is enough).
This update calls shorten_unambiguous_ref() to do so.

Signed-off-by: Junio C Hamano <redacted>
---
 sha1_name.c                   |  116 ++++++++++++++++++++++++++---------------
 t/t1506-rev-parse-upstream.sh |    6 +-
 2 files changed, 77 insertions(+), 45 deletions(-)
diff --git a/sha1_name.c b/sha1_name.c
index fb4e214..2376c6d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -239,24 +239,10 @@ static int ambiguous_path(const char *path, int len)
 	return slash;
 }
 
-static inline int tracked_suffix(const char *string, int len)
-{
-	const char *suffix[] = { "@{upstream}", "@{u}" };
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(suffix); i++) {
-		int suffix_len = strlen(suffix[i]);
-		if (len >= suffix_len && !memcmp(string + len - suffix_len,
-					suffix[i], suffix_len))
-			return suffix_len;
-	}
-	return 0;
-}
-
 /*
  * *string and *len will only be substituted, and *string returned (for
- * later free()ing) if the string passed in is of the form @{-<n>} or
- * of the form <branch>@{upstream}.
+ * later free()ing) if the string passed in is a magic short-hand form
+ * to name a branch.
  */
 static char *substitute_branch_name(const char **string, int *len)
 {
@@ -270,21 +256,6 @@ static char *substitute_branch_name(const char **string, int *len)
 		return (char *)*string;
 	}
 
-	ret = tracked_suffix(*string, *len);
-	if (ret) {
-		char *ref = xstrndup(*string, *len - ret);
-		struct branch *tracking = branch_get(*ref ? ref : NULL);
-
-		if (!tracking)
-			die ("No tracking branch found for '%s'", ref);
-		free(ref);
-		if (tracking->merge && tracking->merge[0]->dst) {
-			*string = xstrdup(tracking->merge[0]->dst);
-			*len = strlen(*string);
-			return (char *)*string;
-		}
-	}
-
 	return NULL;
 }
 
@@ -354,6 +325,20 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
 	return logs_found;
 }
 
+static inline int upstream_mark(const char *string, int len)
+{
+	const char *suffix[] = { "@{upstream}", "@{u}" };
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(suffix); i++) {
+		int suffix_len = strlen(suffix[i]);
+		if (suffix_len <= len
+		    && !memcmp(string, suffix[i], suffix_len))
+			return suffix_len;
+	}
+	return 0;
+}
+
 static int get_sha1_1(const char *name, int len, unsigned char *sha1);
 
 static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
@@ -371,7 +356,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 	if (len && str[len-1] == '}') {
 		for (at = len-2; at >= 0; at--) {
 			if (str[at] == '@' && str[at+1] == '{') {
-				if (!tracked_suffix(str + at, len - at)) {
+				if (!upstream_mark(str + at, len - at)) {
 					reflog_len = (len-1) - (at+2);
 					len = at;
 				}
@@ -773,17 +758,10 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
 }
 
 /*
- * This reads "@{-N}" syntax, finds the name of the Nth previous
- * branch we were on, and places the name of the branch in the given
- * buf and returns the number of characters parsed if successful.
- *
- * If the input is not of the accepted format, it returns a negative
- * number to signal an error.
- *
- * If the input was ok but there are not N branch switches in the
- * reflog, it returns 0.
+ * Parse @{-N} syntax, return the number of characters parsed
+ * if successful; otherwise signal an error with negative value.
  */
-int interpret_branch_name(const char *name, struct strbuf *buf)
+static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf)
 {
 	long nth;
 	int i, retval;
@@ -828,6 +806,60 @@ release_return:
 }
 
 /*
+ * 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
+ * of the branch from the command line.
+ *
+ * - "@{-N}" finds the name of the Nth previous branch we were on, and
+ *   places the name of the branch in the given buf and returns the
+ *   number of characters parsed if successful.
+ *
+ * - "<branch>@{upstream}" finds the name of the other ref that
+ *   <branch> is configured to merge with (missing <branch> defaults
+ *   to the current branch), and places the name of the branch in the
+ *   given buf and returns the number of characters parsed if
+ *   successful.
+ *
+ * If the input is not of the accepted format, it returns a negative
+ * number to signal an error.
+ *
+ * If the input was ok but there are not N branch switches in the
+ * reflog, it returns 0.
+ */
+int interpret_branch_name(const char *name, struct strbuf *buf)
+{
+	char *cp;
+	struct branch *upstream;
+	int namelen = strlen(name);
+	int len = interpret_nth_prior_checkout(name, buf);
+	int tmp_len;
+
+	if (!len)
+		return len; /* syntax Ok, not enough switches */
+	if (0 < len)
+		return len; /* consumed from the front */
+	cp = strchr(name, '@');
+	if (!cp)
+		return -1;
+	tmp_len = upstream_mark(cp, namelen - (cp - name));
+	if (!tmp_len)
+		return -1;
+	len = cp + tmp_len - name;
+	cp = xstrndup(name, cp - name);
+	upstream = branch_get(*cp ? cp : NULL);
+	if (!upstream
+	    || !upstream->merge
+	    || !upstream->merge[0]->dst)
+		return error("No upstream branch found for '%s'", cp);
+	free(cp);
+	cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
+	strbuf_reset(buf);
+	strbuf_addstr(buf, cp);
+	free(cp);
+	return len;
+}
+
+/*
  * This is like "get_sha1_basic()", except it allows "sha1 expressions",
  * notably "xyz^" for "parent of xyz"
  */
diff --git a/t/t1506-rev-parse-upstream.sh b/t/t1506-rev-parse-upstream.sh
index a2c7f92..95c9b09 100755
--- a/t/t1506-rev-parse-upstream.sh
+++ b/t/t1506-rev-parse-upstream.sh
@@ -76,7 +76,7 @@ test_expect_success 'checkout -b new my-side@{u} forks from the same' '
 )
 '
 
-test_expect_failure 'merge my-side@{u} records the correct name' '
+test_expect_success 'merge my-side@{u} records the correct name' '
 (
 	sq="'\''" &&
 	cd clone || exit
@@ -90,7 +90,7 @@ test_expect_failure 'merge my-side@{u} records the correct name' '
 )
 '
 
-test_expect_failure 'branch -d other@{u}' '
+test_expect_success 'branch -d other@{u}' '
 	git checkout -t -b other master &&
 	git branch -d @{u} &&
 	git for-each-ref refs/heads/master >actual &&
@@ -98,7 +98,7 @@ test_expect_failure 'branch -d other@{u}' '
 	test_cmp expect actual
 '
 
-test_expect_failure 'checkout other@{u}' '
+test_expect_success 'checkout other@{u}' '
 	git branch -f master HEAD &&
 	git checkout -t -b another master &&
 	git checkout @{u} &&
-- 
1.6.6.513.g63f4c

Re: [PATCH 0/2] @{u} updates

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:48:04

Hi,

On Wed, 20 Jan 2010, Junio C Hamano wrote:
Earlier I wondered if the approach Dscho's patch takes to teach the new
@{upstream} syntax to substitute_branch_name() (hence dwim_ref()) without
teaching it to interpret_branch_name() (hence strbuf_branchname()) was a
bad idea.  I thought about this a bit more; there are some downsides for
not doing so.

The first patch adds a handful of tests that show why strbuf_branchname()
callers may also want to learn about the new syntax.  The second patch
moves the logic to interpret_branch_name() to make them happier.
Looks good to me.

Ciao,
Dscho

Re: [PATCH 1/2] t1506: more test for @{upstream} syntax

From: Jeff King <hidden>
Date: 2016-06-15 22:48:06

On Wed, Jan 20, 2010 at 01:38:41AM -0800, Junio C Hamano wrote:
This adds a few more tests that exercises @{upstream} syntax by commands
that operate differently when they are given branch name as opposed to a
refname (i.e. where "master" and "refs/heads/master" makes a difference).
Overall this looks good, but there are a few minor defects. I haven't
had a chance to fix them yet, but here are tests showing them. I hope to
get to them pre-1.7.0, but please feel free to take a crack at them if
you want.

The first one is that @{usptream} silently becomes @{0}. I think
we need to double-check whether approxidate found absolutely nothing,
and complain if that is the case.
diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh
new file mode 100755
index 0000000..da43386
--- /dev/null
+++ b/t/t0101-at-syntax.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+test_description='various @{whatever} syntax tests'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	test_commit one &&
+	test_commit two
+'
+
+check_at() {
+	echo "$2" >expect &&
+	git log -1 --format=%s "$1" >actual &&
+	test_cmp expect actual
+}
+
+test_expect_success '@{0} shows current' '
+	check_at @{0} two
+'
+
+test_expect_success '@{1} shows old' '
+	check_at @{1} one
+'
+
+test_expect_success '@{now} shows current' '
+	check_at @{now} two
+'
+
+test_expect_success '@{30.years.ago} shows old' '
+	check_at @{30.years.ago} one
+'
+
+test_expect_success 'silly approxidates work' '
+	check_at @{3.hot.dogs.and.30.years.ago} one
+'
+
+test_expect_failure 'complain about total nonsense' '
+	test_must_fail git log -1 --format=%s @{utter.bogosity}
+'
+
+test_done
The second one is that "log -g branch@{u}" shows the correct commits
(from the upstream of "branch"), but displays the incorrect reflog
information (it shows information for "branch", not for its upstream).
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index 95c9b09..cbe1b25 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -107,4 +107,18 @@ test_expect_success 'checkout other@{u}' '
 	test_cmp expect actual
 '
 
+cat >expect <<EOF
+commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
+Reflog: refs/heads/master@{0} (C O Mitter <committer@example.com>)
+Reflog message: branch: Created from HEAD
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:15:13 2005 -0700
+
+    3
+EOF
+test_expect_failure 'log -g other@{u}' '
+	git log -1 -g other@{u} >actual &&
+	test_cmp expect actual
+'
+
 test_done
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help