Règles de base
- Utilisez la
~
plupart du temps - pour remonter un certain nombre de générations, généralement ce que vous voulez
- Utilisation
^
lors des validations de fusion - parce qu'ils ont deux parents (immédiats) ou plus
Mnémotechnique:
- Tilde
~
est presque linéaire en apparence et veut reculer en ligne droite
- Caret
^
suggère un segment intéressant d'un arbre ou d'une fourche sur la route
Tilde
La section «Spécification des révisions» de la git rev-parse
documentation définit ~
comme
<rev>~<n>
, par exemplemaster~3
Un suffixe ~<n>
pour un paramètre de révision signifie l'objet commit qui est l' ancêtre de n ième génération de l'objet commit nommé, ne suivant que les premiers parents. Par exemple, <rev>~3
est équivalent à <rev>^^^
ce qui équivaut à <rev>^1^1^1
…
Vous pouvez contacter les parents de n'importe quel engagement, pas seulement HEAD
. Vous pouvez également revenir en arrière à travers les générations: par exemple, master~2
signifie le grand-parent de la pointe de la branche principale, favorisant le premier parent lors des validations de fusion.
Caret
L'histoire de Git est non linéaire: un graphique acyclique dirigé (DAG) ou un arbre. Pour un commit avec un seul parent, rev~
et rev^
signifie la même chose. Le sélecteur de curseur devient utile avec les validations de fusion, car chacun est l'enfant de deux parents ou plus - et le langage des souches emprunté à la biologie.
HEAD^
signifie le premier parent immédiat de la pointe de la branche actuelle. HEAD^
est l'abréviation de HEAD^1
, et vous pouvez également adresser HEAD^2
et ainsi de suite, le cas échéant. La même section de la git rev-parse
documentation le définit comme
<rev>^
, par exemple HEAD^
,v1.5.1^0
un suffixe ^
pour un paramètre de révision signifie le premier parent de cet objet de validation. ^<n>
signifie le n ème parent ([ par exemple ] <rev>^
est équivalent à <rev>^1
). En règle générale, <rev>^0
signifie la validation elle-même et est utilisé lorsque <rev>
est le nom d'objet d'un objet balise qui fait référence à un objet de validation.
Exemples
Ces spécificateurs ou sélecteurs peuvent être chaînés arbitrairement, par exemple , topic~3^2
en anglais est le deuxième parent du commit de fusion qui est l'arrière-grand-parent (trois générations en arrière) de la pointe actuelle de la branche topic
.
La section susmentionnée de la git rev-parse
documentation trace de nombreux chemins à travers une histoire git théorique. Le temps s'écoule généralement vers le bas. Les validations D, F, B et A sont des validations de fusion.
Voici une illustration, par Jon Loeliger. Les deux nœuds de validation B et C sont les parents du nœud de validation A. Les validations parent sont ordonnées de gauche à droite.
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
Exécutez le code ci-dessous pour créer un référentiel git dont l'historique correspond à l'illustration citée.
#! /usr/bin/env perl
use strict;
use warnings;
use subs qw/ postorder /;
use File::Temp qw/ mkdtemp /;
my %sha1;
my %parents = (
A => [ qw/ B C / ],
B => [ qw/ D E F / ],
C => [ qw/ F / ],
D => [ qw/ G H / ],
F => [ qw/ I J / ],
);
sub postorder {
my($root,$hash) = @_;
my @parents = @{ $parents{$root} || [] };
postorder($_, $hash) for @parents;
return if $sha1{$root};
@parents = map "-p $sha1{$_}", @parents;
chomp($sha1{$root} = `git commit-tree @parents -m "$root" $hash`);
die "$0: git commit-tree failed" if $?;
system("git tag -a -m '$sha1{$root}' '$root' '$sha1{$root}'") == 0 or die "$0: git tag failed";
}
$0 =~ s!^.*/!!; # / fix Stack Overflow highlighting
my $repo = mkdtemp "repoXXXXXXXX";
chdir $repo or die "$0: chdir: $!";
system("git init") == 0 or die "$0: git init failed";
chomp(my $tree = `git write-tree`); die "$0: git write-tree failed" if $?;
postorder 'A', $tree;
system "git update-ref HEAD $sha1{A}"; die "$0: git update-ref failed" if $?;
system "git update-ref master $sha1{A}"; die "$0: git update-ref failed" if $?;
# for browsing history - http://blog.kfish.org/2010/04/git-lola.html
system "git config alias.lol 'log --graph --decorate --pretty=oneline --abbrev-commit'";
system "git config alias.lola 'log --graph --decorate --pretty=oneline --abbrev-commit --all'";
Il ajoute des alias dans le nouveau référentiel jetable uniquement pour git lol
etgit lola
vous pouvez donc afficher l'historique comme dans
$ git lol
* 29392c8 (HEAD -> master, tag: A) A
|\
| * a1ef6fd (tag: C) C
| |
| \
*-. \ 8ae20e9 (tag: B) B
|\ \ \
| | |/
| | * 03160db (tag: F) F
| | |\
| | | * 9df28cb (tag: J) J
| | * 2afd329 (tag: I) I
| * a77cb1f (tag: E) E
* cd75703 (tag: D) D
|\
| * 3043d25 (tag: H) H
* 4ab0473 (tag: G) G
Notez que sur votre machine, les noms des objets SHA-1 seront différents de ceux ci-dessus, mais les balises vous permettent d'adresser les commits par nom et de vérifier votre compréhension.
$ git log -1 --format=%f $(git rev-parse A^)
B
$ git log -1 --format=%f $(git rev-parse A~^3~)
I
$ git log -1 --format=%f $(git rev-parse A^2~)
F
La «Spécification des révisions» dans la git rev-parse
documentation regorge d'informations utiles et mérite une lecture approfondie. Voir aussi Git Tools - Revision Selection dans le livre Pro Git .
Ordre des engagements des parents
Le commit 89e4fcb0dd de la propre histoire de git est un commit de fusion, comme l' git show 89e4fcb0dd
indique la ligne d'en-tête Merge qui affiche les noms des objets des ancêtres immédiats.
commit 89e4fcb0dd01b42e82b8f27f9a575111a26844df
Merge: c670b1f876 649bf3a42f b67d40adbb
Author: Junio C Hamano <gitster@pobox.com>
Date: Mon Oct 29 10:15:31 2018 +0900
Merge branches 'bp/reset-quiet' and 'js/mingw-http-ssl' into nd/config-split […]
Nous pouvons confirmer la commande en demandant git rev-parse
de montrer les parents immédiats de 89e4fcb0dd dans l'ordre.
$ git rev-parse 89e4fcb0dd^1 89e4fcb0dd^2 89e4fcb0dd^3
c670b1f876521c9f7cd40184bf7ed05aad843433
649bf3a42f344e71b1b5a7f562576f911a1f7423
b67d40adbbaf4f5c4898001bf062a9fd67e43368
L'interrogation du quatrième parent inexistant entraîne une erreur.
$ git rev-parse 89e4fcb0dd^4
89e4fcb0dd^4
fatal: ambiguous argument '89e4fcb0dd^4': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
Si vous souhaitez extraire uniquement les parents, utilisez un joli format %P
pour les hachages complets
$ git log -1 --pretty=%P 89e4fcb0dd
c670b1f876521c9f7cd40184bf7ed05aad843433 649bf3a42f344e71b1b5a7f562576f911a1f7423 b67d40adbbaf4f5c4898001bf062a9fd67e43368
ou %p
pour les parents abrégés.
$ git log -1 --pretty=%p 89e4fcb0dd
c670b1f876 649bf3a42f b67d40adbb