Qual é a cabeça no git?

232

Parece haver uma diferença entre o último commit, o HEAD e o estado do arquivo que posso ver no meu diretório.

O que é HEAD, o que posso fazer com ele e que erro devo evitar?

e-satis
fonte
1
Começando com Git v1.8.4, todas as respostas abaixo que o uso HEADou headagora pode usar @no lugar de HEADvez. Veja esta resposta (última seção) para saber por que você pode fazer isso.
3
Do git-scm : O HEAD no Git é o ponteiro para a referência de ramificação atual, que por sua vez é um ponteiro para o último commit que você fez ou o último commit que foi feito check-out no seu diretório de trabalho. Isso também significa que será o pai do próximo commit que você fizer. Geralmente é mais simples pensar nisso como HEAD é o instantâneo do seu último commit.
Quazi Irfan
3
Possível duplicata do O que é HEAD no Git?
Buts

Respostas:

185

HEAD é uma referência ao último commit no ramo de check-out atualmente.


Há uma pequena exceção a isso, que é o HEAD desanexado. Um HEAD desanexado é a situação em que você termina sempre que faz check-out de um commit (ou tag) em vez de um branch. Nesse caso, você deve imaginar isso como um ramo temporário sem nome; então, em vez de ter uma referência de ramificação nomeada, temos apenas HEAD. Ele ainda permitirá que você faça confirmações (que atualizarão o HEAD), portanto a definição curta acima ainda será verdadeira se você pensar em um HEAD desanexado como um ramo temporário sem nome.

cutucar
fonte
1
Então, por que você pode ter duas cabeças?
e-satis
1
@ e-satis: às vezes, você vê ramos chamados de cabeças - eles são armazenados refs/heads. A cabeça minúscula é diferente HEAD, no entanto. Minha resposta esclarece isso um pouco.
Cascabel 27/03
7
@ e-satis: Isso não é regex. Essa ^é apenas a notação do git para "o commit antes" - esse é o commit antes do atual. (Se a corrente é uma mesclagem, ele usa o primeiro pai.)
Cascabel
1
@ e-satis: Veja a seção de revisões de especificação da página de manual para git-rev-list para obter mais informações sobre todas as maneiras de especificar confirmações - este é apenas um pequeno pedaço. kernel.org/pub/software/scm/git/docs/…
Cascabel
1
Não, quando rev e HEAD estão apontando para o mesmo commit, não há diferença. E você pode até escrever o ID de confirmação (o valor SHA-1) em vez de rev ou HEAD. E não se preocupe, você não nos assediar com as perguntas :) (me, pelo menos: P)
picar
87

HEAD é uma referência (referência) ao commit atualmente com check-out.

Em estados normais, é na verdade uma referência simbólica ao ramo que você fez check-out - se você olhar o conteúdo de .git / HEAD, verá algo como "ref: refs / heads / master". O próprio ramo é uma referência ao commit na ponta do ramo. Portanto, no estado normal, HEADrefere-se efetivamente ao commit na ponta do ramo atual.

Também é possível ter uma "CABEÇA destacada". Isso acontece quando você faz check-out de algo além de uma ramificação (local), como uma ramificação remota, uma confirmação específica ou uma tag. O lugar mais comum para ver isso é durante uma nova refazer interativa, quando você decide editar uma confirmação. No estado HEAD desanexado, seu HEAD é uma referência direta a um commit - o conteúdo de .git / HEAD será um hash SHA1.

De um modo geral, HEAD é apenas um nome conveniente para significar "o que você fez check-out" e você realmente não precisa se preocupar muito com isso. Esteja ciente do que fez o check-out e lembre-se de que você provavelmente não deseja confirmar se não estiver em uma ramificação (estado HEAD desanexado), a menos que saiba o que está fazendo (por exemplo, em um rebase interativo) .

Cascabel
fonte
6
Isso é algo que eu não entendo. Se você faz checkout de uma filial remota, por que você acaba com um "HEAD desanexado". Por que você não salta automaticamente na ramificação em seu repo local que corresponde ao seu controle remoto?
e-satis
3
@ e-satis: Se você deseja a filial local, consulte a filial local. Lembre-se de que os dois não são necessariamente os mesmos - você precisa informar ao local para mesclar o remoto (ou puxar). O rastreamento é apenas para que você saiba qual puxar automaticamente quando você perguntar. O motivo de desanexar é que o ramo remoto se destina a ser um ponteiro para o último local do ramo visto no repositório remoto. Se você tentar se comprometer, o repositório remoto não muda, portanto a ramificação remota também não deve.
Cascabel 27/03
1
OK, foi o que eu não entendi: ter um ramo local nomeado de uma maneira não implica que seja o mesmo que o remoto. Realmente difícil de entender no começo, porque eu venho de um background em SVN :-) Obrigado cara. BTW, como você move um HEAD decapitado para uma filial local para cometer aqui?
e-satis
3
@ e-satis: A resposta geral é git rebase <branch> HEAD. Ele encontrará o último ancestral comum de <branch>e e HEAD, em seguida, leva todos os commits de lá para HEADe os aplica (os rebase) em <branch>. Ele basicamente faz isso aplicando-os como patches; portanto, se os dois ramos forem realmente diferentes, poderá haver conflitos. Mas se <branch>for um ancestral de HEAD(ou seja, você estava no lugar certo, apenas esqueceu que se destacou HEAD), o rebase é apenas uma mesclagem de avanço rápido.
Cascabel 27/03
3
Esta é uma das descrições mais claras e precisas do git HEAD que eu já vi, depois de pesquisar por um tempo.
Larsh
21

Eu sempre pensei que HEAD~5significa ir para 5 confirma antes. Mas ele não carrega a parte GO do comando. Ele só carrega a referência / 'onde' parte do comando.

Em termos leigos, é usado para responder à pergunta: PARA ONDE devo ir? Com qual commit?

  • HEAD significa (a referência à) confirmação atual
  • HEAD~1 significa (a referência a) 1 confirmar antes
  • HEAD~ TAMBÉM significa (a referência a) 1 confirmação antes
  • HEAD~87 significa (a referência a) 87 confirma antes

Uso:

  • git checkout HEAD~1 realmente vai / checkout para 1 confirmação / referência antes
  • git reset HEAD~3 descomprimirá seus últimos 3 commits - sem remover as alterações, ou seja, você poderá ver todas as alterações feitas nos últimos 3 commits juntos, remover qualquer coisa que você não gostar ou adicionar a ele e confirmar todos eles novamente.
  • git reset --hard HEAD~3cancelará sua última confirmação e removerá as alterações . Ele removerá completamente essas alterações. Para mais, veja aqui .
  • git diff HEAD~3 para verificar alterações nos últimos 3 commits
Mel
fonte
3
voltando para a minha própria resposta :)
Mel
15

Ponteiro HEAD no Git

Git mantém uma variável de referência chamada HEAD. E chamamos essa variável de ponteiro, porque seu objetivo é referenciar ou apontar para um commit específico no repositório. À medida que fazemos novas confirmações, o ponteiro muda ou passa para apontar para uma nova confirmação. HEAD sempre aponta para a ponta da ramificação atual em nosso repositório. Agora, isso tem a ver com nosso repositório, não com nosso índice de teste ou nosso diretório de trabalho.

Outra maneira de pensar nisso é o último estado do nosso repositório ou o que foi feito check-out pela última vez, e porque é onde o repositório parou ou o último estado, você também pode dizer que o HEAD aponta para o pai do próximo commit ou é onde a escrita de confirmação ocorrerá.

Eu acho que uma boa metáfora para pensar sobre isso é a cabeça de reprodução e gravação em um gravador de fita cassete. Quando começamos a gravar o áudio, a fita passa pela cabeça e é gravada nela. quando pressionamos Parar, o local em que a cabeça de gravação está parada é o local que ela começará a gravar novamente quando pressionar a tecla Record novamente. Agora podemos nos mover, podemos mover a cabeça para lugares diferentes, mas onde a cabeça estiver posicionada quando batermos em Record novamente, é onde ele começará a gravar.

O ponteiro HEAD no Git é muito semelhante, aponta para o local em que vamos começar a gravar. É o local em que paramos em nosso repositório pelas coisas que comprometemos.

Suhail Gupta
fonte
0

Em termos simples, HEAD é uma referência ao último commit no ramo de check-out atualmente.

Pense no HEAD como o "ramo atual". Quando você alterna ramificações com o git checkout, a revisão HEAD muda para apontar para a ponta da nova ramificação.

Você pode ver o que o HEAD aponta, fazendo:

cat .git/HEAD

É possível que o HEAD se refira a uma revisão específica que não esteja associada a um nome de filial. Essa situação é chamada de CABEÇA desanexada.

Testilla
fonte