Git | A anatomia de um commit no git

Lilian Lima
Devs JavaGirl
Published in
3 min readJun 10, 2019

Essa é a primeira publicação de uma série onde compartilho como as coisas acontecem nos bastidores do Git, além do comandos, conceitos.

Você já reparou que ao gerar um commit no git você recebe um identificador único com 40 posições? Esse identificador na verdade é um código hash SHA-1 gerado por um algoritmo a partir de uma porção de dados.

E que porção de dados é essa considerada na geração do hash?

Existem 4 tipos de objetos que são armazenados no git: commit objects, annotaded tag objects, blobs and tree objects, para iniciar o detalhamento desses objetos considere a seguinte estrutura de arquivos:

Cada arquivo no Git é armazenado como um objeto blob, por exemplo, a partir do conteúdo do arquivo logo.png ele gera um hash que será armazenado em algum lugar endereçável como aa1b2fb696a831c89c53f787e03d863691d2b671 . O mesmo ocorre com o arquivo app.css que é armazenado em 4c511f16ef2644854d04cabebfcecc82be0eb04f e assim também acontece com o arquivo app.js. Ótimo, e como o Git relaciona o arquivo logo.png com o hash aa1b2fb696a831c89c53f787e03d863691d2b671?

Os arquivos logo.png e app.css estão no mesmo diretório assets, e este diretório é representado como um tree object, ele trabalha como um mapa, ele relaciona o nome do arquivo ao hash gerado a partir de seu conteúdo, como exemplificado abaixo:

Atrás de um hash pode existir um simples arquivo, armazenado como blob, ou outro tree object, como nessa representação “gitiana” da estrutura de arquivos completa:

A pasta assets e o arquivo app.js estão no mesmo diretório e num nível superior aos arquivos logo.png e app.css, e novamente o mapeamento é aplicado fazendo a associação do nome asset (diretório) ao hash 7cf2a17f3345635d59e063cffddd23573b6e4a75, repare que aqui o conteúdo não é de um arquivo, mas de um tree object filho, pois ele está debaixo do diretório raiz “.” . E o arquivo app.js é associado ao hash 29bfcf9fa5824331081b31f0c307806c6f6b6f06. E, se subirmos ao topo da estrutura veremos que o diretório raiz também está associado a um hash, 9c435a86e664be00db0d973e981425e4a3ef3f8d.

Quando você executa o comando git add o git bate uma foto (snapshot) do working directory e a armazena em sua memória interna, quando você executar o comando git commit o seguinte objeto de commit num pseudo código será gerado:

sha1(
commit message => feature commit”
committer => Lilian Lima < lilian.lima@mail.com>
commit date => Sat Jun 8 09:15:59 2019 +0100
author => Lilian Lima < lilian.lima@mail.com>
author date => Sat Jun 8 09:15:59 2019 +0100
tree => 508222e4b5ba555711173ff140a6263bef867166
parents => [d0957cc8c91520eedcd3807baa96170020812f0e]
)

Só reforçando, o objeto de commit é composto pelo metadata do commit+ tree object (snapshot do working directory) + identificador do commit antecessor/ancestral/pai

E adivinhem o que o Git faz com esse objeto de commit?!? Gera um hash dele também e é esse identificador que visualizamos ao executarmos um git log.

O Git utiliza essa abordagem de criptografia para assegurar a integridade dos commits, caso um bit seja alterado no commit realizado, mesmo que seja um espaço em branco num arquivo, um novo identificador será gerado.

Esse post é quase uma transcrição desse outro post: https://blog.thoughtram.io/git/2014/11/18/the-anatomy-of-a-git-commit.html

--

--

Lilian Lima
Devs JavaGirl

{“ocupação”: “software engineer”, “idioma computacional”: “java”, “um hobby”:” escrever”,” um valor”:” justiça social”, “um amor”: “minha família 💙”}