A maioria dos desenvolvedores aprende git add, git commit e git push — e depois para por ai. Mas o Git e uma ferramenta extraordinariamente poderosa com comandos que podem economizar horas de trabalho, ajudar a rastrear bugs em segundos, automatizar a aplicacao de qualidade de codigo e recuperar-se de erros que de outra forma seriam catastroficos. Este guia cobre os fluxos de trabalho avancados do Git que separam usuarios cotidianos de usuarios avancados: rebase interativo, bisect, hooks, recuperacao com reflog, cherry-pick, worktrees e mais.
Para quem e isso: Este artigo assume que voce esta confortavel com as operacoes basicas do Git (commit, push, pull, branch, merge). Se ainda esta aprendendo esses fundamentos, comece por la primeiro e volte quando estiver pronto para subir de nivel.
Pre-requisitos
Antes de mergulhar nos fluxos de trabalho avancados, certifique-se de ter:
- Git 2.23 ou posterior instalado (execute
git --versionpara verificar) - Um repositorio com pelo menos 20-30 commits para praticar
- Familiaridade com branching e merging basico
- Um terminal com o qual voce esteja confortavel (Bash, Zsh, PowerShell)
# Verificar sua versao do Git
git --version
# Atualizar Git no Ubuntu/Debian
sudo apt update && sudo apt install git
# Atualizar Git no macOS
brew upgrade git
Dica: Crie um repositorio descartavel para praticar esses comandos. Muitos deles reescrevem o historico, e voce quer ganhar confianca antes de usa-los em codigo de producao.
Rebase Interativo
O rebase interativo e provavelmente a ferramenta de edicao de commits mais poderosa do Git. Permite reescrever, combinar, reordenar e excluir commits antes de fazer push para uma branch compartilhada.
Iniciando um Rebase Interativo
Para modificar os ultimos 5 commits:
git rebase -i HEAD~5
Isso abre seu editor com uma lista de commits, do mais antigo ao mais recente:
pick a1b2c3d Add user authentication
pick e4f5g6h Fix typo in login form
pick i7j8k9l Add password reset feature
pick m0n1o2p Fix lint errors
pick q3r4s5t Update README
Comandos de Rebase
Cada linha de commit comeca com um comando. Os mais uteis sao:
- pick — Manter o commit como esta
- reword — Manter o commit mas alterar a mensagem
- squash — Combinar este commit com o anterior (mantem ambas as mensagens)
- fixup — Combinar com o commit anterior (descarta a mensagem deste commit)
- edit — Pausar o rebase neste commit para poder emenda-lo
- drop — Remover este commit completamente
Combinando Commits (Squash)
O uso mais comum do rebase interativo e combinar multiplos commits pequenos em um significativo:
pick a1b2c3d Add user authentication
fixup e4f5g6h Fix typo in login form
pick i7j8k9l Add password reset feature
fixup m0n1o2p Fix lint errors
drop q3r4s5t Update README
Isso produz dois commits limpos em vez de cinco desorganizados.
Reordenando Commits
Simplesmente reorganize as linhas no seu editor para mudar a ordem dos commits:
pick i7j8k9l Add password reset feature
pick a1b2c3d Add user authentication
Aviso: Nunca faca rebase de commits que ja foram enviados para uma branch compartilhada. Reescrever historico compartilhado causa conflitos para todos na sua equipe. Apenas faca rebase dos seus commits locais nao enviados.
Autosquash com Commits de Correcao
Se voce sabe que um commit e uma correcao para um anterior, marque-o no momento do commit:
# Criar um commit fixup que se auto-combina com o commit alvo
git commit --fixup=a1b2c3d
# Depois, autosquash durante o rebase
git rebase -i --autosquash HEAD~10
O Git automaticamente reordena os commits fixup ao lado dos seus alvos e os marca com fixup.
Git Bisect: Busca Binaria para Bugs
Quando um bug aparece e voce nao sabe qual commit o introduziu, testar cada commit um por um e impraticavel. git bisect realiza uma busca binaria, encontrando o commit exato em O(log n) passos.
Bisect Manual
# Iniciar a biseccao
git bisect start
# Marcar o commit atual como ruim (tem o bug)
git bisect bad
# Marcar um commit bom conhecido (antes do bug existir)
git bisect good v2.0.0
# Git faz checkout do ponto medio -- teste-o
# Se este commit tem o bug:
git bisect bad
# Se este commit nao tem o bug:
git bisect good
# Repetir ate que o Git identifique o primeiro commit ruim
# Quando terminar:
git bisect reset
Para um intervalo de 1.024 commits, o bisect encontra o culpado em aproximadamente 10 passos.
Bisect Automatizado com um Script
Se voce tem um script de teste que retorna codigo de saida 0 para bom e diferente de zero para ruim:
git bisect start
git bisect bad HEAD
git bisect good v2.0.0
# Executar o teste automaticamente em cada passo
git bisect run ./test-script.sh
# Ou usar um comando de teste especifico
git bisect run npm test -- --grep "login feature"
O Git executa o script em cada ponto medio e identifica o commit culpado sem nenhuma intervencao manual.
Bisect com Criterios Complexos
# Pular commits que nao podem ser testados (ex., build quebrado)
git bisect skip
# Ver o log do bisect
git bisect log
# Reproduzir uma sessao de bisect a partir de um arquivo de log
git bisect replay bisect-log.txt
Estrategias de Cherry-Pick
Cherry-pick aplica um commit especifico de uma branch para outra sem fazer merge da branch inteira. E util para hotfixes, backporting e integracao seletiva de funcionalidades.
Cherry-Pick Basico
# Aplicar um unico commit na sua branch atual
git cherry-pick abc1234
# Aplicar multiplos commits
git cherry-pick abc1234 def5678 ghi9012
# Aplicar um intervalo de commits (excluindo o primeiro)
git cherry-pick abc1234..ghi9012
Cherry-Pick Sem Fazer Commit
# Preparar as mudancas mas nao fazer commit (util para combinar multiplos picks)
git cherry-pick --no-commit abc1234
git cherry-pick --no-commit def5678
# Revisar as mudancas combinadas, depois fazer commit
git commit -m "Backport: authentication fixes from develop"
Lidando com Conflitos de Cherry-Pick
# Se um conflito ocorrer durante o cherry-pick:
# 1. Resolver os conflitos nos arquivos afetados
# 2. Adicionar os arquivos resolvidos ao staging
git add resolved-file.js
# 3. Continuar o cherry-pick
git cherry-pick --continue
# Ou abortar todo o cherry-pick
git cherry-pick --abort
Cherry-Pick para Hotfixes
Um padrao comum para hotfixes em producao:
# Na branch main, corrigir o bug
git checkout main
git checkout -b hotfix/login-crash
# Fazer a correcao e commit
git commit -am "Fix: prevent null pointer in login handler"
# Fazer merge para main
git checkout main
git merge hotfix/login-crash
# Cherry-pick a correcao para a branch develop
git checkout develop
git cherry-pick <hotfix-commit-sha>
Git Hooks
Os Git hooks sao scripts que executam automaticamente em pontos especificos do ciclo de vida do Git. Aplicam qualidade de codigo, validam mensagens de commit e previnem que codigo defeituoso entre no repositorio.
Tipos de Hooks e Localizacoes
Os hooks ficam em .git/hooks/. Os hooks mais utilizados sao:
| Hook | Gatilho | Uso Comum |
|---|---|---|
pre-commit | Antes de um commit ser criado | Linting, formatacao, testes |
commit-msg | Apos a mensagem de commit ser digitada | Validar formato da mensagem |
pre-push | Antes de fazer push para um remoto | Executar suite completa de testes |
post-merge | Apos um merge ser concluido | Instalar dependencias |
pre-rebase | Antes de um rebase iniciar | Prevenir rebase em branches compartilhadas |
Hook Pre-Commit: Linting
#!/bin/sh
# .git/hooks/pre-commit
# Executar ESLint em arquivos JavaScript preparados
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')
if [ -n "$STAGED_FILES" ]; then
echo "Running ESLint on staged files..."
npx eslint $STAGED_FILES
if [ $? -ne 0 ]; then
echo "ESLint failed. Fix errors before committing."
exit 1
fi
fi
# Executar verificacao do Prettier
STAGED_ALL=$(git diff --cached --name-only --diff-filter=ACM)
if [ -n "$STAGED_ALL" ]; then
npx prettier --check $STAGED_ALL
if [ $? -ne 0 ]; then
echo "Prettier check failed. Run 'npx prettier --write .' first."
exit 1
fi
fi
exit 0
Hook Commit-Msg: Conventional Commits
#!/bin/sh
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# Aplicar formato Conventional Commits
PATTERN="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,72}"
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
echo "ERROR: Commit message does not follow Conventional Commits format."
echo ""
echo "Expected: <type>(<scope>): <description>"
echo "Example: feat(auth): add password reset endpoint"
echo ""
echo "Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
exit 1
fi
exit 0
Hook Pre-Push: Suite de Testes
#!/bin/sh
# .git/hooks/pre-push
echo "Running test suite before push..."
npm test
if [ $? -ne 0 ]; then
echo "Tests failed. Push aborted."
echo "Fix failing tests before pushing."
exit 1
fi
echo "All tests passed. Pushing..."
exit 0
Compartilhando Hooks com Sua Equipe
Os hooks em .git/hooks/ nao sao rastreados pelo Git. Para compartilha-los:
# Opcao 1: Armazenar hooks em um diretorio rastreado
mkdir -p .githooks
cp .git/hooks/pre-commit .githooks/
# Configurar o Git para usar o diretorio rastreado
git config core.hooksPath .githooks
# Opcao 2: Usar Husky (projetos Node.js)
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"
Git Reflog e Recuperacao
O reflog e sua rede de seguranca. Registra cada mudanca no HEAD — commits, rebases, resets, checkouts — por pelo menos 30 dias. Se voce perder commits, o reflog e como voce os recupera.
Visualizando o Reflog
# Ver o reflog
git reflog
# A saida se parece com:
# a1b2c3d HEAD@{0}: commit: Add new feature
# e4f5g6h HEAD@{1}: rebase -i (finish): returning to refs/heads/main
# i7j8k9l HEAD@{2}: rebase -i (squash): Add user auth
# m0n1o2p HEAD@{3}: reset: moving to HEAD~3
Recuperando Apos um Reset Incorreto
# Voce acidentalmente executou git reset --hard HEAD~3 e perdeu 3 commits
# Passo 1: Encontrar o commit perdido no reflog
git reflog
# Passo 2: O commit antes do reset esta em HEAD@{1}
git checkout HEAD@{1}
# Passo 3: Criar uma branch para salva-lo
git checkout -b trabalho-recuperado
# Ou fazer cherry-pick de commits especificos de volta
git cherry-pick a1b2c3d
Recuperando Apos um Rebase Incorreto
# Se um rebase deu errado, encontrar o estado antes do rebase
git reflog
# Procurar a entrada logo antes de "rebase -i (start)"
# Resetar para esse ponto
git reset --hard HEAD@{5}
Recuperando Branches Excluidas
# Voce excluiu uma branch com trabalho importante
git branch -D feature/trabalho-importante
# Encontrar a ponta da branch no reflog
git reflog | grep "trabalho-importante"
# Recriar a branch no SHA encontrado
git branch feature/trabalho-importante abc1234
Importante: As entradas do reflog expiram apos 90 dias (30 dias para commits inalcancaveis). Se voce descobrir trabalho perdido, recupere-o o mais rapido possivel. Voce pode configurar a expiracao com
git config gc.reflogExpire.
Git Worktree: Desenvolvimento Paralelo
Os worktrees permitem ter multiplas branches abertas simultaneamente em diretorios separados. Sem mais stashing, committing ou troca de branches para revisar um pull request ou corrigir um hotfix.
Criando um Worktree
# Fazer checkout de uma branch em um novo diretorio
git worktree add ../hotfix-branch hotfix/login-fix
# Criar uma nova branch em um worktree
git worktree add -b feature/new-api ../new-api-work
# Listar todos os worktrees
git worktree list
Fluxo de Trabalho Pratico com Worktrees
# Seu diretorio principal de trabalho tem develop em checkout
# Um bug de producao aparece -- trabalhe nele sem interromper seu trabalho atual
git worktree add ../prod-fix main
cd ../prod-fix
# Corrigir o bug em uma nova branch
git checkout -b hotfix/critical-fix
# ... fazer mudancas, commit, push ...
# Retornar ao seu trabalho de funcionalidade
cd ../my-project
# develop esta exatamente onde voce o deixou
# Limpar quando terminar
git worktree remove ../prod-fix
Worktree para Revisao de Codigo
# Revisar o PR de um colega sem sair da sua branch atual
git fetch origin
git worktree add ../review-pr-42 origin/feature/user-dashboard
# Abrir o worktree no seu editor, revisar o codigo
# Quando terminar:
git worktree remove ../review-pr-42
Uso Avancado do Stash
Alem do basico git stash, ha opcoes poderosas para gerenciar mudancas em andamento.
Stashes com Nome
# Stash com uma mensagem descritiva
git stash push -m "WIP: refactoring auth middleware"
# Listar todos os stashes
git stash list
# stash@{0}: On develop: WIP: refactoring auth middleware
# stash@{1}: On develop: WIP: database migration script
Stash Parcial
# Fazer stash apenas de arquivos especificos
git stash push -m "stash auth changes" src/auth.js src/middleware.js
# Stash interativo -- escolher hunks individuais
git stash push -p -m "partial stash"
Stash Apply vs. Pop
# Apply mantem o stash na lista (seguro para tentar novamente)
git stash apply stash@{0}
# Pop aplica e remove o stash da lista
git stash pop stash@{0}
# Aplicar stash em uma branch diferente
git checkout feature/outra-branch
git stash apply stash@{0}
Criar uma Branch a Partir de um Stash
# Criar uma nova branch e aplicar o stash nela
git stash branch nova-branch-feature stash@{0}
Isso e particularmente util quando o stash tem conflitos com as mudancas na branch atual.
Git Blame e Forense de Log
Quando voce precisa entender por que uma linha de codigo existe ou rastrear quando uma mudanca foi introduzida, as ferramentas de forense do Git sao indispensaveis.
Git Blame
# Ver quem modificou cada linha por ultimo
git blame src/auth.js
# Blame de um intervalo de linhas especifico
git blame -L 10,20 src/auth.js
# Ignorar mudancas de espacos em branco
git blame -w src/auth.js
# Mostrar o commit que moveu ou copiou a linha de outro arquivo
git blame -C src/auth.js
Buscas Avancadas de Log
# Buscar em mensagens de commit por uma palavra-chave
git log --grep="authentication" --oneline
# Buscar mudancas em uma funcao especifica
git log -p -S "function loginUser" -- src/
# Buscar mudancas que correspondam a uma regex
git log -p -G "TODO|FIXME|HACK"
# Ver historico de um arquivo especifico
git log --follow --oneline -- src/auth.js
# Mostrar commits de um autor especifico em um intervalo de datas
git log --author="JC" --after="2025-01-01" --before="2025-12-31" --oneline
Formatos Visuais de Log
# Grafico compacto de branches
git log --oneline --graph --all --decorate
# Formato personalizado com data e autor
git log --pretty=format:"%h %ad | %s%d [%an]" --date=short
# Mostrar estatisticas por commit
git log --stat --oneline -10
Estrategias de Branching
Escolher a estrategia de branching correta afeta a velocidade e qualidade de codigo da sua equipe.
Git Flow
Git Flow usa branches de longa duracao para diferentes estagios:
# Branches principais
main # Codigo pronto para producao
develop # Branch de integracao para funcionalidades
# Branches de suporte
feature/* # Novas funcionalidades (branch a partir de develop)
release/* # Preparacao de lancamento (branch a partir de develop)
hotfix/* # Correcoes de producao (branch a partir de main)
# Iniciar uma funcionalidade
git checkout develop
git checkout -b feature/user-dashboard
# Finalizar uma funcionalidade
git checkout develop
git merge --no-ff feature/user-dashboard
git branch -d feature/user-dashboard
Ideal para: Equipes com lancamentos programados e multiplos ambientes.
GitHub Flow
Uma alternativa mais simples com uma regra: tudo que esta em main e implantavel.
# Criar uma branch a partir de main
git checkout main
git checkout -b feature/add-search
# Trabalhar, fazer commit, push
git push -u origin feature/add-search
# Abrir um Pull Request, obter revisao, fazer merge para main
# O deploy acontece automaticamente a partir de main
Ideal para: Equipes que praticam deploy continuo com branches de curta duracao.
Desenvolvimento Baseado em Trunk
Todos os desenvolvedores fazem commit no main (o trunk) frequentemente, usando branches de funcionalidade de curta duracao de um a dois dias no maximo.
# Branch de curta duracao (1-2 dias maximo)
git checkout -b feature/small-change
# ... mudancas minimas ...
git push -u origin feature/small-change
# Fazer merge para main rapidamente via PR
# Feature flags controlam funcionalidades nao lancadas
if (featureFlags.newDashboard) {
renderNewDashboard();
}
Ideal para: Equipes de alta velocidade com pipelines CI/CD solidos e infraestrutura de feature flags.
Tabela de Referencia de Comandos Avancados do Git
| Comando | Descricao | Exemplo |
|---|---|---|
git rebase -i HEAD~N | Rebase interativo para os ultimos N commits | git rebase -i HEAD~5 |
git bisect start | Iniciar busca binaria para bugs | git bisect start |
git bisect run <script> | Bisect automatizado com um script de teste | git bisect run npm test |
git cherry-pick <SHA> | Aplicar um commit especifico na branch atual | git cherry-pick a1b2c3d |
git cherry-pick --no-commit | Cherry-pick sem auto-commit | git cherry-pick --no-commit a1b2c3d |
git reflog | Mostrar historico de movimentos do HEAD | git reflog |
git worktree add <caminho> <branch> | Fazer checkout de uma branch em um diretorio separado | git worktree add ../fix main |
git stash push -m "msg" | Guardar mudancas com uma mensagem descritiva | git stash push -m "WIP auth" |
git stash push -p | Stash interativo de hunks selecionados | git stash push -p |
git blame -L 10,20 <arquivo> | Blame de um intervalo de linhas especifico | git blame -L 10,20 auth.js |
git log -S "string" | Encontrar commits que adicionam/removem uma string | git log -S "loginUser" |
git log -G "regex" | Encontrar commits que correspondam a uma regex | git log -G "TODO|FIXME" |
git commit --fixup=<SHA> | Criar um commit fixup para autosquash | git commit --fixup=a1b2c3d |
git config core.hooksPath | Definir um diretorio de hooks personalizado | git config core.hooksPath .githooks |
Solucao de Problemas
Conflitos de Rebase Nao Se Resolvem
# Se um rebase tem conflitos demais, abortar e tentar outra abordagem
git rebase --abort
# Alternativa: usar merge em vez de rebase para historicos complexos
git merge develop
Bisect Da Resultados Incorretos
# Se voce marcou um commit incorretamente, ver o log e reproduzir
git bisect log > bisect-log.txt
# Editar o arquivo de log para remover a entrada incorreta
git bisect reset
git bisect replay bisect-log.txt
Scripts de Hook Nao Executam
# Garantir que o arquivo de hook seja executavel
chmod +x .git/hooks/pre-commit
# Verificar que a linha shebang esteja correta
head -1 .git/hooks/pre-commit
# Deveria ser: #!/bin/sh ou #!/bin/bash
# Verificar se core.hooksPath sobrescreve a localizacao padrao
git config --get core.hooksPath
Nao Consegue Excluir um Worktree
# Forcar a remocao de um worktree com mudancas nao commitadas
git worktree remove --force ../old-worktree
# Limpar entradas de worktree obsoletas
git worktree prune
Entrada de Reflog Nao Encontrada
# Aumentar o tempo de expiracao do reflog antes que seja tarde demais
git config gc.reflogExpire 180.days
git config gc.reflogExpireUnreachable 90.days
# Se o reflog estiver vazio, tentar fsck para encontrar commits pendentes
git fsck --unreachable --no-reflogs
Cherry-Pick Resulta em um Commit Vazio
# As mudancas ja existem na branch destino
# Usar --allow-empty para manter o commit, ou pula-lo
git cherry-pick --skip
# Ou verificar se a mudanca ja foi aplicada
git log --oneline --all -- path/to/changed/file
Resumo
Os fluxos de trabalho avancados do Git transformam a forma como voce gerencia codigo. O rebase interativo mantem seu historico de commits limpo e significativo. Git bisect transforma uma busca manual por bugs em uma busca binaria automatizada. Os Git hooks aplicam padroes de qualidade de codigo antes que codigo defeituoso entre no repositorio. O reflog atua como sua rede de seguranca, tornando virtualmente cada erro do Git recuperavel. Cherry-pick e worktrees proporcionam a flexibilidade para trabalhar entre branches sem interrupcoes.
A chave e a pratica. Crie um repositorio de teste, faca dezenas de commits e experimente cada comando deste guia. Uma vez que essas ferramentas se tornem naturais, voce lidara com situacoes complexas do Git com confianca.
Para automatizar seus pipelines de testes e deploy apos dominar esses fluxos de trabalho do Git, leia nosso guia sobre Primeiros Passos com GitHub Actions para CI/CD.