Como o git organiza os arquivos do repositório? - Instituto Eldorado
29 de Setembro de 2026

Como o git organiza os arquivos do repositório?

André

André Schinzel Braga

Autor

Todos nós que trabalhamos com o git estamos acostumados com os commits. Quando dizemos “commit”, imediatamente pensamos no ato de registrar nossas últimas alterações para a posteridade e formar aquela bela sequência histórica do nosso projeto.

Por pura curiosidade, vamos olhar um pouco mais a fundo o que significa um commit e como o git organiza todas as informações que armazena. Nosso ponto de partida é um repo bem simples:

mkdir git_por_dentro && cd git_por_dentro
git init
echo AAAA > a.txt && git add a.txt && git commit -m “Primeira atividade”
echo BBBB > b.txt && git add b.txt && git commit -m “Segunda atividade”
echo CCCC > c.txt && git add c.txt && git commit -m “Terceira atividade”
echo AaaA > a.txt && git add a.txt && git commit -m “Quarta atividade”

É da essência do git: cada commit que criamos é identificado por um hash, um número hexadecimal que permite encontrar exatamente as informações sobre cada uma das versões do nosso projeto.

Observe agora o diretório .git/objects que o git criou em git_por_dentro. Nele há vários diretórios começando por dois dígitos hexadecimais, e dentro deles, há arquivos cujo nome também são números hexadecimais.

O interessante aqui é que, para cada um dos nossos commits, há um arquivo que corresponde ao hash dele, por exemplo: se temos um commit
cc712caea1f4b711af909d060c10bf4b8bc63f81
haverá um arquivo
.git/objects/cc/712caea1f4b711af909d060c10bf4b8bc63f81

Então temos a primeira conclusão: um commit é simplesmente um arquivo binário (mais especificamente, um arquivo texto compactado pelo zlib). Teoricamente, poderíamos usar algum programa que conheça o padrão zlib para descompactá-lo, mas o próprio git permite ver seu conteúdo “puro”. O comando `git cat-file -p <hash_do_commit>` mostrará o conteúdo do arquivo:
tree <um número hexadecimal>
parent <outro número hexadecimal>
author <nome> <email> <timestamp>
committer <nome> <email> <timestamp>
<linha em branco>
<o texto da sua mensagem de commit>

Só de olhar conseguimos reconhecer algumas informações como as identificações do autor e do commiter e o texto que colocamos quando criamos o commit.

Vamos olhar os outros campos agora. O nome “parent” por si só já é uma dica do seu significado. Ele é o hash do commit imediatamente anterior a esse que estamos olhando. É a partir dele que o git monta o histórico quando pedimos o log. Ele olha o “parent” do commit atual, depois o “parent” do “parent”, e assim por diante, até o início do branch.

Até aqui, vemos que o conteúdo do arquivo de commit tem basicamente informações burocráticas (ou “meta dados” para ficar mais elegante): quem, quando, descrição etc. Então… como o git sabe quais arquivos formam aquela versão do projeto? A esta altura, não seria surpresa dizer que é através do único campo que não vimos ainda: o “tree”.

Um arquivo tree é a fotografia do nosso projeto em um instante. Sempre que fazemos um commit no repositório, o git cria uma lista de todos os arquivos que formam o projeto naquele instante. Ele então calcula o hash dela e salva-a no .git/objects. Esse hash é o que aparece no campo tree do commit, como vimos acima. Assim o git sabe quais arquivos formam aquela versão específica do projeto.

Podemos ver essa lista da mesma forma que vimos o conteúdo do arquivo de commit: usando o comando `git cat-file -p <hash_da_tree>`. O resultado será algo do tipo:
<atributos> blob <número hexadecimal> <nome do primeiro arquivo>
<atributos> blob <outro número hexadecimal> <nome do segundo arquivo>
<atributos> blob <mais um número hexadecimal> <nome do terceio arquivo>

O campo <atributos> quase sempre aparece como 100644 (arquivo normal) ou 100755 (arquivo executável), mas não entraremos em detalhes sobre isso.
A palavra “blob” indica que a linha descreve um arquivo do nosso projeto e não um subdiretório (neste caso veríamos a palavra “tree” e sim, pode haver aninhamento de trees em estruturas de diretórios mais complexas, mas também não vamos tratar disso).

Depois vemos um hash e o nome do arquivo em questão. E agora você deve estar se perguntando: sim, eu vejo o nome do arquivo, mas onde está o seu conteúdo?

A resposta está nesse hash junto ao nome do arquivo. E… surpresa! Há um arquivo no .git/objects que corresponde a esse hash. Se usarmos o mesmo `git cat-file -p <hash_do_blob>` veremos exatamente o conteúdo do arquivo.

Os blobs são os arquivos que realmente armazenam o conteúdo do nosso projeto. Cada vez que um arquivo é criado ou alterado, seu conteúdo compactado é salvo no .git/objects e identificado pelo seu hash.

Na “terceira atividade” do repositório simples que criamos, temos um projeto com os arquivos a.txt (com o conteúdo AAAA), b.txt e c.txt. Olhando a tree informada no commit dessa terceira atividade, vemos algo parecido com:
100644 blob <um hash> a.txt
100644 blob <outro hash> b.txt
100644 blob <mais um hash> c.txt
A “quarta atividade” alterou o conteúdo do arquivo a.txt para AaaA. Olhando a tree desse commit vemos que esse novo conteúdo do arquivo resultou em um novo hash:
100644 blob <o novo hash deste arquivo> a.txt
100644 blob <o mesmo hash que aparece na tree anterior> b.txt
100644 blob <mais um hash igual ao da tree anterior> c.txt

Observe que os hashes dos blobs b.txt e c.txt não mudam, pois eles não tiveram alterações. Você consegue ver o conteúdo de todos eles com o `git cat-file -p <hash>`

Aqui é onde acontece a mágica do git: ele sempre sabe todo o conteúdo de todas as versões dos arquivos e ocupa relativamente pouco espaço para isso, porque faz uso muito inteligente da compactação e dos hashes.

Mas, onde aplico isso?

Primeiro: amor à ciência… saber pelo prazer de saber.

Segundo: Imagine um projeto com dois branches, cada um com seu histórico. Se observarmos que, independentemente dos commits, eles têm as mesmas trees, teremos certeza de que todos os arquivos são idênticos, com mesmos nomes e atributos. O que pode diferir é a sua história (ou seja, a sequência de commits que levou até aquela versão), mas o conteúdo é o mesmo.

Terceiro: Você não precisa saber esses detalhes para usar o git muito bem. Eventualmente, conhecer o funcionamento “por dentro” ajuda a compreender e tirar melhor proveito dos recursos mais complexos do git, como o cherry-pick, rebase, merge etc.

Cadastre-se em nossa newsletter

Ao se cadastrar aqui você concorda com a nossa Política de Privacidade.