Git do básico ao avançado

Um mapa prático para trabalhar com Git no mundo real: histórico, branches, remotes, worktrees, cherry-pick e manobras menos óbvias.

Git parece simples quando o caso é linear: editar, adicionar, commitar, dar push. O problema é que a vida real raramente é linear. Você muda de branch no meio do trabalho, precisa reaproveitar um commit isolado, quer publicar artefatos sem misturar código, ou precisa manter várias linhas de trabalho vivas ao mesmo tempo. É aí que o Git deixa de ser uma lista de comandos e passa a ser um sistema de modelagem de histórico.

TL;DR O Git fica previsível quando você separa quatro coisas: working tree, index, commits e refs. O resto — branch, merge, rebase, cherry-pick, worktree, orphan branch, remote — é consequência dessa base.

O modelo mental que evita 80% da confusão

Antes de falar de comandos, vale fixar as camadas certas:

  • Working tree: os arquivos como estão no disco agora.
  • Index ou staging area: o que vai entrar no próximo commit.
  • Commit: um snapshot versionado com pai(s), mensagem e metadados.
  • Ref: um nome que aponta para um commit, como main, HEAD ou origin/main.
Working tree arquivos editados README.md app.py Index próximo commit git add Commit snapshot versionado git commit Refs nomes que apontam main origin/main edita seleciona consolida nomeia o histórico
Se você entende essas quatro camadas, quase todo comando do Git passa a fazer sentido.

Cenários básicos que precisam ficar automáticos

O básico não é “iniciante”. O básico é o conjunto de movimentos que você executa sem pensar.

Situação Comando Intenção real
Ver o estado atualgit statusdescobrir em que camada a mudança está
Ver o diff do discogit diffo que mudou no working tree
Ver o diff stagedgit diff --cachedo que vai para o próximo commit
Adicionar arquivogit add arquivomover mudança para o index
Commitargit commit -m "..."criar snapshot local
Atualizar refs remotasgit fetchbaixar histórico sem misturar ainda
Enviar sua branchgit push -u origin minha-branchpublicar e criar upstream

O comando mais importante aqui é, curiosamente, o git status. Quase todo erro operacional nasce de agir sem saber se a mudança está só no disco, staged, commitada ou já publicada.

Branches: o que são e como usá-las bem

Uma branch não é uma cópia do repositório. É só um ponteiro móvel para um commit. Isso parece detalhe, mas muda tudo: criar branch é barato, apagar branch é barato, experimentar é barato.

Fluxo simples e saudável de branch

git switch main
git pull --ff-only

git switch -c feature/painel-filtros
# ... trabalho ...
git add .
git commit -m "feat: adiciona filtros no painel"
git push -u origin feature/painel-filtros
Boa prática Dê nomes semânticos às branches. feature/, fix/, chore/, spike/ já resolvem muito. Branch com nome claro vira documentação operacional.

Merge, rebase e merge request: qual problema cada um resolve

Essas coisas costumam ser misturadas, mas resolvem problemas diferentes:

  • Merge: combina duas linhas de histórico preservando o fato de que eram paralelas.
  • Rebase: reescreve sua linha de commits como se ela tivesse nascido em outro ponto.
  • Merge request / pull request: mecanismo social e de revisão, não operação de DAG em si.

Regra prática: use rebase para manter sua branch atualizada e limpa antes de revisão; use merge quando quiser preservar a estrutura real de integração ou quando o time prefere esse estilo; use MR/PR como ritual de revisão, CI e aprovação.

Atualizando sua branch com rebase

git fetch origin
git switch feature/painel-filtros
git rebase origin/main

Integrando com merge local

git switch main
git merge --no-ff feature/painel-filtros
Atenção Rebase reescreve commits. Em branch compartilhada, isso pode gerar confusão se outras pessoas já basearam trabalho nela. Rebase é ótimo, mas não é neutro.

Cherry-pick: quando você quer só aquele commit

Cherry-pick é o instrumento certo quando você quer reaproveitar um commit específico sem trazer a branch inteira junto.

Casos clássicos:

  • corrigir produção com um patch pequeno que nasceu em outra branch;
  • copiar um commit de documentação sem misturar o resto da feature;
  • backport de correção para release antiga.

Exemplo: trazer só uma correção

git switch release/1.4
git cherry-pick a1b2c3d

A beleza do cherry-pick é a precisão. O risco é o contexto: às vezes aquele commit dependia de mudanças anteriores e, isolado, para de fazer sentido.

Heurística Se você está puxando um conjunto coerente de 6 commits, talvez não seja mais caso de cherry-pick. Talvez já seja integração de branch.

Worktrees: a forma elegante de viver em várias branches ao mesmo tempo

Muita gente ainda troca de branch dentro do mesmo diretório e vai fazendo stash para sobreviver. Funciona, mas é frágil. Worktree resolve isso melhor: múltiplas árvores de trabalho ligadas ao mesmo repositório Git.

Criando uma worktree para uma feature

git worktree add ../repo-feature-login -b feature/login origin/main

Isso cria um novo diretório, uma nova branch e uma nova working tree, sem duplicar o repositório inteiro. O objeto Git continua compartilhado; o que muda é a área de trabalho.

Quando worktree brilha:

  • manter main aberta para hotfix e outra árvore para uma feature longa;
  • rodar testes de duas branches lado a lado;
  • revisar PR sem desmontar seu trabalho atual;
  • usar agentes ou automação paralela sem colisão de checkout.

Inspecionar e remover

git worktree list
git worktree remove ../repo-feature-login
Ponto importante Worktree não é clone. É outra visão operacional do mesmo histórico local. Para fluxo avançado, isso costuma ser melhor e mais barato do que duplicar repo.

Branches órfãs: quando você quer uma história nova sem herdar a velha

Branch órfã é uma branch que nasce sem pai no histórico visível daquela linha. Ela é útil quando você quer publicar conteúdo ou artefatos sem carregar o histórico principal junto.

Casos típicos:

  • gh-pages ou branch só de site estático;
  • branch de export, snapshot ou build;
  • repositórios onde você quer manter código numa linha e documentação publicada em outra totalmente separada.

Criando branch órfã

git switch --orphan gh-pages
git rm -rf .
# adiciona só os arquivos que devem viver nessa branch

A branch órfã é boa justamente porque impede que a história de build, artefato ou site fique acoplada à história do código-fonte. É uma separação conceitual, não só estética.

Atenção Depois de criar uma branch órfã, o working tree ainda reflete o checkout atual até você limpar ou substituir os arquivos. O erro clássico é esquecer isso e commitar lixo junto.

Remotes: mais do que origin

Remote é só um nome para um endpoint Git. origin é convenção, não regra. Entender isso libera fluxos mais sofisticados.

Exemplos de uso real:

  • origin: seu fork;
  • upstream: repositório principal do projeto;
  • mirror: outro host, como GitLab além do GitHub;
  • deploy: repo especial só para publicação.

Inspecionar e ajustar remotes

git remote -v
git remote add upstream git@github.com:org/projeto.git
git remote set-url origin git@github.com:marinho/projeto.git
git remote rename origin github

Esse tipo de ajuste é valioso quando você muda de provedor, cria fork, passa de HTTPS para SSH ou quer espelhar o mesmo projeto em mais de um lugar.

Fluxo clássico fork + upstream

git fetch upstream
git switch main
git rebase upstream/main
git push --force-with-lease origin main

O detalhe importante aqui é o --force-with-lease. Ele é o jeito civilizado de forçar push após rebase: protege contra sobrescrever trabalho remoto que você não viu.

Cenários complexos do mundo real

1. Hotfix no meio de uma feature longa

Você está no meio de uma feature cheia de mudanças locais, mas precisa corrigir produção agora. Em vez de stash frenético, use worktree ou branch limpa a partir de main.

Fluxo seguro

git worktree add ../repo-hotfix -b hotfix/caddy-timeout origin/main
cd ../repo-hotfix
# corrige, testa, commit, push

2. Backport de correção sem trazer a feature inteira

A correção nasceu em main, mas a release antiga ainda precisa dela. Cherry-pick costuma ser a ferramenta certa.

git switch release/1.2
git cherry-pick a1b2c3d

3. Publicar artefato sem sujar a linha principal

Você quer separar claramente “fonte” e “publicado”. Branch órfã ajuda muito aqui.

git switch --orphan published-docs
git rm -rf .
cp -R build/* .
git add .
git commit -m "docs: publica versão atual"

4. Migrando de host ou mantendo espelho

Em vez de trocar tudo de uma vez, você pode operar com remotes paralelos e validar aos poucos.

git remote add gitlab git@gitlab.com:empresa/projeto.git
git push gitlab main
git push gitlab --tags

Comandos de inspeção que valem ouro

Uso avançado de Git depende menos de “decorar mutações” e mais de saber inspecionar bem.

  • git log --oneline --graph --decorate --all para enxergar a topologia.
  • git show <commit> para entender um commit isolado.
  • git reflog para achar referências recentes, inclusive depois de erro.
  • git branch -vv para ver tracking e último commit.
  • git remote show origin para auditar o remote com mais contexto.
Truque importante git reflog salva muita gente. Se você “perdeu” uma branch, resetou errado ou reescreveu histórico, muitas vezes o commit ainda está acessível pelo reflog.

Antipadrões que custam caro

  • Usar stash como estratégia de vida. Stash serve para pausas pontuais, não como arquitetura de fluxo.
  • Rebase cego em branch compartilhada. Reescrever histórico sem combinar com o time é receita para ruído.
  • Forçar push com --force por reflexo. Prefira --force-with-lease.
  • Não nomear branches semânticas. Branch ruim é custo cognitivo futuro.
  • Ignorar worktrees. Muita dor de contexto paralelo some quando você passa a usá-las.
  • Confundir PR/MR com integração técnica. PR é processo social; merge/rebase/cherry-pick são operações de histórico.

Uma receita prática para operar melhor

  1. Fixe o modelo mental: disco, index, commit, ref.
  2. Antes de agir, rode git status e saiba exatamente em que estado você está.
  3. Use branch curta e nomeada para cada linha de trabalho.
  4. Use worktree quando houver paralelismo real.
  5. Use cherry-pick para reaproveitamento preciso, não para integrar tudo.
  6. Use branch órfã quando o histórico publicado precisa ser outro.
  7. Modele seus remotes conscientemente: fork, upstream, espelho, deploy.

Esta página é um estudo gerado em conversa com o Hermes e pode evoluir com novos exemplos, cenários de recuperação e fluxos específicos de GitHub, GitLab ou Forgejo.