HEAD e ORIG_HEAD no Git

252

A que esses símbolos se referem e o que eles significam?

(Não consigo encontrar nenhuma explicação na documentação oficial)

collimarco
fonte
4
Nota: HEADé agora (próximo git1.8.4) ' @'! Veja minha resposta editada abaixo
VonC
Nota-bis: ' @' (para HEAD) ainda está chegando, mas não para a resposta 1.8.4 editada e alterada .
VonC 16/08/13
1
Nota ter: ' @' para HEADestá de volta para o git 1.8.5 / 1.9. resposta editada novamente .
VonC 23/09
21
HEADe ORIG_HEADno Git são como $PWDe $OLDPWDno Bash. :)
musiphil

Respostas:

325

HEADé (direta ou indireta, ie simbólica) referência ao commit atual. É uma confirmação que você verificou no diretório de trabalho (a menos que você tenha feito algumas alterações, ou equivalente), e é uma confirmação sobre a qual "git commit" criaria uma nova. Geralmente HEADé uma referência simbólica a algum outro ramo nomeado; este ramo está atualmente com check-out ramo ou ramo atual. HEADtambém pode apontar diretamente para um commit; esse estado é chamado "HEAD desanexado" e pode ser entendido como estando em uma ramificação anônima e sem nome.

E @sozinho é um atalho para HEAD, desde o Git 1.8.5

ORIG_HEADé o estado anterior de HEAD, definido por comandos que possuem um comportamento possivelmente perigoso, para ser fácil revertê-los. É menos útil agora que o Git possui reflog: HEAD@{1}é aproximadamente equivalente a ORIG_HEAD( HEAD@{1}é sempre o último valor de HEAD, ORIG_HEADé o último valor HEADantes de uma operação perigosa).

Para obter mais informações, leia a página de manual do git (1) , o Manual do Usuário do Git , o Git Community Book e o Git Glossary

Jakub Narębski
fonte
2
Oi Jakub. +1 para a explicação. Você poderia detalhar a parte "aproximadamente equivalente" do HEAD @ {1}? Refiro-me na minha resposta ao tópico thread.gmane.org/gmane.comp.version-control.git/38379 (você estava lá, em fevereiro de 2007), e não entendi exatamente a discussão que vocês estavam tendo a sintaxe @ {...}.
VonC
19
ORIG_HEAD é definido (acho) apenas por comandos 'perigosos', que movem HEAD mais de um commit. Portanto, ORIG_HEAD nem sempre está definido, enquanto HEAD @ {1} está sempre definido. @ {1} é $ (git symbolic-ref HEAD) @ {1}, ou seja, usa reflog para ramificação atual, não HEAD reflog.
Jakub Narębski
Riiight ... eu entendi agora :) Obrigado por esse esclarecimento. Por quanto vale, também votei no seu comentário!
VonC
1
"e HEAD é um commit em cima do qual" git commit "criaria um novo." - bom lembrar, obrigado! Também no @VonC, 'É o commit "git commit" construído sobre, e "git diff --cached" e "git status" se comparam.'
Minqi Pan
1
As revisões de ajuda do git traz git-scm.com/docs/gitrevisions , que descreve todas as maneiras de referenciar confirmações (incluindo HEADe ORIG_HEAD).
Dahlbyk
104

Do git reset

"puxar" ou "mesclar" sempre deixa a ponta original da ramificação atual em ORIG_HEAD.

git reset --hard ORIG_HEAD

A redefinição difícil traz o arquivo de índice e a árvore de trabalho de volta para esse estado e redefine a ponta do ramo para esse commit.

git reset --merge ORIG_HEAD

Após inspecionar o resultado da mesclagem, você pode achar que a alteração na outra ramificação não é satisfatória. A execução " git reset --hard ORIG_HEAD" permitirá que você volte para onde estava, mas descartará as alterações locais, que você não deseja. " git reset --merge" mantém suas alterações locais.


Antes que qualquer correção seja aplicada, ORIG_HEAD é definido na ponta da ramificação atual.
Isso é útil se você tiver problemas com várias confirmações, como executar ' git am' na ramificação errada ou um erro nas confirmações que é mais facilmente corrigido alterando a caixa de correio (por exemplo, + erros nas linhas "De:").

Além disso, a mesclagem sempre define ' .git/ORIG_HEAD' para o estado original de HEAD, para que uma mesclagem problemática possa ser removida usando ' git reset ORIG_HEAD'.


Nota: daqui

HEAD é um ponteiro em movimento. Às vezes, significa o ramo atual, às vezes não.

Portanto, HEAD NÃO é sinônimo de "ramificação atual" em todos os lugares.

HEAD significa "atual" em todos os lugares no git, mas não significa necessariamente "ramo atual" (isto é, HEAD desanexado).

Mas quase sempre significa o "commit atual".
É o commit "git commit " construído sobre, e " git diff --cached" e " git status" comparam.
Significa a ramificação atual apenas em contextos muito limitados (exatamente quando queremos que um nome de ramificação opere --- redefinindo e aumentando a ponta da ramificação via commit / rebase / etc.).

O reflog é um veículo para voltar no tempo e as máquinas do tempo têm uma interação interessante com a noção de "atual".

HEAD@{5.minutes.ago}pode significar "desreferência HEAD symref para descobrir em que ramo estamos agora e depois descobrir onde estava a ponta desse ramo 5 minutos atrás".
Como alternativa, isso poderia significar "qual é o commit que eu chamaria de HEAD 5 minutos atrás, por exemplo, se eu" git show HEAD "naquela época".


git1.8.4 (julho de 2013) introduz introduziu uma nova notação!
(na verdade, será para 1.8.5 ou 1.9, quarto trimestre de 2013: reintroduzido com o commit 9ba89f4 )

Em vez de digitar quatro letras maiúsculas " HEAD", você pode dizer " @" agora,
por exemplo " git log @".

Consulte commit cdfd948

Digitar ' HEAD' é entediante, especialmente quando podemos usar ' @'.

A razão para escolher ' @' é que ela segue naturalmente a ref@opsintaxe (por exemplo,HEAD@{u} ), exceto que não temos ref, e nenhuma operação, e quando não as temos, faz sentido supor " HEAD".

Então agora podemos usar 'git show @~1 ', e toda essa bondade.

Até agora ' @' era um nome válido, mas entra em conflito com essa ideia, então vamos torná-la inválida. Provavelmente muito poucas pessoas, se houver, usaram esse nome.


Um post no período 1.8.4-RC3 (14, agosto de 2013) anunciou que esse recurso foi revertido e atrasou (Obrigado Cupcake para o heads-up ).
Novamente, ele é apresentado novamente com o commit 9ba89f4 (setembro de 2013).

Consulte commit 2c2b664 :

Reverter "Adicionar novo @atalho para HEAD"

Isso reverte o commit cdfd948 , pois ele não se aplica apenas a " @" (e se forma com modificadores como o @{u}aplicado), mas também afeta, por exemplo, " refs/heads/@/foo", o que não deveria.

A idéia básica de fornecer uma mão abreviada pode ser boa, e o tópico pode ser tentado novamente mais tarde, mas vamos reverter para evitar afetar os casos de uso existentes por enquanto para a próxima versão.

VonC
fonte
Depois de executar o git, restaure ORIG_HEAD e confirme. ORIG_HEAD ainda está lá em Referências ao lado de HEAD. Por que não foi removido da vista?
precisa saber é o seguinte
@ powder366, mas a git resetgerará a ORIG_HEAD. Então você precisa fazer rmisso manualmente. Consulte stackoverflow.com/a/12418078/6309, por exemplo.
VonC 21/01
1
@VonC o @alias para HEADestá sendo revertido (temporariamente?) Para a versão Git 1.8.4 ! Foi anunciado hoje!
Gostei do comentário "heads-up"!
Robino
2

Meu entendimento é que o HEAD aponta o ramo atual, enquanto ORIG_HEAD é usado para armazenar o HEAD anterior antes de executar operações "perigosas".

Por exemplo, git-rebase e git-am registram a ponta original da ramificação antes de aplicar qualquer alteração.

sinistro
fonte
4
CABEÇA nem sempre apontam no ramo atual (que pode ser independente)
VonC
1
Então, qual é o "ramo atual" quando HEAD é "desanexado?"
CJS
@ CurtJ.Sampson Isso é "nenhum ramo". é por isso que quando você está desapegado, você faz isso git branch foo -bpara "criar" um ramo para os órfãos que confirmam.
Royi Namir 11/03/19
1

De man 7 gitrevisions:

HEAD nomeia o commit no qual você baseou as alterações na árvore de trabalho. FETCH_HEAD registra a ramificação que você buscou em um repositório remoto com sua última chamada de busca git. ORIG_HEAD é criado por comandos que movem seu HEAD de maneira drástica, para registrar a posição do HEAD antes da operação, para que você possa alterar facilmente a ponta do ramo de volta ao estado antes de executá-los. MERGE_HEAD registra os commits que você está mesclando em sua ramificação quando você executa o git merge. CHERRY_PICK_HEAD registra o commit que você seleciona quando executa o git cherry-pick.

Nathan Chappell
fonte