{"thread":{"id":"8475","subject":"git does the wrong thing with ambiguous names","startedAt":"2007-06-06T22:13:48Z","lastAt":"2007-06-07T14:54:46Z","messageCount":6,"participants":["Brandon Casey","Alex Riesen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"44201","messageId":"4667319C.9070302@nrlssc.navy.mil","threadId":"8475","inReplyTo":null,"subject":"git does the wrong thing with ambiguous names","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2007-06-06T22:13:48Z","receivedAt":"2007-06-06T22:13:48Z","isPatch":false,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"\nWhen a branch and tag have the same name, a git-checkout using that name \nsucceeds (exits zero without complaining), switches to the _branch_, but \nupdates the working directory contents to that specified by the _tag_. \ngit-status show modified files.\n\nLooks like the ambiguity issue was brought up last year, and git is now \n*supposed* to warn when it encounters an ambiguous name. I agree with \nPetr, it should fail violently, preferably as Josef Weidendorfer \nsuggests also printing out the ambiguous matches so the user can cut and \npaste.\n\nhttp://article.gmane.org/gmane.comp.version-control.git/17720\n\nBut it doesn't, git-checkout.sh redirects stderr on git-rev-parse \n--verify so the message is lost. git-log complains, but most users will \nnever see it since it is pushed off the screen so quickly.\n\nIn another portion of the same thread Junio describes the caveats and \nhis experience:\n\nhttp://article.gmane.org/gmane.comp.version-control.git/16996\n\nThe tag==branch name case is trivial to reproduce and a test script is \nprovided below. It should fail, so it's not really a submission as a \ntest script until this is fixed.\n\n-brandon\n\nps. I was told a previous patch was ws munged. I'm using thunderbird, if \nit happens this time suggestions welcome.\n\n\n\nSigned-off-by: Brandon Casey <casey@nrlssc.navy.mil>\n---\n  t/t2006-checkout-name-clash.sh |   39 \n+++++++++++++++++++++++++++++++++++++++\n  1 files changed, 39 insertions(+), 0 deletions(-)\n  create mode 100755 t/t2006-checkout-name-clash.sh\n\ndiff --git a/t/t2006-checkout-name-clash.sh b/t/t2006-checkout-name-clash.sh\nnew file mode 100755\nindex 0000000..2220578\n--- /dev/null\n+++ b/t/t2006-checkout-name-clash.sh\n@@ -0,0 +1,39 @@\n+#!/bin/sh\n+\n+test_description='git-checkout with tag/branch naming clash\n+\n+This tests whether git does something sane when a tag\n+and a branch have the same name.'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+echo initial >file1 &&\n+echo initial >file2 &&\n+git-add file1 file2 &&\n+git-commit -m initial\n+'\n+\n+test_expect_success 'create modified branch named test' '\n+git-branch test &&\n+git-checkout test &&\n+echo test >file1 &&\n+git-commit -a -m test\n+'\n+\n+test_expect_success 'create tag named test on master branch' '\n+git-checkout master &&\n+git-tag test\n+'\n+\n+test_expect_success 'modify master and commit' '\n+echo master >file2 &&\n+git-commit -a -m master\n+'\n+\n+test_expect_success 'checkout test and check consistency' '\n+git-checkout test &&\n+test \"`git diff-index --name-only HEAD`\" = \"\"\n+'\n+\n+test_done\n-- \n1.5.2.1.126.g6abd0\n"},{"id":"44208","messageId":"20070606225826.GC3969@steel.home","threadId":"8475","inReplyTo":"4667319C.9070302@nrlssc.navy.mil","subject":"Re: git does the wrong thing with ambiguous names","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-06-06T22:58:26Z","receivedAt":"2007-06-06T22:58:26Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Brandon Casey, Thu, Jun 07, 2007 00:13:48 +0200:\n> \n> When a branch and tag have the same name, a git-checkout using that name \n> succeeds (exits zero without complaining), switches to the _branch_, but \n> updates the working directory contents to that specified by the _tag_. \n> git-status show modified files.\n\nBad. To reproduce:\n\nmkdir a && cd a && git init && :> a && git add . && git commit -m1 &&\n:>b && git add . && git commit -m2 && git tag master HEAD^ &&\nfind .git/refs/ && gco -b new && gco master && git status\n\n\n> Looks like the ambiguity issue was brought up last year, and git is now \n> *supposed* to warn when it encounters an ambiguous name. I agree with \n> Petr, it should fail violently, preferably as Josef Weidendorfer \n> suggests also printing out the ambiguous matches so the user can cut and \n> paste.\n> \n\nThat'd be failing friendly :) Very good idea\n"},{"id":"44209","messageId":"20070606233327.GD3969@steel.home","threadId":"8475","inReplyTo":"20070606225826.GC3969@steel.home","subject":"Re: git does the wrong thing with ambiguous names","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-06-06T23:33:27Z","receivedAt":"2007-06-06T23:33:27Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Alex Riesen, Thu, Jun 07, 2007 00:58:26 +0200:\n> Brandon Casey, Thu, Jun 07, 2007 00:13:48 +0200:\n> > \n> > When a branch and tag have the same name, a git-checkout using that name \n> > succeeds (exits zero without complaining), switches to the _branch_, but \n> > updates the working directory contents to that specified by the _tag_. \n> > git-status show modified files.\n> \n> Bad. To reproduce:\n> \n> mkdir a && cd a && git init && :> a && git add . && git commit -m1 &&\n> :>b && git add . && git commit -m2 && git tag master HEAD^ &&\n> find .git/refs/ && gco -b new && gco master && git status\n> \n\ngit-rev-parse actually warns about ambguities:\n\n    $ git-rev-parse --verify master\n    warning: refname 'master' is ambiguous.\n    dd5cdc387f2160bf04d02ac08dfdaf952f769357\n\nIt's just that the warning is thrown away in git-checkout.sh\n\nA quick and _very_ messy fix could like like that:\n\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex 37addb2..3c3bc4e 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -368,6 +368,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tshow_datestring(\"--min-age=\", arg+8);\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--fail-ambiguous\")) {\n+\t\t\t\tfail_ambiguous_refs = 1;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tif (show_flag(arg) && verify)\n \t\t\t\tdie(\"Needed a single revision\");\n \t\t\tcontinue;\ndiff --git a/cache.h b/cache.h\nindex 8a9d1f3..4c532c6 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -279,6 +279,7 @@ extern int assume_unchanged;\n extern int prefer_symlink_refs;\n extern int log_all_ref_updates;\n extern int warn_ambiguous_refs;\n+extern int fail_ambiguous_refs;\n extern int shared_repository;\n extern const char *apply_default_whitespace;\n extern int zlib_compression_level;\ndiff --git a/environment.c b/environment.c\nindex 9d3e5eb..872ab36 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -18,6 +18,7 @@ int prefer_symlink_refs;\n int is_bare_repository_cfg = -1; /* unspecified */\n int log_all_ref_updates = -1; /* unspecified */\n int warn_ambiguous_refs = 1;\n+int fail_ambiguous_refs = 0;\n int repository_format_version;\n const char *git_commit_encoding;\n const char *git_log_output_encoding;\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 6b6facf..4c07fe5 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -57,6 +57,13 @@ while [ \"$#\" != \"0\" ]; do\n \t\tusage\n \t\t;;\n \t*)\n+\t\tif ! git-rev-parse --verify --fail-ambiguous \"$arg^0\" \\\n+\t\t    2>/dev/null\n+\t\tthen\n+\t\t    echo >&2 \"$arg is ambiguous\"\n+\t\t    find \"$GIT_DIR/refs/\" |grep -F \"$arg\"|sed -e 's|.git/|  |'\n+\t\t    exit 1\n+\t\tfi\n \t\tif rev=$(git-rev-parse --verify \"$arg^0\" 2>/dev/null)\n \t\tthen\n \t\t\tif [ -z \"$rev\" ]; then\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 7df01af..d094d41 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -345,6 +345,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n \n \tif (warn_ambiguous_refs && refs_found > 1)\n \t\tfprintf(stderr, warning, len, str);\n+\tif (fail_ambiguous_refs && refs_found > 1) {\n+\t\tfprintf(stderr, \"found %d refs\\n\", refs_found);\n+\t\treturn -1;\n+\t}\n \n \tif (reflog_len) {\n \t\tint nth, i;\n"},{"id":"44210","messageId":"20070607000100.GE3969@steel.home","threadId":"8475","inReplyTo":"20070606233327.GD3969@steel.home","subject":"Re: git does the wrong thing with ambiguous names","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-06-07T00:01:00Z","receivedAt":"2007-06-07T00:01:00Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Alex Riesen, Thu, Jun 07, 2007 01:33:27 +0200:\n> Alex Riesen, Thu, Jun 07, 2007 00:58:26 +0200:\n> > Brandon Casey, Thu, Jun 07, 2007 00:13:48 +0200:\n> > > \n> > > When a branch and tag have the same name, a git-checkout using that name \n> > > succeeds (exits zero without complaining), switches to the _branch_, but \n> > > updates the working directory contents to that specified by the _tag_. \n> > > git-status show modified files.\n> > \n> > Bad. To reproduce:\n> > \n> > mkdir a && cd a && git init && :> a && git add . && git commit -m1 &&\n> > :>b && git add . && git commit -m2 && git tag master HEAD^ &&\n> > find .git/refs/ && gco -b new && gco master && git status\n> > \n> \n> git-rev-parse actually warns about ambguities:\n> \n>     $ git-rev-parse --verify master\n>     warning: refname 'master' is ambiguous.\n>     dd5cdc387f2160bf04d02ac08dfdaf952f769357\n> \n> It's just that the warning is thrown away in git-checkout.sh\n> \n> A quick and _very_ messy fix could like like that:\n> \n\nThis one is much shorter and less friendly. Suggested by Junio on irc.\nIt makes checkout always prefer a branch.\n\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 6b6facf..282c84f 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -67,6 +67,8 @@ while [ \"$#\" != \"0\" ]; do\n \t\t\tnew_name=\"$arg\"\n \t\t\tif git-show-ref --verify --quiet -- \"refs/heads/$arg\"\n \t\t\tthen\n+\t\t\t\trev=$(git-rev-parse --verify \"refs/heads/$arg^0\" 2>/dev/null)\n+\t\t\t\tnew=\"$rev\"\n \t\t\t\tbranch=\"$arg\"\n \t\t\tfi\n \t\telif rev=$(git-rev-parse --verify \"$arg^{tree}\" 2>/dev/null)\n"},{"id":"44245","messageId":"46681932.9060808@nrlssc.navy.mil","threadId":"8475","inReplyTo":"20070607000100.GE3969@steel.home","subject":"Re: git does the wrong thing with ambiguous names","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2007-06-07T14:41:54Z","receivedAt":"2007-06-07T14:41:54Z","isPatch":false,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"Alex Riesen wrote:\n> Alex Riesen, Thu, Jun 07, 2007 01:33:27 +0200:\n>> Alex Riesen, Thu, Jun 07, 2007 00:58:26 +0200:\n>>> Brandon Casey, Thu, Jun 07, 2007 00:13:48 +0200:\n[snip]\n> This one is much shorter and less friendly. Suggested by Junio on irc.\n> It makes checkout always prefer a branch.\n> \n> diff --git a/git-checkout.sh b/git-checkout.sh\n> index 6b6facf..282c84f 100755\n> --- a/git-checkout.sh\n> +++ b/git-checkout.sh\n> @@ -67,6 +67,8 @@ while [ \"$#\" != \"0\" ]; do\n>  \t\t\tnew_name=\"$arg\"\n>  \t\t\tif git-show-ref --verify --quiet -- \"refs/heads/$arg\"\n>  \t\t\tthen\n> +\t\t\t\trev=$(git-rev-parse --verify \"refs/heads/$arg^0\" 2>/dev/null)\n> +\t\t\t\tnew=\"$rev\"\n>  \t\t\t\tbranch=\"$arg\"\n>  \t\t\tfi\n>  \t\telif rev=$(git-rev-parse --verify \"$arg^{tree}\" 2>/dev/null)\n> \n\nThis doesn't work.\n\nNow the working directory contents are never updated when switching \nbranches.\n\nRun my test script, or add an 'echo \"some data\" > a' in your shell code \nso that the two branches have different contents.\n\n-brandon\n"},{"id":"44246","messageId":"46681C36.4060305@nrlssc.navy.mil","threadId":"8475","inReplyTo":"20070606233327.GD3969@steel.home","subject":"Re: git does the wrong thing with ambiguous names","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2007-06-07T14:54:46Z","receivedAt":"2007-06-07T14:54:46Z","isPatch":false,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"Alex Riesen wrote:\n> Alex Riesen, Thu, Jun 07, 2007 00:58:26 +0200:\n>> Brandon Casey, Thu, Jun 07, 2007 00:13:48 +0200:\n>>> When a branch and tag have the same name, a git-checkout using that name \n>>> succeeds (exits zero without complaining), switches to the _branch_, but \n>>> updates the working directory contents to that specified by the _tag_. \n>>> git-status show modified files.\n>> Bad. To reproduce:\n>>\n>> mkdir a && cd a && git init && :> a && git add . && git commit -m1 &&\n>> :>b && git add . && git commit -m2 && git tag master HEAD^ &&\n>> find .git/refs/ && gco -b new && gco master && git status\n>>\n> \n> git-rev-parse actually warns about ambguities:\n> \n>     $ git-rev-parse --verify master\n>     warning: refname 'master' is ambiguous.\n>     dd5cdc387f2160bf04d02ac08dfdaf952f769357\n> \n> It's just that the warning is thrown away in git-checkout.sh\n> \n> A quick and _very_ messy fix could like like that:\n\n[snip patch]\n\nThis one suffers from what Junio described previously on the mailing \nlist, when get_sha1_basic() fails, get_sha1_1() continues trying \nalternatives. The risk is that one of those alternatives could match, \nfor example if the ambiguous branch and tag name is 'dead'.\n\n-brandon\n"}]}