当我在Git中指定一个祖先提交对象时,我混淆了HEAD^和HEAD~。

两者都有“编号”版本,如HEAD^3和HEAD~2。

在我看来它们非常相似或相同,但是波浪号和插入符号之间有什么不同吗?


当前回答

OP:当我在Git中指定一个祖先提交对象时,我混淆了HEAD^和HEAD~。

Git中的HEAD^和HEAD~有什么区别?

HEAD^(插入号)和HEAD~(波浪号)之间的区别在于它们如何从指定的起点向后遍历历史,在这种特殊情况下是HEAD。

波浪号~

<rev>~[<n>] = select <n>第一代祖先

插入符号 ^

<rev>^[<n>] = select <n>第一代祖先的第一个父母

*第一个父节点总是在merge的左边,例如,在被合并到的分支上提交。

把~和^连在一起

如下图所示,两个选择器~和^可以组合使用。还要注意,不使用HEAD作为起点,任何常规引用都可以使用,比如分支、标记甚至是提交散列。

此外,根据要选择的祖先,^和~可以互换使用,如下表所示。

来源:在这篇关于这个主题的博客文章中可以找到一个完整的纲要。

其他回答

^<n>格式允许您选择提交的第n个父节点(与合并相关)。~<n>格式允许您选择第n个祖先提交,始终紧跟在第一个父提交之后。有关一些示例,请参阅git-rev-parse的文档。

HEAD^^^与HEAD~3相同,选择HEAD之前的第三次提交

HEAD^2指定合并提交中的第二个头

我的意见…

HEAD^和HEAD~之间的区别可以通过http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html上的插图(由Jon Loeliger绘制)很好地描述。

这个文档对于初学者来说可能有点晦涩,所以我复制了下面的插图:

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A
A =      = A^0
B = A^   = A^1     = A~1
C = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2

值得注意的是,git还有一个用于跟踪“从哪里来的”/“想要返回-现在”的语法——例如,HEAD@{1}将引用您跳转到新提交位置的位置。

基本上,HEAD@{}变量捕获了HEAD移动的历史,你可以使用git reflog命令查看git的reflogs来决定使用特定的HEAD。

例子:

0aee51f HEAD@{0}: reset: moving to HEAD@{5}
290e035 HEAD@{1}: reset: moving to HEAD@{7}
0aee51f HEAD@{2}: reset: moving to HEAD@{3}
290e035 HEAD@{3}: reset: moving to HEAD@{3}
9e77426 HEAD@{4}: reset: moving to HEAD@{3}
290e035 HEAD@{5}: reset: moving to HEAD@{3}
0aee51f HEAD@{6}: reset: moving to HEAD@{3}
290e035 HEAD@{7}: reset: moving to HEAD@{3}
9e77426 HEAD@{8}: reset: moving to HEAD@{3}
290e035 HEAD@{9}: reset: moving to HEAD@{1}
0aee51f HEAD@{10}: reset: moving to HEAD@{4}
290e035 HEAD@{11}: reset: moving to HEAD^
9e77426 HEAD@{12}: reset: moving to HEAD^
eb48179 HEAD@{13}: reset: moving to HEAD~
f916d93 HEAD@{14}: reset: moving to HEAD~
0aee51f HEAD@{15}: reset: moving to HEAD@{5}
f19fd9b HEAD@{16}: reset: moving to HEAD~1
290e035 HEAD@{17}: reset: moving to HEAD~2
eb48179 HEAD@{18}: reset: moving to HEAD~2
0aee51f HEAD@{19}: reset: moving to HEAD@{5}
eb48179 HEAD@{20}: reset: moving to HEAD~2
0aee51f HEAD@{21}: reset: moving to HEAD@{1}
f916d93 HEAD@{22}: reset: moving to HEAD@{1}
0aee51f HEAD@{23}: reset: moving to HEAD@{1}
f916d93 HEAD@{24}: reset: moving to HEAD^
0aee51f HEAD@{25}: commit (amend): 3rd commmit
35a7332 HEAD@{26}: checkout: moving from temp2_new_br to temp2_new_br
35a7332 HEAD@{27}: commit (amend): 3rd commmit
72c0be8 HEAD@{28}: commit (amend): 3rd commmit

一个例子可以是我做了本地提交a->b->c->d,然后我回去丢弃2个提交来检查我的代码- git重置HEAD~2 -然后在那之后我想把我的HEAD移回d - git重置HEAD@{1}。