Git中HEAD ^和HEAD〜有什么区别?

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

两者都有一个“编号”的版本,像HEAD^3HEAD~2

他们对我来说看起来很相似或相同,但在代字和插入符号之间是否有区别?

HEAD^表示当前分支顶端的第一个父项。

请记住,git提交可以有多个父代。 HEAD^HEAD^1缩写,您也可以根据需要定位HEAD^2等等。

你可以到任何提交的父母,而不仅仅是HEAD 。 你也可以代代相传:例如, master~2表示master分支的祖父母,在含糊不清的情况下赞成第一个父母。 这些说明符可以任意链接, 例如 topic~3^2

有关完整的详细信息,请参阅git rev-parse文档中的“指定修订” 。

要有一个可视化的想法表示,让我们引用一部分文档:

这是由Jon Loeliger提供的一个例子。 提交节点B和C都是提交节点A的父节点。父提交按从左到右的顺序排列。

 GHIJ \ / \ / DEF \ | / \ \ | / | \|/ | BC \ / \ / A A = = A^0 B = A^ = A^1 = A~1 C = A^2 = 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 

HEAD^和HEAD〜的区别在http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html上的插图(Jon Loeliger)中有详细描述。

这个文档对于初学者来说可能有些模糊,所以我在下面重复了这个插图:

 GHIJ \ / \ / DEF \ | / \ \ | / | \|/ | BC \ / \ / A A = = A^0 B = A^ = A^1 = A~1 C = A^2 = 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 

^^^都是指提交的父母( ~~^^都指祖父母提交等),但是它们与数字一起使用时意义不同:

  • 如果一个提交具有多于一个父代,那么〜2意味着通过第一个父级在层次结构中增加两个级别

  • ^2表示提交具有多个父代的第二个父代(即因为它是合并)

这些可以合并,所以HEAD~2^3表示HEAD的祖父母提交的第三个父母提交。

我的两分钱…(好吧,我必须input更多的字符,因为计算器策略。)

在这里输入图像描述

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

值得注意的是,git也有一个跟踪“from-where-you-come”/“想要回到现在”的语法 – 例如, HEAD@{1}会引用你跳转的地方到新的提交位置。

基本上, HEAD@{}variables捕获HEAD移动的历史logging,您可以通过使用git reflog命令查看git reflog来决定使用特定的头部。

例:

 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 reset HEAD~2 – 之后,我想要移回我的HEAD到d – git reset HEAD@{1}

这是从http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde逐字logging的一个非常好的解释:;

ref~是ref〜1的简写forms,表示提交的第一个父代。 ref~2表示提交的第一个父代的第一个父代。 ref~3表示提交的第一个父代的第一个父代的第一个父代。 等等。

ref^ref^1缩写,意思是提交的第一个父代。 但是,两者不同的地方在于ref^2意味着提交的第二个父(记住,提交可以在合并时有两个父母)。

^~运算符可以合并。

在这里输入图像描述

HEAD ^^^与HEAD〜3相同,selectHEAD之前的第三个提交

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

  • HEAD〜指定“分支”上的第一个父项

  • HEAD ^允许您select提交的特定父级

一个例子:

如果你想跟随一个分支,你必须指定类似的东西

 master~209^2~15 

简单地说

  • ~指定祖先
  • ^指定父母

合并时可以指定一个或多个分支。 然后提交有两个或更多的父母,然后^是有用的表示父母。

假设你在分支A上,并且你有两个分支: BC.

在每个分支上,最后的三个提交分别是:

  • A1A2A3
  • BB1B2B3
  • CC1C3C3

如果现在在分支A上执行命令:

 git merge BC 

那么你正在梳理三个分支(这里你的合并提交有三个父母)

~表示第一个分支的第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~ )和: HEAD^...^n^ )。

注意2

  • HEAD^3HEAD^^^ (第一个表示C3 ,第二个表示A1 ),

一般来说

  • HEAD^1HEAD^相同,
  • 但对于n > 1: HEAD^n始终与HEAD^...^n~相同。

简单地说,对于第一级血统(血统,inheritance,谱系等)HEAD ^和HEAD〜都指向相同的提交,它是(位于)HEAD(提交)之上的一个父级。

此外,HEAD = HEAD = 1 = HEAD = HEAD = 1。 但是HEAD ^^!= HEAD ^ 2!= HEAD〜2。 然而HEAD ^ HEAD〜2。 阅读。

除了第一级亲子关系,事情变得更加棘手,特别是如果工作分支/主分支已经合并(来自其他分支)。 还有一个与脱字符语法相关的问题,HEAD ^^ = HEAD〜2(它们是等价的)但是HEAD ^^!= HEAD ^ 2(它们完全是两个不同的东西)。

每一个插入符号都是指HEAD的第一个父母,这就是为什么在一起串连起来的贴子相当于代字符的expression,因为它们严格地根据连接的插入符号的数字来引用第一个父母(第一父母)的第一个父母等等或者在波浪号之后的数字(无论哪种方式,它们都是指同一事物),即与第一父母留在一起并向上x代。

HEAD〜2(或HEAD ^^)是指在层次结构中当前提交(HEAD)之上/之上的两层血统的提交,即HEAD的祖父提交。

另一方面,HEAD ^ 2不是指第一个父母的第二个父母的提交,而是第二个父母的提交。 这是因为脱字符表示提交的父项,后面的数字表示提及哪个/哪个父提交(第一个父项,在脱字符后面没有跟随一个数字的情况下[因为它是数字的缩写是1,意思是第一个父母])。 与脱字符号不同的是,后面的数字并不意味着另一层次的层次向上,而是意味着在层次结构中横向有多less层次,需要find正确的父代(提交)。 与波浪号expression式中的数字不同,它只是层次结构中的一个父项,而不pipe数字(立即)如何处理。 插入的号码不是向上的,而是横跨整个层级的父母的横向数目(在父母向上的水平上,相当于连续的插入数)。

所以HEAD ^ 3等于HEAD提交的第三个父代(不是曾祖父母,这是HEAD ^^^和HEAD〜3会是…)。