Quando eu especifico um objeto de confirmação de ancestral no Git, fico confuso entre HEAD^
e HEAD~
.
Ambos têm uma versão "numerada" como HEAD^3
e HEAD~2
.
Eles parecem muito parecidos ou iguais comigo, mas existem diferenças entre o til e o sinal de intercalação?
Respostas:
Regras de ouro
~
maior parte do tempo - para voltar várias gerações, geralmente o que você deseja^
em consolidação de mesclagem - porque eles têm dois ou mais pais (imediatos)Mnemônicos:
~
aparência é quase linear e quer retroceder em linha reta^
sugere um segmento interessante de uma árvore ou uma bifurcação na estradaTil
A seção "Especificando revisões" da
git rev-parse
documentação define~
comoVocê 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~2
significa 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~
erev^
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 deHEAD^1
, e você também pode abordarHEAD^2
e assim por diante, conforme apropriado. A mesma seção dagit rev-parse
documentação define comoExemplos
Esses especificadores ou seletores podem ser encadeados arbitrariamente, por exemplo ,
topic~3^2
em inglês é o segundo pai do commit de mesclagem que é o bisavô (três gerações atrás) da ponta atual do ramotopic
.A seção mencionada acima da
git rev-parse
documentaçã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.Execute o código abaixo para criar um repositório git cujo histórico corresponda à ilustração citada.
Ele adiciona aliases no novo repositório descartável apenas para,
git lol
egit lola
assim você pode ver o histórico como emObserve 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.
As "Revisões de especificação" na
git rev-parse
documentaçã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 89e4fcb0dd
indica a linha de cabeçalho Merge que exibe os nomes de objetos dos ancestrais imediatos.Podemos confirmar a ordem pedindo
git rev-parse
para mostrar os pais imediatos de 89e4fcb0dd em sequência.A consulta do quarto pai pai inexistente resulta em um erro.
Se você deseja extrair apenas os pais, use um formato bonito
%P
para os hashes completosou
%p
para pais abreviados.fonte
^^^^^^^
não~7
é? É por isso que~
é útilA diferença entre
HEAD^
eHEAD~
é bem descrita pela ilustração (de Jon Loeliger) encontrada em http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html .Esta documentação pode ser um pouco obscura para iniciantes, por isso reproduzi a ilustração abaixo:
fonte
F = A^2^
,.^ == ^1 == LEFTMOST PARENT
,^2 == SECOND LEFTMOST PARENT
e assim por diante. E~ == ~1 == LEFTMOST PARENT
,~2 == LEFTMOST PARENTS LEFTMOST PARENT == LEFTMOST GRANDPARENT
. Por extensão,~2^2 == LEFTMOST GRANDPARENTS SECOND LEFTMOST PARENT
Ambos
~
e^
por si só se referem ao pai do commit (~~
e^^
ambos se referem ao commit dos avós, etc.). Mas eles diferem em significado quando são usados com números:~2
significa dois níveis na hierarquia , através do primeiro pai, se um commit tiver mais de um pai^2
significa o segundo pai em que um commit tem mais de um pai (ou seja, porque é uma mesclagem)Eles podem ser combinados, portanto
HEAD~2^3
,HEAD
o terceiro pai do commit dos avós.fonte
^^
era o mesmo,^2
mas não é.Meus dois centavos...
fonte
H=A~2^2
nãoH=A~2^1
?A
,B
,D
,G
estão no mesmo ramo ea cometerD
é uma mesclagem deG
eH
, portanto, ter dois pais. Portanto, o commit (H
) de outro ramo é referência por^2
.Aqui está uma explicação muito boa, extraída literalmente de http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde :
fonte
O
^<n>
formato permite selecionar o enésimo pai da confirmação (relevante nas mesclagens). O~<n>
formato permite selecionar o enésimo enésimo commit ancestral, sempre seguindo o primeiro pai. Veja a documentação do git-rev-parse para alguns exemplos.fonte
Vale ressaltar que o git também possui uma sintaxe para rastrear "de onde você veio" / "quero voltar agora" - por exemplo,
HEAD@{1}
fará referência ao local de onde você pulou para o novo local de confirmação.Basicamente
HEAD@{}
variáveis capturar a história do movimento da cabeça, e você pode decidir usar uma cabeça em particular, olhando para reflogs de git usando o comandogit reflog
.Exemplo:
Um exemplo pode ser que eu fiz commit local a-> b-> c-> d e depois voltei a descartar 2 commit para verificar meu código -
git reset HEAD~2
- e depois quero mover meu HEAD de volta para d -git reset HEAD@{1}
.fonte
Simplisticamente :
~
especifica ancestrais^
especifica os paisVocê pode especificar uma ou mais ramificações ao mesclar. Então, um commit tem dois ou mais pais e
^
é útil para indicar os pais.Suponha que você esteja no ramo A e você tem mais dois ramos: B e C .
Em cada ramificação, os três últimos commits são:
Se agora no ramo A você executar o comando:
então você está combinando três ramos juntos (aqui o seu commit de mesclagem tem três pais)
e
~
indica o nono antepassado no primeiro ramo, entãoHEAD~
indica A3HEAD~2
indica A2HEAD~3
indica A1^
indica o nono pai, entãoHEAD^
indica A3HEAD^2
indica B3HEAD^3
indica C3O próximo uso de um
~
ou^
ao lado do outro é no contexto do commit designado pelos caracteres anteriores.Nota 1 :
HEAD~3
é sempre igual a:HEAD~~~
e a:HEAD^^^
(todos indicam A1 ),e geralmente :
HEAD~n
é sempre igual a:HEAD~...~
( n vezes~
) e a:HEAD^...^
( n vezes^
).Aviso 2 :
HEAD^3
não é o mesmo queHEAD^^^
(o primeiro indica C3 e o segundo indica A1 ),e geralmente :
HEAD^1
é o mesmo queHEAD^
,HEAD^n
sempre é o mesmo queHEAD^...^
( n vezes~
).fonte
TLDR
~ é o que você deseja na maioria das vezes, ele faz referência a confirmações anteriores à ramificação atual
^ faz referência aos pais (o git-merge cria um segundo pai ou mais)
A ~ é sempre o mesmo que A ^
A ~~ é sempre o mesmo que A ^^, e assim por diante
A ~ 2 não é o mesmo que A ^ 2, no entanto,
porque ~ 2 é uma abreviação de ~~
enquanto ^ 2 não é abreviação de qualquer coisa, significa o segundo pai
fonte
HEAD ^^^ é o mesmo que HEAD ~ 3, selecionando o terceiro commit antes de HEAD
HEAD ^ 2 especifica o segundo cabeçalho em uma consolidação de mesclagem
fonte
HEAD ~ especifica o primeiro pai em um "ramo"
HEAD ^ permite que você selecione um pai específico da confirmação
Um exemplo:
Se você deseja seguir uma ramificação lateral, precisa especificar algo como
fonte
exemplo real da diferença entre HEAD ~ e HEAD ^
fonte
Simplificando, para o primeiro nível de ascendência (ascendência, herança, linhagem etc.) HEAD ^ e HEAD ~ apontam para o mesmo commit, que é (localizado) um pai acima do HEAD (commit).
Além disso, HEAD ^ = HEAD ^ 1 = HEAD ~ = HEAD ~ 1. Mas HEAD ^^! = HEAD ^ 2! = HEAD ~ 2. No entanto, CABEÇA ^^ = CABEÇA ~ 2. Leia.
Além do primeiro nível de ascendência, as coisas ficam mais complicadas, especialmente se a ramificação / ramificação principal tiver sido mesclada (de outras ramificações). Há também a questão da sintaxe com o cursor, HEAD ^^ = HEAD ~ 2 (eles são equivalentes) MAS HEAD ^^! = HEAD ^ 2 (são duas coisas completamente diferentes).
Cada / o sinal de intercalação refere-se ao primeiro pai do HEAD, e é por isso que os caracteres agrupados são equivalentes a expressões til, porque se referem aos primeiros pais do primeiro pai (primeiro pai), etc., etc., com base estritamente no número de caracteres conectados ou no número que segue o til (de qualquer forma, ambos significam a mesma coisa), ou seja, fique com o primeiro pai e suba x gerações.
HEAD ~ 2 (ou HEAD ^^) refere-se ao commit que é dois níveis de ancestralidade acima / acima do commit atual (o HEAD) na hierarquia, significando o commit dos avós do HEAD.
HEAD ^ 2, por outro lado, refere-se NÃO ao commit do segundo pai, mas simplesmente ao commit do segundo pai. Isso ocorre porque o sinal de intercalação significa o pai da confirmação, e o número a seguir significa a qual / qual confirmação do pai é referida (o primeiro pai, no caso em que o cursor não é seguido por um número [porque é uma abreviação para o número sendo 1, significando o primeiro pai]). Diferentemente do sinal de intercalação, o número que segue depois não implica outro nível de hierarquia para cima, mas implica quantos níveis de lado, na hierarquia, é necessário encontrar o pai correto (confirmação). Diferente do número em uma expressão de til, ele é apenas um pai na hierarquia, independentemente do número (imediatamente) que prossegue o cursor. Em vez de para cima, o sinal de intercalação '
Então HEAD ^ 3 é igual ao terceiro pai do commit HEAD (NÃO o bisavô, que é o que HEAD ^^^ AND HEAD ~ 3 seria ...).
fonte
~
isso significa pai.^
se tiver pais de dois ou mais, como consolidação de mesclagem, podemos selecionar o segundo pai ou outro.portanto, se apenas uma coisa como (HEAD ~ ou HEAD ^), ela tem os mesmos resultados.
fonte