Refname不明确

昨天,我从一个分支创建了一个分支,将其推送到原点,然后将其合并回 master。你可以在这里看到:

$ history |less
 8358  git co master
 8359   commit # shortcut that adds all and commits
 8360  push # shortcut that `git push`'s
 8361  git lg # shortcut that logs my output
 8362  git co 1600
 8363  git co -b 1601
 8364  npm run test
 8365  npm run test
 8366  npm run test
 8367  npm run test
 8368  npm run test
 8369  npm run test
 8370  npm run test
 8371  npm run test
 8372  npm run test
 8373  npm run test
 8374  npm run test
 8375  npm run test
 8376  npm run test
 8377  ./release.sh
 8378  ./release.sh
 8379  commit
 8380  push
 8381      git push --set-upstream origin 1601
 8382  git lg
 8383  git co master
 8384  git merge --no-ff -
 8385  git st
 8386  commit 
 8387  push 
$ history |less
 8358  git co master
 8359   commit # shortcut that adds all and commits
 8360  push # shortcut that `git push`'s
 8361  git lg # shortcut that logs my output
 8362  git co 1600
 8363  git co -b 1601
 8364  npm run test
 8365  npm run test
 8366  npm run test
 8367  npm run test
 8368  npm run test
 8369  npm run test
 8370  npm run test
 8371  npm run test
 8372  npm run test
 8373  npm run test
 8374  npm run test
 8375  npm run test
 8376  npm run test
 8377  ./release.sh
 8378  ./release.sh
 8379  commit
 8380  push
 8381      git push --set-upstream origin 1601
 8382  git lg
 8383  git co master
 8384  git merge --no-ff -
 8385  git st
 8386  commit 
 8387  push 

我在这个列表中包含了不相关的东西,所以我不会意外地删掉一些相关的东西;如您所见,所有这些历史都是连续的。以下是我历史上所有与 1601 相关的内容:

不知何故,在这些步骤之后,无论何时git co 1601,它都会给我这个警告:

$ history | grep 1601
 1601  npm run test
 8363  git co -b 1601
 8381      git push --set-upstream origin 1601
 8438  git co 1601
 8445  git co 1601
 8446  git show-ref 1601
 8447  history | grep 1601
 8449  git show-ref | grep 1601
 8458  git show-ref --heads --tags | grep 1601
 8460  history | grep 1601
 8461  history | grep (1601|merge)
 8462  history | grep -p (1601|merge)
 8464  history | grep -E (1601|merge)
 8466  history | grep -E -e (1601|merge)
 8467  history | grep -E -e (1601|merge)
 8468  history | grep -E -e '(1601|merge)'
 8469  history | grep -E -e '(1601|merge|master)'
 8470  history | grep -E -e '(1601|1601|merge|master)'
 8472  history | grep -E -e '(1601|1601|merge|master)'
 8474  history | grep -E -e '(1601|1601|merge|master)'
 8480  history | grep 1601

我已经在谷歌上搜索了一段时间,寻找其他有这个问题的人,但他们似乎都没有同样的情况。这是我看过的没有帮助的内容:

  1. Git 警告:refname 'xxx' 不明确
  2. Git:refname 'master' 不明确
  3. git refname 'origin/master' 不明确
  4. http://thesimplesynthesis.com/post/git-error-warning-refname-originbranch-name-is-ambiguous

以下输出有助于排除故障:

$ git co 1601
warning: refname '1601' is ambiguous.
Already on '1601'
Your branch is up to date with 'origin/1601'.
$ git show-ref | grep 1601
137b74c8ff6807f07bb32ba0d2f76a3ba287e981 refs/heads/1601
137b74c8ff6807f07bb32ba0d2f76a3ba287e981 refs/remotes/origin/1601
$ git tag -l

cat .git/config
# this is the only place where it mentions 1601
[branch "1601"]
        remote = origin
        merge = refs/heads/1601

$ cat .git/config | grep 1601
[branch "1601"]
        merge = refs/heads/1601

$ git show-ref --heads --tags | grep 1601
137b74c8ff6807f07bb32ba0d2f76a3ba287e981 refs/heads/1601
cat .git/config
# this is the only place where it mentions 1601
[branch "1601"]
        remote = origin
        merge = refs/heads/1601

$ cat .git/config | grep 1601
[branch "1601"]
        merge = refs/heads/1601

$ git checkout 1601 --
warning: refname '1601' is ambiguous.
Already on '1601'
Your branch is up to date with 'origin/1601'.
$ git ls-remote . *1601*
beea6ee68d6fe6b4f5222c0efe0e206e23af993c        refs/heads/1601
beea6ee68d6fe6b4f5222c0efe0e206e23af993c        refs/remotes/origin/1601
$ git show 1601 # this only shows one log message
warning: refname '1601' is ambiguous.
commit beea6ee68d6fe6b4f5222c0efe0e206e23af993c (HEAD -> 1601, origin/1601)
...

FWIW,我在 Windows 上使用 cygwin。

为什么我会收到此警告,如何摆脱它,以及如何在将来防止它?

回答

我可以通过为分支提供与提交的 SHA1 前缀匹配的名称来获得此行为。

$ git rev-list @ | egrep '^[0-9]{4}'
7802d6937673dbff4d26dc906c714a054c9e883e
81070af68e1b254c7f36eccb1261050a5a4a133a
7537dac08fd165845b6300f32c19a52fc7fa7299
$ git branch 7802
$ git branch 9999
$ git checkout 7802
warning: refname '7802' is ambiguous.
Switched to branch '7802'
$ git checkout 9999
Switched to branch '9999'
$

由于对象 id 前缀至少有四位数字是引用对象的合法方式,因此将引用名称设为四位或更多长的十六进制字符串很可能会产生这种歧义。所以,不要那样做。如果你想给一些东西编号,包括一个类型标记,像bugfix/1601什么的。

  • @DanielKaplan I think yes, or, you could also shorten your branch names to 3 numbers instead of 4, since you need at least 4 characters to reference a commit ID. I generally prefer more descriptive branch names anyway, but in your case, even something like `test-1600`, `build-1600`, `z1600`, or whatever makes sense there, would alleviate the problem.
  • Wow! thank you for all the effort you put into this. `Why am I getting this warning, how do I get rid of it, and how do I prevent it in the future?` I now understand why, is the only way to get rid of it to rename my branches and put a character in it that isn't valid in a sha?

回答

为什么我会收到此警告...

正如您通过jthill's answer 发现的那样,这是因为1601匹配了一些合适的对象的哈希值。

还有一些其他方法可以获得相同的错误,包括创建具有相同拼写的分支和标记名称(例如,git branch abc; git tag abc)。

我该如何摆脱它...

使用明确的名称。对于 branch-vs-tag,这意味着不要使用与分支和标签名称相同的名称;对于分支或标签与提交哈希,这意味着避免此处可能出现的提交哈希名称。正如TTT 评论的那样,提交哈希缩写必须至少包含四个字符,因此abc即使abc在哈希 ID 中所有三个字符都是合法的,也可以作为分支或标记名称。

要查看分支名称是否可能与哈希 ID 冲突,请检查它是否完全由集合中的字符组成,[0-9][a-f][A-F]并且长度至少为四个字符。如果是这样,请添加一些字符集之外的字符,或缩短名称。快速:

egrep '^[a-f]{4,}$' /usr/share/dict/words

会出现一些有趣的分支名称以避免出现,例如accede, aface, beaded, deed, 和facade。(这些当然是我喜欢作为例子,如使用各种假散列ID的来源feedc0ffeedeadbeefcafedad,等等-一些需要比特11ce45e1与拼写。)

以及我将来如何防止它?

一个非常方便的系统是系统化的分支名称,包括/-或东西:例如,feature/c0ffee从来没有运行到这样的问题。


1 “许可证”,有点类似于 1337-5p34k。


回答

为什么我会收到此警告,如何摆脱它,以及如何在将来防止它?

首先,确保使用git switch,而不是旧的过时且令人困惑的 git checkout 命令。

其次,即使使用git switch,您也会收到警告(即使您已经在该分支上!):

vonc@vclp MINGW64 ~/git/test (29876e)
$ git switch -- 29876e
warning: refname '29876e' is ambiguous.
Already on '29876e'

但是设置core.warnAmbiguousRefsfalse实际上会消除该警告。

$ git -c core.warnAmbiguousRefs=false switch 29876e
Already on '29876e' 

  • Switch is just an alternative, it's not obsolete nor deprecated and most likely not present in any of older manuals/articles/tutorials + has zero benefit for this problem.

回答

如果您知道ref-name 是一个分支或一个标签,您可以在 id 前加上heads/tags/。所以这有效:

git checkout heads/1601

鉴于<refname>Git 搜索位置列表。这是根据git help revisions页面的列表:

  1. 如果$GIT_DIR/<refname>存在,那就是你的意思(这通常只对HEAD, FETCH_HEAD, ORIG_HEAD,MERGE_HEAD和有用CHERRY_PICK_HEAD);

  2. 否则,refs/<refname>如果存在;

  3. 否则,refs/tags/<refname>如果存在;

  4. 否则,refs/heads/<refname>如果存在;

  5. 否则,refs/remotes/<refname>如果存在;

  6. 否则,refs/remotes/<refname>/HEAD如果它存在。

因此,即使您有一个带有名称的分支tags/1601也可以通过说refs/heads/tags/1601.


以上是Refname不明确的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>