Na última dica, visitamos o objetivo do índice. Mas o que é isso realmente?
Na verdade, não é uma tree, como me referi da última vez. Ou seja, você não pode iterar os conteúdos com git ls-tree. Ele aponta para blobs no objeto do banco de dados↳Banco de dados134 conteúdosSQL ou NoSQL: eis a questão!!Data · mar 2020Banco de dados: como organizar e dar segurança para milhões de dados de loteriasData · mai 20215 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data →, no entanto. Então, por que precisamos de um tipo diferente de objeto para se referir ao índice?
Algumas das razões são orientadas para o desempenho. Sempre que você faz um diff (ou outra operação repository-wide), o Git precisa de forma rápida e eficiente calcular se o estado da working tree mudou desde o último índice. Algumas ferramentas, incluindo o prompt shell, precisam ser capazes de determinar se a working tree é suja ou não rapidamente:
(master) $ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>…" to update what will be committed)
# (use "git checkout -- <file>…" to discard changes in working directory)
#
# modified: example
#
no changes added to commit (use "git add" and/or "git commit -a")
(master) $ export GIT_PS1_SHOWDIRTYSTATE=true
(master *) $
Se o Git só sabe se a tree está suja fazendo uma caminhada completa pelos de conteúdo (e calculando seus hashes SHA1), essa operação seria proibitivamente dispendiosa. Felizmente, o Git tem um número de otimizações que lhe permite evitar isso.
O índice armazena não apenas os nomes de arquivos, mas também o tempo da última modificação dos mesmos. Como resultado, o Git sabe se houve quaisquer alterações nos timestamps, por iteração de metadados dos arquivos e comparando os timestamps com os do índice. Se estiver faltando um arquivo do índice, ele é representado como uma adição. Se estiver faltando um arquivo do disco, ele é representado como uma exclusão. Se a data de modificação de um arquivo é diferente, em seguida, este é representado como uma modificação.
Além de armazenar timestamps, o índice armazena os hashes SHA1 de cada blob. Isso permite que o índice se atualize sozinho, se o arquivo for revertido para um estado anterior, mas com um timestamp mais recente.
Finalmente, o índice é também utilizado para merges de processamento. No índice, existe um conceito de ter números de índice múltiplos (ou números de fase). Normalmente, apenas 0 é utilizado, uma vez que ele representa o estado atual da working tree. No entanto, se um conflito de merge surge, então o índice é usado para resolver a ambiguidade do estado dos arquivos em cada nível. Se você tem um conflito, então stage 0 é usado para representar a working tree atual, o stage 1 é utilizado para a sua mudança, então o stage 2 e 3 para as outras diferenças. Você pode ver o número do stage, executando git ls-files –stage (ou -s):
(master) $ git status
(master) $ git ls-files -s
100644 ce013625030ba8dba906f756967f9e9ca394464a 0 example
(master) $ git pull # with known conflict
Auto-merging example
CONFLICT (content): Merge conflict in example
Automatic merge failed; fix conflicts and then commit the result.
(master|MERGING) $ git ls-files -s
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 1 example
100644 a895c0db0a627cb9451ae390a2a0922495dbb161 2 example
100644 13940d48c3d3693113f7543d4fc5423a916ef55d 3 example
O arquivo do stage 1 aqui é o lugar dos dois arquivos derivados, para que possamos fazer 1..2 e 1..3 diffs para descobrir qual cada lado da tree mudou desde então. (Os mais astutos de vocês irão reconhecer e69…391 como o arquivo vazio.) Nós podemos mostrar o conteúdo dessas versões dos arquivos, ou carregá-los em uma ferramenta de comparação de 3 vias, se você tem tal coisa:
(master) $ git show e69de #empty file
(master) $ git show a895c
Left tree
(master) $ git show 13940
Right tree
Claro que, normalmente, o Git vai lidar com os diffs para você, e você não precisa se preocupar com as mudanças específicas, nem extrair o conteúdo de fora do índice. Mas ele ressalta o fato de que quando você terminar de fazer um merge de um único arquivo, executando git add no arquivo, coloca uma cópia em stage 0 do índice, removendo os índices 1,2,3:
(master|MERGING) $ git add example
(master|MERGING) $ git ls-files -s
100644 319c128291474d30f48e721ca87bd10425e8e296 0 example
É por isso que fazer merge de grandes alterações em conflito com o Git é fácil. Cada arquivo pode ser abordado em uma base “arquivo por arquivo”; quando você terminar de fazer o merge de um arquivo, você pode fazer um add dele no índice, que registra os seus conteúdos, bem como remove os outros arquivos do status de merge. Fazer o merge de muitos arquivos torna-se então um exercício de fusão um por um, e adições conforme você continua. E uma vez que todos eles são transitoriamente armazenados no índice, você pode continuar adicionando-os até que esteja pronto para executar um git commit.
?
Texto original disponível em http://alblue.bandlem.com/2011/10/git-tip-of-week-index-revisited.html






