`git checkout ...` 是什么意思?

54

我偶尔会不小心写成git checkout ...,这会使我进入分离头状态。我想知道为什么会这样。以下是"点号故事":

> git checkout .
# checks out current directory
> git checkout ..
# Checks out parent directory, if in repository.
> git checkout ...
# Puts into detached head state?
> git checkout ....
error: pathspec '....' did not match any file(s) known to git.
1个回答

48

这是一个语法的退化形式,在gitrevisions(7)手册页面中有描述:

   <rev1>...<rev2>
       Include commits that are reachable from either <rev1> or <rev2> but
       exclude those that are reachable from both. When either <rev1> or
       <rev2> is omitted, it defaults to HEAD.

请注意最后一句话,“当省略<rev1>或者<rev2>时,默认为HEAD”。这意味着写...等同于HEAD...HEAD。在git checkout中使用时,将会得到HEAD提交的ID。也就是说,你只是执行了以下操作:

git checkout HEAD^{commit}

6
这是正确的,但也有一些微妙之处:Git 在一个名为 get_oid_mb 的函数中实现了这个功能,其中 mb 代表合并基础。它字面上检查三个点 ... 表示法,当存在时,在两侧解析两个修订版本(或使用 HEAD 如注释所述),然后实际上运行 git merge-base --all <rev1> <rev2> 来获取合并基础。如果恰好有一个这样的合并基础,那就是提交;否则 ... 无法解决。 - torek
2
git diff 命令曾经使用相同的技巧:git diff A...B 意味着 git diff $(git merge-base A B) B,我认为可能代码是共享的。现在 git checkout 是唯一使用 get_oid_mb 的用户。所有其他情况都按照文档中描述的方式处理,即不会实际运行等效的 git merge-base --all - torek
3
当我说“所有其他”的时候,我指的是“除了git checkoutgit diff之外的所有内容。git diff中的代码使用了你运行git rev-parse所看到的内部版本:例如运行一个字面上的git rev-parse ...。但是,git diff会以一种目前略微有问题但如果只有一个合并基础则表现良好的方式转换正负参考集。 - torek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接