当我在Git中指定一个祖先提交对象时,我混淆了HEAD^和HEAD~。
两者都有“编号”版本,如HEAD^3和HEAD~2。
在我看来它们非常相似或相同,但是波浪号和插入符号之间有什么不同吗?
当我在Git中指定一个祖先提交对象时,我混淆了HEAD^和HEAD~。
两者都有“编号”版本,如HEAD^3和HEAD~2。
在我看来它们非常相似或相同,但是波浪号和插入符号之间有什么不同吗?
当前回答
HEAD~和HEAD^之间区别的一个实际例子:
其他回答
简单地说:
~指定祖先 ^指定父母
合并时可以指定一个或多个分支。然后提交有两个或多个父节点,然后^用于表示父节点。
假设你在分支A上,还有两个分支:B和C。
在每个分支上的最后三个提交是:
A: a1, a2, a3 B: b1 b2 b3 C: c1 c3 c3
如果现在在分支A上执行命令:
git merge B C
然后你将三个分支合并在一起(这里你的合并提交有三个父分支)
and
~表示第一个分支中的第n个祖先,因此
HEAD~表示A3 HEAD~2表示A2 HEAD~3表示A1
^表示第n个父结点,因此
HEAD^表示A3 HEAD^2表示B3 HEAD^3表示C3
~或^的下一个用法是在前面的字符指定的提交上下文中。
注意1:
HEAD~3总是等于:HEAD~~~和:HEAD^^^(每个表示A1),
和一般:
HEAD~n总是等于:HEAD~…~ (n次~)和to: HEAD^…^ (n乘以^)
注意2:
HEAD^3和HEAD^^^不一样(第一个表示C3,第二个表示A1),
和一般:
HEAD^1和HEAD^是一样的, 但是对于n > 1: HEAD^n总是不等于HEAD^…^ (n乘以^)
值得注意的是,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}。
~和^本身都是指提交的父节点(~~和^^都是指祖父节点提交,等等),但当它们与数字一起使用时,它们的含义有所不同:
~2表示在层次结构中向上两层,如果一个提交有多个父级,则通过第一个父级 ^2表示第二个父节点,其中提交有多个父节点(也就是说,因为它是一个merge)
这些可以组合起来,所以HEAD~2^3意味着HEAD的祖父提交的第三个父提交。
OP:当我在Git中指定一个祖先提交对象时,我混淆了HEAD^和HEAD~。
Git中的HEAD^和HEAD~有什么区别?
HEAD^(插入号)和HEAD~(波浪号)之间的区别在于它们如何从指定的起点向后遍历历史,在这种特殊情况下是HEAD。
波浪号~
<rev>~[<n>] = select <n>第一代祖先
插入符号 ^
<rev>^[<n>] = select <n>第一代祖先的第一个父母
*第一个父节点总是在merge的左边,例如,在被合并到的分支上提交。
把~和^连在一起
如下图所示,两个选择器~和^可以组合使用。还要注意,不使用HEAD作为起点,任何常规引用都可以使用,比如分支、标记甚至是提交散列。
此外,根据要选择的祖先,^和~可以互换使用,如下表所示。
来源:在这篇关于这个主题的博客文章中可以找到一个完整的纲要。
HEAD~和HEAD^之间区别的一个实际例子: