Regras de ouro
- Use a
~maior parte do tempo - para voltar várias gerações, geralmente o que você deseja
- Use
^em consolidação de mesclagem - porque eles têm dois ou mais pais (imediatos)
Mnemônicos:
- A
~aparência é quase linear e quer retroceder em linha reta
- Caret
^sugere um segmento interessante de uma árvore ou uma bifurcação na estrada
Til
A seção "Especificando revisões" da git rev-parsedocumentação define ~como
<rev>~<n>, Por exemplo,master~3
um sufixo ~<n>a um parâmetro de revisão significa que o objeto que é a cometer n º ancestral geração do chamado cometer objeto, seguindo apenas os primeiros pais. Por exemplo, <rev>~3é equivalente a <rev>^^^que é equivalente a <rev>^1^1^1…
Você pode obter os pais de qualquer confirmação, não apenas HEAD. Você também pode voltar através de gerações: por exemplo, master~2significa o avô da ponta do ramo mestre, favorecendo o primeiro pai na confirmação de mesclagem.
Caret
A história do Git é não linear: um gráfico acíclico direcionado (DAG) ou árvore. Para um commit com apenas um pai rev~e rev^significa a mesma coisa. O seletor de intercalação se torna útil com confirmações de mesclagem, porque cada um é filho de dois ou mais pais - e estirpe a linguagem emprestada da biologia.
HEAD^significa o primeiro pai imediato da ponta do ramo atual. HEAD^é a abreviação de HEAD^1, e você também pode abordar HEAD^2e assim por diante, conforme apropriado. A mesma seção da git rev-parsedocumentação define como
<rev>^, por exemplo HEAD^ ,v1.5.1^0
um sufixo ^para um parâmetro de revisão significa o primeiro pai desse objeto de confirmação. ^<n>significa o n th -mãe ([ por exemplo ] <rev>^é equivalente a <rev>^1). Como regra especial, <rev>^0significa o commit em si e é usado quando <rev>é o nome do objeto de um objeto de tag que se refere a um objeto de commit.
Exemplos
Esses especificadores ou seletores podem ser encadeados arbitrariamente, por exemplo , topic~3^2em inglês é o segundo pai do commit de mesclagem que é o bisavô (três gerações atrás) da ponta atual do ramo topic.
A seção mencionada acima da git rev-parsedocumentação rastreia muitos caminhos através de um histórico nocional do git. O tempo flui geralmente para baixo. As confirmações D, F, B e A são confirmações de mesclagem.
Aqui está uma ilustração, de Jon Loeliger. Os nós de confirmação B e C são pais do nó de confirmação A. As confirmações pai são ordenadas da esquerda para a direita.
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
Execute o código abaixo para criar um repositório git cujo histórico corresponda à ilustração citada.
#! /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'";
Ele adiciona aliases no novo repositório descartável apenas para, git lolegit lola assim você pode ver o histórico como em
$ 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
Observe que na sua máquina os nomes dos objetos SHA-1 serão diferentes daqueles acima, mas as tags permitem que você endereça as confirmações por nome e verifique sua compreensão.
$ 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
As "Revisões de especificação" na git rev-parsedocumentação estão cheias de ótimas informações e valem uma leitura aprofundada. Veja também Ferramentas Git - Seleção de Revisão do livro Pro Git .
Ordem dos pais confirmados
O commit 89e4fcb0dd do próprio histórico do git é um commit de mesclagem, como git show 89e4fcb0ddindica a linha de cabeçalho Merge que exibe os nomes de objetos dos ancestrais imediatos.
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 […]
Podemos confirmar a ordem pedindo git rev-parsepara mostrar os pais imediatos de 89e4fcb0dd em sequência.
$ git rev-parse 89e4fcb0dd^1 89e4fcb0dd^2 89e4fcb0dd^3
c670b1f876521c9f7cd40184bf7ed05aad843433
649bf3a42f344e71b1b5a7f562576f911a1f7423
b67d40adbbaf4f5c4898001bf062a9fd67e43368
A consulta do quarto pai pai inexistente resulta em um erro.
$ 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>...]'
Se você deseja extrair apenas os pais, use um formato bonito %P para os hashes completos
$ git log -1 --pretty=%P 89e4fcb0dd
c670b1f876521c9f7cd40184bf7ed05aad843433 649bf3a42f344e71b1b5a7f562576f911a1f7423 b67d40adbbaf4f5c4898001bf062a9fd67e43368
ou %ppara pais abreviados.
$ git log -1 --pretty=%p 89e4fcb0dd
c670b1f876 649bf3a42f b67d40adbb