🧠FFVAcademy
🌿

Git de verdade: commit, branch, merge, rebase, reflog

16 min de leitura·+80 XP
Pré-requisitos (0/1)0%

Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.

Git é o sistema de controle de versão mais usado do mundo — e também o mais mal-entendido. A maioria aprende os comandos sem entender o modelo mental subjacente. Quando você entende o que Git realmente armazena, tudo faz sentido: merge, rebase, reset, cherry-pick viram operações previsíveis.

O que Git realmente armazena: objetos e o DAG

Git não armazena diffs — armazena snapshots. Cada commit é uma foto completa do projeto naquele momento. Git é eficiente porque objetos idênticos (mesmo conteúdo → mesmo hash SHA-1) são armazenados apenas uma vez.

Existem 4 tipos de objetos no Git:

# Blob — conteúdo de um arquivo (sem nome, sem permissão)
git cat-file -p a1b2c3   # mostra conteúdo de um blob

# Tree — diretório (lista de blobs e outras trees com nomes e permissões)
# 100644 blob a1b2c3   README.md
# 100755 blob d4e5f6   script.sh
# 040000 tree 789abc   src/

# Commit — aponta para uma tree + metadados + referências ao(s) pai(s)
# tree 789abc...
# parent def012...   ← SHA do commit anterior
# author Fernando ...
# committer Fernando ...
# (linha em branco)
# Mensagem do commit

# Tag — aponta para um commit com anotação

# O histórico é um DAG (Directed Acyclic Graph) de commits:
#   A ← B ← C ← D (main)
#               ↖
#             E ← F (feature)
# D e F são a mesma base C. Após merge: A ← B ← C ← D ← G
#                                                   ↗
#                                             E ← F
# Explorar os objetos internamente
git log --oneline --graph --all   # visualiza o DAG
git cat-file -t SHA               # tipo do objeto (blob/tree/commit/tag)
git cat-file -p SHA               # conteúdo do objeto
ls .git/objects/                  # os arquivos físicos no disco

As três áreas do Git

# Working Directory → Staging Area (Index) → Repository (.git/)

# Estado das mudanças
git status                    # resumo das três áreas
git diff                      # working directory vs staging area
git diff --staged             # staging area vs último commit
git diff HEAD                 # working directory vs último commit

# Movendo mudanças para staging
git add arquivo.txt           # adiciona arquivo inteiro
git add src/                  # adiciona diretório
git add -p                    # interativo: seleciona hunks (partes) a adicionar
git add -A                    # todos os arquivos (novos, modificados, deletados)

# Commit: salva staging no repositório
git commit -m "feat: adiciona autenticação JWT"
git commit --amend            # modifica o ÚLTIMO commit (não use se já fez push)
git commit -v                 # abre editor com o diff completo visível

# Desfazendo staging (sem perder mudanças)
git restore --staged arquivo.txt   # retira do staging, mantém no working dir
git reset HEAD arquivo.txt         # equivalente (forma antiga)

# Desfazendo mudanças no working directory (DESTRUTIVO)
git restore arquivo.txt            # descarta mudanças locais (irrecuperável)
git checkout -- arquivo.txt        # equivalente (forma antiga)

Branches: são só ponteiros para commits

Uma branch no Git é literalmente um arquivo de texto com 40 caracteres: o SHA do commit que ela aponta. Criar uma branch é instantâneo — não copia nada. HEAD é um ponteiro para a branch atual (ou diretamente para um commit, "detached HEAD state").

# Criar e navegar branches
git branch feature/auth           # cria branch no commit atual
git checkout feature/auth         # muda para ela
git checkout -b feature/auth      # cria E muda (atalho)
git switch -c feature/auth        # forma moderna (Git 2.23+)

# Ver branches
git branch                        # branches locais
git branch -r                     # branches remotas
git branch -a                     # todas
git branch -v                     # com último commit de cada

# Deletar branch
git branch -d feature/auth        # deleta se já mergeada
git branch -D feature/auth        # força delete (mesmo sem merge)

# Renomear
git branch -m nome-novo           # renomeia branch atual
git branch -m nome-velho nome-novo

# Mudar de branch (com mudanças em andamento)
git stash                         # salva mudanças temporariamente
git switch outra-branch
git stash pop                     # recupera as mudanças

Merge vs Rebase: qual escolher

Aspectogit mergegit rebase
HistóricoPreserva — cria commit de mergeReescreve — commits novos com mesmos changes
ResultadoCommit com 2 pais (não-linear)Histórico linear
ConflitosResolve uma vez no merge commitResolve em cada commit rebased
Seguro para pushSempreSomente para branches não compartilhadas
Quando usarIntegrar branches públicas (main)Limpar histórico local antes do push
# MERGE — preserva histórico real
git checkout main
git merge feature/auth
# Cria: main → ... → merge-commit (tem dois pais: ultimo-main e ultimo-feature)

# REBASE — reescreve o histórico da feature sobre main
git checkout feature/auth
git rebase main
# Move commits da feature para após o último commit do main
# Os commits da feature são NOVOS (SHAs diferentes), mas com os mesmos changes

# MERGE SQUASH — todos os commits da feature viram 1 commit só em main
git checkout main
git merge --squash feature/auth
git commit -m "feat: autenticação JWT (squash de 5 commits)"
# Útil para manter main com histórico limpo

# INTERACTIVE REBASE — editar, reordenar, squash, fixup commits
git rebase -i HEAD~5    # edita últimos 5 commits
# pick   SHA1  commit 1     → manter
# squash SHA2  commit 2     → juntar com anterior
# fixup  SHA3  commit 3     → juntar sem preservar mensagem
# reword SHA4  commit 4     → mudar mensagem
# drop   SHA5  commit 5     → deletar

Reflog: a rede de segurança do Git

O reflog registra para onde HEAD aponta a cada operação. É local (não vai para o remote) e mantém objetos por ~90 dias. É o que salva quando você faz reset --hard acidentalmente.

# Ver o reflog
git reflog              # últimas ~100 entradas do HEAD
git reflog show main    # reflog de uma branch específica

# Saída típica:
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: feat: adiciona login
# ghi9012 HEAD@{2}: commit: fix: corrige validação
# jkl3456 HEAD@{3}: checkout: moving from main to feature/auth

# RECUPERAR após reset --hard acidental
git reflog              # encontra SHA antes do reset
git reset --hard def5678   # volta para lá
# ou: criar nova branch naquele ponto
git checkout -b recuperado def5678

# RECUPERAR commit que nunca foi commitado em nenhuma branch
git fsck --lost-found   # lista dangling objects
ls .git/lost-found/     # blobs e commits "perdidos"
💡
git stash também aparece no reflog como stash@0. Se fizer git stash drop por acidente, git stash show stash@0 e git stash apply stash@0 podem recuperar se o objeto ainda não foi coletado.

Operações avançadas do dia-a-dia

# cherry-pick: aplicar um commit específico em outra branch
git checkout main
git cherry-pick abc1234   # aplica as mudanças desse commit em main

# Desfazer um commit de forma segura (não-destrutivo)
git revert abc1234        # cria um novo commit que desfaz as mudanças

# Bisect: encontra qual commit introduziu um bug (busca binária)
git bisect start
git bisect bad            # commit atual tem o bug
git bisect good v2.1.0    # esta versão estava OK
# Git faz checkout automático de commits intermediários
# Você testa e informa: git bisect good / git bisect bad
git bisect reset          # termina

# Tags: marcar releases
git tag v1.0.0            # tag leve (só aponta para commit)
git tag -a v1.0.0 -m "Release 1.0.0"  # tag anotada (com metadados)
git push origin v1.0.0    # tags não sobem com push padrão
git push origin --tags    # sobe todas as tags

# Stash avançado
git stash push -m "WIP: auth endpoint"  # com nome
git stash list            # lista todos os stashes
git stash apply stash@{2} # aplica sem remover da lista
git stash pop             # aplica e remove
Regras que evitam desastres: (1) Nunca force-push em branches compartilhadas. (2) Antes de reset --hard, crie uma branch no ponto atual. (3) Se perdeu algo, cheque git reflog antes de entrar em pânico. (4) Commits pequenos e focados — mais fácil de reverter e entender.
💡
Próximo: GitHub profissional — Pull Requests, code review, issues, e GitHub Actions para CI/CD básico.
🧩

Quiz rápido

3 perguntas · Acerte tudo e ganhe o badge 🎯 Gabarito

Continue lendo