Quelle est la différence entre HEAD ^ et HEAD ~ dans Git?

Lorsque je spécifie un object commit ancêtre dans Git, je suis confondu entre HEAD^ et HEAD~ .

Les deux ont une version “numérotée” comme HEAD^3 et HEAD~2 .

Ils me semblent très similaires ou identiques, mais y a-t-il des différences entre le tilde et le caret?

HEAD^ signifie le premier parent de la pointe de la twig en cours.

Rappelez-vous que git commits peut avoir plus d’un parent. HEAD^ est l’abréviation de HEAD^1 , et vous pouvez également adresser HEAD^2 et ainsi de suite, le cas échéant.

Vous pouvez contacter les parents de n’importe quel engagement, pas seulement HEAD . Vous pouvez également remonter d’une génération à l’autre: par exemple, master~2 signifie le grand-parent de la pointe de la twig principale, favorisant le premier parent en cas d’ambiguïté. Ces spécificateurs peuvent être chaînés arbitrairement, par exemple , topic~3^2 .

Pour plus de détails, reportez-vous à “Spécification des révisions” dans la documentation de git rev-parse .

Pour avoir une représentation visuelle de l’idée, citons une partie de la documentation:

Voici une illustration de Jon Loeliger. Les deux nœuds de validation B et C sont les parents du nœud de validation A. Les validations parentales sont ordonnées de gauche à droite.

 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 

La différence entre HEAD^ et HEAD~ est bien décrite par l’illustration (de Jon Loeliger) disponible sur http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html .

Cette documentation peut être un peu obscure pour les débutants, donc j’ai reproduit cette illustration ci-dessous:

 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 

Les deux ~ et ^ réfèrent tous deux au parent du commit ( ~~ et ^^ se réfèrent tous deux au commit du grand-parent, etc.) Mais ils ont un sens différent lorsqu’ils sont utilisés avec des nombres:

  • ~2 signifie deux niveaux dans la hiérarchie , via le premier parent si un commit a plus d’un parent

  • ^2 signifie le deuxième parent où un commit a plus d’un parent (c’est parce que c’est une fusion)

Celles-ci peuvent être combinées, de sorte que HEAD~2^3 signifie que le troisième parent du commit de ses grands-parents est engagé.

Mes deux centimes…

entrer la description de l'image ici

Le format ^ vous permet de sélectionner le nième parent du commit (pertinent dans les fusions). Le format ~ vous permet de sélectionner le nième commit de l’ancêtre, toujours en suivant le premier parent. Voir la documentation de git-rev-parse pour quelques exemples.

Voici une très bonne explication prise textuellement de http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde :

ref~ est un raccourci pour ref~1 et signifie le premier parent du commit. ref~2 signifie le premier parent du premier parent du commit. ref~3 signifie le premier parent du premier parent du commit. Etc.

ref^ est un raccourci pour ref^1 et signifie le premier parent du commit. Mais là où les deux diffèrent, c’est que ref^2 signifie le deuxième parent du commit (rappelez-vous que les commits peuvent avoir deux parents quand ils sont une fusion).

Les opérateurs ^ et ~ peuvent être combinés.

entrer la description de l'image ici

Il convient de noter que git a également une syntaxe pour suivre “from-where-you-came” / “want-to-go-back-now” – par exemple, HEAD@{1} fera référence à l’endroit d’où vous avez sauté au nouvel emplacement de validation.

Fondamentalement, les variables HEAD@{} capturent l’historique des mouvements HEAD, et vous pouvez décider d’utiliser une tête particulière en examinant les reflogs de git à l’aide de la commande git reflog .

Exemple:

 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 

Un exemple pourrait être que j’ai fait des commits locaux a-> b-> c-> d puis je suis retourné en éliminant 2 commits pour vérifier mon code – git reset HEAD~2 – et ensuite je veux déplacer ma HEAD pour git reset HEAD@{1} .

HEAD ^^^ est identique à HEAD ~ 3, en sélectionnant le troisième commit avant HEAD

HEAD ^ 2 spécifie la deuxième tête dans un commit de fusion

  • HEAD ~ spécifie le premier parent sur une “twig”

  • HEAD ^ vous permet de sélectionner un parent spécifique du commit

Un exemple:

Si vous voulez suivre une twig latérale, vous devez spécifier quelque chose comme

 master~209^2~15 

De manière simpliste :

  • ~ spécifie les ancêtres
  • ^ spécifie les parents

Vous pouvez spécifier une ou plusieurs twigs lors de la fusion. Ensuite, commit a deux parents ou plus et alors ^ est utile pour indiquer les parents.

Supposons que vous êtes sur la twig A et que vous avez deux autres twigs: B et C.

Sur chaque twig, trois derniers commits sont respectivement:

  • A : A1 , A2 , A3
  • B : B1 , B2 , B3
  • C : C1 , C3 , C3

Si maintenant sur la twig A, vous exécutez la commande:

 git merge BC 

alors vous combinez trois twigs ensemble (ici, votre engagement de fusion a trois parents)

et

~ indique le nième ancêtre dans la première twig, donc

  • HEAD~ indique A3
  • HEAD~2 indique A2
  • HEAD~3 indique A1

^ indique le nième parent, donc

  • HEAD^ indique A3
  • HEAD^2 indique B3
  • HEAD^3 indique C3

La prochaine utilisation de ~ ou ^ les uns à côté des autres est dans le contexte du commit désigné par les caractères précédents.

Avis 1 :

  • HEAD~3 est toujours égal à: HEAD~~~ et à: HEAD^^^ (tout indique A1 ),

et généralement :

  • HEAD~n est toujours égal à: HEAD~...~ ( n fois ~ ) et à: HEAD^...^ ( n fois ^ ).

Avis 2 :

  • HEAD^3 n’est pas la même chose que HEAD^^^ (le premier indique C3 et le second indique A1 ),

et généralement :

  • HEAD^1 est le même que HEAD^ ,
  • mais pour n > 1: HEAD^n est toujours différent de HEAD^...^ ( n times ~ ).

TLDR

~ est ce que vous voulez la plupart du temps, il fait référence aux engagements passés à la twig actuelle

^ références parents (git-merge crée un 2ème parent ou plus)

A ~ est toujours le même que A ^
Un ~~ est toujours le même que A ^^, et ainsi de suite
A ~ 2 n’est pas la même chose que A ^ 2 cependant,
parce que ~ 2 est un raccourci pour ~~
alors que ^ 2 n’est pas sténographique pour quelque chose, cela signifie le 2e parent

exemple actuel de la différence entre HEAD ~ et HEAD ^

HEAD ^ VS HEAD ~

En termes simples, pour le premier niveau de parenté (ascendance, inheritance, lignage, etc.), HEAD ^ et HEAD ~ désignent tous deux le même commit, qui est (situé) un parent au-dessus de HEAD (commit).

En outre, HEAD ^ = HEAD ^ 1 = HEAD ~ = HEAD ~ 1. Mais HEAD ^^! = HEAD ^ 2! = HEAD ~ 2. Pourtant, HEAD ^^ = HEAD ~ 2. Continuer à lire.

Au-delà du premier niveau de parenté, les choses se compliquent, en particulier si la twig / twig principale a été fusionnée (à partir d’autres twigs). Il y a aussi la question de la syntaxe avec le caret, HEAD ^^ = HEAD ~ 2 (ils sont équivalents) BUT HEAD ^^! = HEAD ^ 2 (ce sont deux choses complètement différentes).

Chaque / le caret fait référence au premier parent du HEAD, ce qui explique pourquoi les carets combinés sont équivalents aux expressions de tilde, car ils se réfèrent aux premiers parents du premier parent (premier parent), etc. ou sur le nombre qui suit le tilde (de toute façon, ils signifient tous les deux la même chose), c’est-à-dire restr avec le premier parent et remonter x générations.

HEAD ~ 2 (ou HEAD ^^) fait référence au commit qui correspond à deux niveaux d’ascendance au-dessus ou au-dessus du commit actuel (le HEAD) dans la hiérarchie, ce qui signifie que le grand-parent du HEAD commet.

HEAD ^ 2, d’autre part, ne fait PAS référence au commit du second parent du premier parent, mais simplement au commit du deuxième parent. C’est parce que le caret signifie le parent du commit, et le nombre suivant signifie à quoi / à quoi le parent est fait référence (le premier parent, dans le cas où le curseur n’est pas suivi par un nombre) étant 1, signifiant le premier parent]). Contrairement au signe d’insertion, le nombre qui suit n’implique pas un autre niveau de hiérarchie, mais implique plutôt le nombre de niveaux sur le plan latéral, dans la hiérarchie, il faut aller chercher le bon parent (commit). Contrairement au nombre dans une expression tilde, il ne s’agit que d’un parent dans la hiérarchie, quel que soit le nombre (immédiatement) passant par le curseur. Au lieu de remonter, le nombre de suivi du caret compte latéralement pour les parents dans la hiérarchie [à un niveau de parents supérieur au nombre de carets consécutifs].

Donc HEAD ^ 3 est égal au troisième parent de l’engagement HEAD (PAS l’arrière-grand-parent, qui est ce que HEAD ^^^ AND HEAD ~ 3 serait …).