Qual é a diferença entre HEAD, árvore de trabalho e índice, no Git?

488

Alguém pode me dizer a diferença entre HEAD, árvore de trabalho e índice, no Git?

Pelo que entendi, todos são nomes para ramos diferentes. Minha suposição está correta?


Editar

Eu achei isto

Um único repositório git pode rastrear um número arbitrário de ramificações, mas sua árvore de trabalho está associada a apenas uma delas (a ramificação "atual" ou "com saída") e o HEAD aponta para essa ramificação.

Isso significa que HEAD e árvore de trabalho são sempre as mesmas?

Joyce Babu
fonte
26
Com relação à sua edição: absolutamente não. HEADé o commit na ponta da ramificação atual. Se você acabou de verificar a ramificação, ou seja, não possui arquivos modificados, seu conteúdo corresponde à árvore de trabalho. Assim que você modifica algo, ele não corresponde mais.
Cascabel
6
Eu acho que você tem que ler isto: think-like-a-git.net #
Andrzej Duś
5
Eu também adicionaria um Staging Areaa essa lista. O que é HEAD, Working Tree, Indexe umStaging Area
Verde
2
A última frase do @ Jefromi's seria mais clara como:> Assim que você modifica alguma coisa, a árvore de trabalho não corresponde mais ao commit HEAD
starscream_disco_party 8/16
3
Para quem ler isso no futuro, a melhor maneira de entender verdadeiramente algumas dessas respostas é ver, sentir e conceitualizar visualmente o que está acontecendo: esta é a melhor ferramenta para aprender o git de todos os tempos: onlywei.github.io/explain-git-with -D3 / # fetchrebase
BKSpurgeon

Respostas:

579

Algumas outras boas referências sobre esses tópicos:

texto alternativo

Eu uso o índice como um ponto de verificação .

Quando estou prestes a fazer uma alteração que pode dar errado - quando quero explorar uma direção que não tenho certeza se posso seguir adiante ou mesmo se é uma boa ideia, como uma refatoração ou mudança conceitual exigente tipo de representação - eu verifico meu trabalho no índice. Se esta é a primeira alteração que fiz desde a minha última confirmação, posso usar o repositório local como um ponto de verificação, mas geralmente tenho uma alteração conceitual que estou implementando como um conjunto de pequenas etapas. Desejo verificar o ponto após cada etapa, mas salve o commit até voltar ao trabalho, código testado.

Notas:

  1. o espaço de trabalho é a árvore de diretórios dos arquivos (de origem) que você vê e edita.

  2. O índice é um arquivo binário único e grande, <baseOfRepo>/.git/indexque lista todos os arquivos da ramificação atual, suas somas de verificação sha1 , registros de data e hora e o nome do arquivo - não é outro diretório com uma cópia dos arquivos.

  3. O repositório local é um diretório oculto ( .git), incluindo um objectsdiretório que contém todas as versões de cada arquivo no repositório (ramificações locais e cópias de ramificações remotas) como um arquivo compactado "blob".

Não pense nos quatro 'discos' representados na imagem acima como cópias separadas dos arquivos de recompra.

texto alternativo

Eles são basicamente referências nomeadas para confirmações do Git. Existem dois tipos principais de referências: tags e heads.

  • Tags são referências fixas que marcam um ponto específico no histórico, por exemplo, v2.6.29.
  • Pelo contrário, os chefes são sempre movidos para refletir a posição atual do desenvolvimento do projeto.

texto alternativo

(observação: como comentado por Timo Huovinen , essas setas não são o que as confirmações apontam, é a ordem do fluxo de trabalho , basicamente mostrando as setas como 1 -> 2 -> 3 -> 4onde 1está o primeiro commit e 4o último)

Agora sabemos o que está acontecendo no projeto.
Mas, para saber o que está acontecendo aqui e agora, há uma referência especial chamada HEAD. Serve para dois propósitos principais:

  • informa ao Git qual commit para obter arquivos quando você faz o checkout e
  • diz ao Git onde colocar novos commit quando você faz o commit.

Quando você o executa git checkout ref, aponta HEADpara o árbitro que você designou e extrai arquivos dele. Quando você executa, git commitele cria um novo objeto de confirmação, que se torna filho do atual HEAD. Normalmente HEADaponta para uma das cabeças, então tudo funciona muito bem.

texto alternativo

VonC
fonte
20
Depois de ler muitas vezes sobre o idiota, nunca entendi completamente. Fiquei realmente frustrado e quero usar a palavra f; Mas estou em comunidade! Você mencionou cabeças, mas nas imagens acima há sempre uma única CABEÇA onde estão as cabeças restantes? "Normalmente, HEAD aponta para uma das cabeças, então tudo funciona muito bem." Eu imploro para você explicar isso, sua declaração.
precisa saber é o seguinte
12
@neckTwi HEAD é o commit atual com o qual você está trabalhando ( stackoverflow.com/a/964927/6309 ). Geralmente é uma das "cabeças do ramo" (um dos commits referenciados pelos ramos, representando a ponta dos referidos ramos). Mas você pode fazer o checkout (e trabalhar) em qualquer commit. Se você efetuar o check-out de um commit que não seja um dos chefes (de ramificação), você estará no modo "desanexado HEAD": stackoverflow.com/a/3965714/6309
VonC:
1
@Irmay, eu concordo, mas foi assim que eu encontrei essas fotos há 5 anos ( hades.name/blog/2010/01/28/… )
VonC
11
Em relação ao índice, acho que a coisa mais útil que se pode dizer é "O índice é apenas outro nome para a área de preparação", como @ ashraf-alam disse. Eu sinto que na maioria das vezes em discussão é referida como a área de preparação, e é por isso que não estabeleci automaticamente a conexão de que era a mesma coisa que o índice.
Pete
1
@Pete Eu concordo. Para saber mais sobre a diferença entre cache e índice, consulte minha outra resposta stackoverflow.com/a/6718135/6309
VonC 8/16/16
137

A diferença entre HEAD (ramificação atual ou último estado confirmado na ramificação atual), índice (também conhecido como área de preparação) e árvore de trabalho (o estado dos arquivos no checkout) é descrita na seção "Os três estados" do "1.3 Git Basics " capítulo do livro Pro Git de Scott Chacon (licença Creative Commons).

Aqui está a imagem que ilustra este capítulo:

Operações locais - diretório de trabalho x área de armazenamento temporário (índice) vs repositório git (HEAD)

Na imagem acima, "diretório de trabalho" é o mesmo que "árvore de trabalho", "área de preparação" é um nome alternativo para git "index", e HEAD aponta para a ramificação com check-out atualmente, cujo ponto de ponta é o último commit no " diretório git (repositório) "

Observe que git commit -aisso prepararia mudanças e confirmaria em uma etapa.

Jakub Narębski
fonte
1
"Uma imagem vale mais que mil palavras". Obrigado Jakub .. E obrigado pelo link.
Joyce Babu
5
Nota: working treeparece ser preferido working directoryhoje em dia. Veja github.com/git/git/commit/…
VonC
3
Essa imagem não é exatamente precisa porque a Área de Preparação está contida em um único arquivo chamado "índice" - e esse arquivo de índice está na raiz do diretório .git. Portanto, se você definir o repositório como o diretório .git, a área de preparação estará tecnicamente dentro do repositório. A terceira coluna seria melhor rotulada como "objeto da árvore Raiz do HEAD" para indicar que os arquivos com check-out são provenientes de um objeto de confirmação e que o commit grava uma nova árvore em um objeto de commit - ambos os objetos de commit são apontados pelo HEAD.
Jazimov 28/04
@Jazimov Você provavelmente está certo, mas como ele escreveu, ele tirou essa foto do conhecido livro Pro Git e forneceu um link. Assim, se a imagem puder ser aprimorada ou estiver errada, alguém deve contar aos autores desse livro ... Em geral, eu estaria disposto a fazer isso, mas, para ser sincero, ainda sou um iniciante e não tenho ainda entendi o que você disse, então eu sou definitivamente a pessoa errada nesse caso.
Binarus 6/08
@Binarus: O perigo na reprodução por atacado de imagens como essa é que ela serve para propagar uma "deturpação" feita por um autor / livro. Penso que este é um caso de interpretações literais versus funcionais aqui: no sentido literal, o índice de fato está contido no repositório se você definir o repositório como tudo na pasta .git. No sentido funcional, no entanto, o índice ajuda o Git a manter o DAG no repositório e pode ser considerado um ser externo a ele.
Jazimov 6/08/19
64

Sua árvore de trabalho é o que realmente está nos arquivos nos quais você está trabalhando atualmente.

HEADé um ponteiro para a ramificação ou confirmação que você fez check-out pela última vez e que será o pai de uma nova confirmação, se você fizer isso. Por exemplo, se você estiver no masterramo, HEADapontará para master, e quando você confirmar, esse novo commit será um descendente da revisão masterapontada e masterserá atualizado para apontar para o novo commit.

O índice é uma área de preparação onde a nova confirmação é preparada. Essencialmente, o conteúdo do índice é o que entrará no novo commit (embora, se você fizer git commit -aisso, isso adicionará automaticamente todas as alterações nos arquivos que o Git conhece no índice antes de confirmar, para confirmar o conteúdo atual da sua árvore de trabalho ) git addadicionará ou atualizará arquivos da árvore de trabalho no seu índice.

Brian Campbell
fonte
Muito obrigado pela explicação Brian. Portanto, a árvore de trabalho contém todas as alterações não confirmadas. Se eu confirmar minhas alterações com o git commit -a, nesse momento específico, minha Árvore de Trabalho e Índice serão os mesmos. Quando eu for para o meu repositório central, todos os três serão os mesmos. Estou correcto?
precisa saber é o seguinte
3
@ Vinod Praticamente. Você pode ter arquivos em sua árvore de trabalho que o Git não conhece, e esses não serão comprometidos git commit -a(é necessário adicioná-los git add), para que sua árvore de trabalho possa ter arquivos extras que seu índice, seu repositório local ou seu repo remoto não possui.
Brian Campbell
2
@ Vinod: A árvore de trabalho e o índice podem se tornar os mesmos sem confirmar (o git add atualiza o índice da árvore de trabalho, e o git checkout <path> atualiza a árvore de trabalho do índice). HEADrefere-se à confirmação mais recente; portanto, ao confirmar, você está atualizando HEADpara a nova confirmação, que corresponde ao índice. Empurrar não tem muito a ver com isso - ele cria ramificações nas ramificações de correspondência remota no seu repositório local.
Cascabel
45

Árvore de trabalho

Sua árvore de trabalho são os arquivos nos quais você está trabalhando no momento.

Índice Git

  • O git "index" é onde você coloca os arquivos que deseja confirmar no repositório git.

  • O índice também é conhecido como o cache , cache de diretório , cache do diretório atual , área de preparação , encenado arquivos .

  • Antes de "confirmar" (fazer check-in) os arquivos no repositório git, você precisa primeiro colocar os arquivos no "index" git.

  • O índice não é o diretório ativo: você pode digitar um comando como git status, e o git informará quais arquivos no seu diretório ativo foram adicionados ao índice git (por exemplo, usando o git add filenamecomando).

  • O índice não é o repositório git: arquivos no índice git são arquivos que o git confirmaria no repositório git se você usasse o comando git commit.

Ashraf Alam
fonte
1
Observe que o Git 2.5 trará várias árvores de trabalho ( stackoverflow.com/a/30185564/6309 ). +1
VonC
3
Não tenho certeza de que "O índice não seja o diretório de trabalho" esteja 100% correto. Deveria ser "O índice não é o diretório de trabalho, mas inclui todo o diretório de trabalho + alterações que você deseja confirmar em seguida". Prova? vá para um repositório git, reset --hard HEADpara garantir que seu índice == sua árvore de trabalho. an then: mkdir history && git checkout-index --prefix history/ -aO resultado é uma duplicação de toda a sua árvore de trabalho no seu history/diretório. Ergo git index> = diretório de trabalho git
Adam Kurkiewicz
3
O índice não é o diretório ativo e não precisa incluir o diretório ativo. O índice é apenas um arquivo no repositório git que armazena informações sobre o que você deseja confirmar.
Boon
3
"O" índice "mantém uma captura instantânea do conteúdo da árvore de trabalho e é essa captura instantânea que é tomada como o conteúdo da próxima confirmação. Assim, depois de fazer alterações no diretório de trabalho e antes de executar o comando de confirmação, você deve usar o comando add para adicionar arquivos novos ou modificados ao índice "( git-scm.com/docs/git-add )
anth 15/15
3
@ AdamKurkiewicz: a prova falhará se você primeiro echo untracked-data > untracked-file, antes ou depois das etapas git reset --HARDe git checkout-index. Você descobrirá que o arquivo não rastreado não está no historydiretório Você também pode modificar o índice e a árvore de trabalho de forma independente, embora a modificação do índice sem primeiro tocar na árvore de trabalho seja difícil (requer uso git update-index --index-info).
Torek