O Que Acontece Quando Você Faz um Commit: Um Mergulho Profundo no Git

1. O que é o Git? O Git é um sistema de controle de versão distribuído que permite aos desenvolvedores gerenciar e acompanhar alterações em arquivos de projetos. Ele armazena imagens do sistema de arquivos em miniatura, salvando apenas referências para arquivos não alterados, o que torna suas operações rápidas e eficientes. 2. Os Três Estados Os arquivos no Git podem estar em três estados principais: Modified: O arquivo foi modificado. Staged: O arquivo está preparado para o próximo commit. Committed: O arquivo foi salvo no banco de dados local. 3. Como o Git Garante a Integridade dos Arquivos? Tudo no Git passa por uma soma de verificações (checksum) antes de ser armazenado e é referenciado por esse checksum. Isso torna impossível alterar o conteúdo de qualquer arquivo ou pasta sem que o Git saiba. O mecanismo de verificação é chamado de hash SHA-1, uma sequência de 40 caracteres hexadecimais (ex.: fa7064f204b8bb4ade5eed778ee1e278e54559d2), calculada com base no conteúdo de uma estrutura de arquivo ou diretório no Git. Para gerar um hash SHA-1 no linux: echo -e 'Hello, World!' | sha1sum 60fde9c2310b0d4cad4dab8d126b04387efba289 E caso seja removido algum caractere da string? echo -e 'Hello, World' | sha1sum 4ab299c8ad6ed14f31923dd94f8b5f5cb89dfb54 Percebe-se que o valor mudou. Dessa forma, o Git garante a integridade dos arquivos. 4. Estrutura Básica de Pastas Ao iniciar um projeto no Git, é criado o diretório de trabalho .git, que contém a seguinte estrutura: git init ls -F1 .git Estrutura Descrição HEAD Aponta para a branch atual. config Contém opções de configuração específicas do projeto. description Usado pelo GitWeb, pode ser ignorado. hooks Scripts que podem ser executados em operações como commit e merge. info Mantém o arquivo exclude global para padrões ignorados. objects Guarda todo o conteúdo do banco de dados de objetos. refs Guarda referências para objetos de commit. index Guarda informações da staging area. Os principais diretórios são: objects, refs e HEAD. 5. Plumbing vs. Porcelain Existem duas categorias de comandos no Git: Plumbing: Comandos de baixo nível, que oferecem acesso ao funcionamento interno do Git. Porcelain: Comandos amigáveis usados no dia a dia. Para os comandos porcelain, este guia expõe os comandos do dia a dia: Git Cheatsheet 6. Objetos O Git utiliza uma estrutura de dados baseada em objetos para armazenar informações sobre o repositório. Existem três tipos principais de objetos: Blobs Trees Commits 6.1 Blobs Um blob é um objeto que contém o conteúdo de um arquivo. Ele não armazena informações sobre o nome do arquivo ou o diretório em que está localizado. Para criar um blob, utiliza-se o comando plumbing: hash-object: echo 'Hello, World!' | git hash-object -w --stdin 8ab686eafeb1f44702738c8b0f24f2567c36da6d -w: Informa ao hash-object para armazenar o objeto. --stdin: Informa ao comando para ler o conteúdo do stdin. Se você não especificar, o parâmetro é o caminho para um arquivo. O comando hash-object não apenas faz o hash do conteúdo, ele adiciona algumas informações importantes para o funcionamento interno, como: o tipo do objeto, o tamanho do conteúdo e o delimitador. Para o exemplo Hello, World! fica dessa forma: blob 14\0Hello, World!. Então, dessa obtêm-se o mesmo valor nesses dois casos: echo 'Hello, World!' | git hash-object -w --stdin 8ab686eafeb1f44702738c8b0f24f2567c36da6d echo -e 'blob 14\0Hello, World!' | sha1sum 8ab686eafeb1f44702738c8b0f24f2567c36da6d Para visualizar como o Git armazenou os dados: find .git/objects -type f .git/objects/8a/b686eafeb1f44702738c8b0f24f2567c36da6d Para recuperar o conteúdo do arquivo: git cat-file -p Hello, World! 6.2 Trees Os objetos tree resolvem o problema de armazenar o nome do arquivo e também permitem armazenar de forma conjunta um grupo de arquivos. Para agrupar os objetos blobs na área de staging em uma estrutura de árvore (tree): Criar um arquivo: echo 'Hello, World!' > hello-world.txt Gerar um hash SHA-1 para esse arquivo: git hash-object -w hello-world.txt Usar o comando plumbing update-index para adicionar o blob à área de staging e dar um nome a ele: git update-index \ --add \ --cacheinfo 100644 \ \ hello-world.txt --add: Adiciona o blob à área de staging --cacheinfo ,,: Registra um arquivo que ainda não está no diretório de trabalho (.git). Alguns dos Modos UNIX Válidos no Git: 100644: Arquivo normal (permissões de leitura e escrita para o proprietário, leitura para o grupo e outros). 100755: Arquivo executável (permissões de leitura, escrita e execução para o proprietário, leitura e execução para o grupo e outros). 120000: Link simbólico (um ponteiro para outro arquivo ou diretório). E pode ser adicionado outros blobs à área de staging, após isso, já pode ser cr

Apr 7, 2025 - 20:21
 0
O Que Acontece Quando Você Faz um Commit: Um Mergulho Profundo no Git

1. O que é o Git?

O Git é um sistema de controle de versão distribuído que permite aos desenvolvedores gerenciar e acompanhar alterações em arquivos de projetos. Ele armazena imagens do sistema de arquivos em miniatura, salvando apenas referências para arquivos não alterados, o que torna suas operações rápidas e eficientes.

2. Os Três Estados

Os arquivos no Git podem estar em três estados principais:

  • Modified: O arquivo foi modificado.
  • Staged: O arquivo está preparado para o próximo commit.
  • Committed: O arquivo foi salvo no banco de dados local.

3. Como o Git Garante a Integridade dos Arquivos?

Tudo no Git passa por uma soma de verificações (checksum) antes de ser armazenado e é referenciado por esse checksum. Isso torna impossível alterar o conteúdo de qualquer arquivo ou pasta sem que o Git saiba. O mecanismo de verificação é chamado de hash SHA-1, uma sequência de 40 caracteres hexadecimais (ex.: fa7064f204b8bb4ade5eed778ee1e278e54559d2), calculada com base no conteúdo de uma estrutura de arquivo ou diretório no Git.

Para gerar um hash SHA-1 no linux:

echo -e 'Hello, World!' | sha1sum
60fde9c2310b0d4cad4dab8d126b04387efba289

E caso seja removido algum caractere da string?

echo -e 'Hello, World' | sha1sum
4ab299c8ad6ed14f31923dd94f8b5f5cb89dfb54

Percebe-se que o valor mudou. Dessa forma, o Git garante a integridade dos arquivos.

4. Estrutura Básica de Pastas

Ao iniciar um projeto no Git, é criado o diretório de trabalho .git, que contém a seguinte estrutura:

git init
ls -F1 .git
Estrutura Descrição
HEAD Aponta para a branch atual.
config Contém opções de configuração específicas do projeto.
description Usado pelo GitWeb, pode ser ignorado.
hooks Scripts que podem ser executados em operações como commit e merge.
info Mantém o arquivo exclude global para padrões ignorados.
objects Guarda todo o conteúdo do banco de dados de objetos.
refs Guarda referências para objetos de commit.
index Guarda informações da staging area.

Os principais diretórios são: objects, refs e HEAD.

5. Plumbing vs. Porcelain

Existem duas categorias de comandos no Git:

  • Plumbing: Comandos de baixo nível, que oferecem acesso ao funcionamento interno do Git.
  • Porcelain: Comandos amigáveis usados no dia a dia.

Para os comandos porcelain, este guia expõe os comandos do dia a dia: Git Cheatsheet

6. Objetos

O Git utiliza uma estrutura de dados baseada em objetos para armazenar informações sobre o repositório. Existem três tipos principais de objetos:

  1. Blobs
  2. Trees
  3. Commits

6.1 Blobs

Um blob é um objeto que contém o conteúdo de um arquivo. Ele não armazena informações sobre o nome do arquivo ou o diretório em que está localizado.

  • Para criar um blob, utiliza-se o comando plumbing: hash-object:
echo 'Hello, World!' | git hash-object -w --stdin
8ab686eafeb1f44702738c8b0f24f2567c36da6d
  • -w: Informa ao hash-object para armazenar o objeto.
  • --stdin: Informa ao comando para ler o conteúdo do stdin. Se você não especificar, o parâmetro é o caminho para um arquivo.

O comando hash-object não apenas faz o hash do conteúdo, ele adiciona algumas informações importantes para o funcionamento interno, como: o tipo do objeto, o tamanho do conteúdo e o delimitador.

Para o exemplo Hello, World! fica dessa forma: blob 14\0Hello, World!.

Então, dessa obtêm-se o mesmo valor nesses dois casos:

echo 'Hello, World!' | git hash-object -w --stdin
8ab686eafeb1f44702738c8b0f24f2567c36da6d
echo -e 'blob 14\0Hello, World!' | sha1sum
8ab686eafeb1f44702738c8b0f24f2567c36da6d

Para visualizar como o Git armazenou os dados:

find .git/objects -type f
.git/objects/8a/b686eafeb1f44702738c8b0f24f2567c36da6d

Para recuperar o conteúdo do arquivo:

git cat-file -p 
Hello, World!

6.2 Trees

Os objetos tree resolvem o problema de armazenar o nome do arquivo e também permitem armazenar de forma conjunta um grupo de arquivos.

Para agrupar os objetos blobs na área de staging em uma estrutura de árvore (tree):

  1. Criar um arquivo:
echo 'Hello, World!' > hello-world.txt
  1. Gerar um hash SHA-1 para esse arquivo:
git hash-object -w hello-world.txt
  1. Usar o comando plumbing update-index para adicionar o blob à área de staging e dar um nome a ele:
git update-index \
--add \
--cacheinfo 100644 \
 \
hello-world.txt
  • --add: Adiciona o blob à área de staging
  • --cacheinfo ,,: Registra um arquivo que ainda não está no diretório de trabalho (.git).

    Alguns dos Modos UNIX Válidos no Git:

    • 100644: Arquivo normal (permissões de leitura e escrita para o proprietário, leitura para o grupo e outros).
    • 100755: Arquivo executável (permissões de leitura, escrita e execução para o proprietário, leitura e execução para o grupo e outros).
    • 120000: Link simbólico (um ponteiro para outro arquivo ou diretório).

    E pode ser adicionado outros blobs à área de staging, após isso, já pode ser criado um objeto tree com o comando plumbing write-tree:

    git write-tree
    43b603fc7207c1f84ba7e65934181336a0e68b92
    

    Para visualizar, basta utilizar o comando cat-file:

    git cat-file -p 
    100644 blob 8ab686eafeb1f44702738c8b0f24f2567c36da6d    hello-world.txt
    

    Mas ainda falta algo: Onde está as informações do autor, a data da modificação e a mensagem?

    6.3 Commits

    Os objetos commit armazenam informações essenciais sobre as alterações feitas no repositório. Cada objeto commit contém:

    • Um ponteiro para um objeto tree, que representa o estado do diretório no momento do commit.
    • Informações sobre o autor do commit (nome e e-mail).
    • A data e hora em que o commit foi feito (timestamp).
    • Uma mensagem de commit que descreve as alterações realizadas.
    • Um ponteiro para o commit anterior (ou commits, no caso de merges), permitindo a construção de um histórico de alterações.

    O comando plumbing commit-tree é o encarregado para criar um objeto commit:

    git commit-tree 43b60 -m 'mensagem do commit'
    21cc9199e22c5eb10731608f88d99a3bb147b2eb
    

    Para visualizar o objeto commit, basta utilzar o comando plumbing cat-file:

    git cat-file -p 
    tree 43b603fc7207c1f84ba7e65934181336a0e68b92
    author Gustavo Vasconcelos  1744048435 -0300
    committer Gustavo Vasconcelos  1744048435 -0300
    
    mensagem do commit
    

    É possível também aninhar commits passando o hash do commit anterior para que eles tenham uma linha do tempo:

    1. Gerar hash:
    'Para um segundo commit' | git hash-object -w --stdin
    fa538a1ae921322d20bc39c86135ec528c261e1f
    
    1. Adicionar a área de staging:
    git update-index \
    --add \
    --cacheinfo 100644 \
    fa538a1ae921322d20bc39c86135ec528c261e1f \
    hello-world.txt
    
    1. Criar o objeto tree:
    git write-tree
    a687f3f49545dba2ff9a424891d445b59c107893
    
    1. Criar o objeto commit referenciando o commit anterior:
    git commit-tree a687f -m 'segundo commit' -p 21cc9
    a3e6aedbac6c7e8c33db0cd6490658c8b3519dd3
    
    • -p: Usa para referenciar o commit anterior.

    Pode-se utilizar o comando porcelain log para visualizar o histórico:

    git log --stat 6aa7e
    commit 6aa7e37d8ad583deaee0783462fb62a241c5b9c1
    Author: Gustavo Vasconcelos 
    Date:   Mon Apr 7 15:17:01 2025 -0300
    
        segundo commit
    
     hello-world.txt | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    commit 21cc9199e22c5eb10731608f88d99a3bb147b2eb
    Author: Gustavo Vasconcelos 
    Date:   Mon Apr 7 14:53:55 2025 -0300
    
        mensagem do commit
    
     hello-world.txt | 1 +
     1 file changed, 1 insertion(+)
    

    Basicamente este é o ciclo de vida de uma modificação até um commit no Git, tudo baseado em chave-valor e armazenado no banco de dados local, e agora dá pra entender como o git busca tão rapidamente alterações feitas em um projeto, independente do tamanho ou do tempo que o projeto existe.

    This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies.