12k
All articles

5 Comandos Git Além de Commit e Push

Cinco comandos Git além de commit e push: stash, reflog, cherry-pick, rebase -i e bisect para recuperar, limpar histórico e achar bugs.

OpenReplay Team
OpenReplay Team
5 Comandos Git Além de Commit e Push

A maioria dos desenvolvedores vive em add, commit, push e pull, mas a verdadeira força do Git está nos comandos de recuperação, edição de histórico e depuração que o ciclo diário nunca toca.

Você costuma conhecer o resto deles do jeito difícil. Um reset --hard engole uma tarde inteira de trabalho, ou um bug aparece em algum lugar dentro de 200 commits e ninguém sabe dizer qual deles quebrou tudo. Os cinco comandos abaixo resolvem problemas que o básico não consegue: guardar trabalho pela metade, recuperar commits que você achava perdidos, mover uma única correção entre branches, limpar um histórico bagunçado antes de um PR e localizar com precisão o commit que introduziu um bug. Cada um vem com um gatilho mental, a sintaxe exata e a pegadinha que costuma derrubar as pessoas.

Principais Conclusões

  • git stash guarda seu trabalho pela metade e devolve uma working tree limpa, permitindo trocar de contexto sem um commit descartável.
  • git reflog registra todos os lugares para onde o HEAD apontou, então, após um reset ou rebase malsucedido, você pode encontrar o hash do commit perdido e restaurá-lo com git reset --hard <ref>.
  • git cherry-pick <hash> copia um único commit para o seu branch atual, o que é ideal para mover um hotfix específico para um branch de release sem trazer todo o resto junto.
  • Comandos que reescrevem histórico, como git rebase -i e git reset --hard, são seguros em trabalho local não publicado e perigosos em branches compartilhados; git reflog é o seu caminho de recuperação quando algo dá errado.
  • git bisect faz uma busca binária no seu histórico para encontrar o commit exato que introduziu um bug em log₂(n) passos.

git stash: guarde o trabalho para trocar de contexto rapidamente

Use quando um relatório de bug chega enquanto sua working tree é uma bagunça pela metade e você precisa pular de branch agora. O git stash estaciona suas alterações não commitadas em um lugar seguro e devolve a working tree limpa, igual ao seu último commit. Nenhum commit “WIP” descartável é necessário.

git stash                  # shelve tracked changes, clean the tree
git stash --include-untracked   # also shelve new, untracked files
git stash list             # see all stashes: stash@{0}, stash@{1}, ...
git stash pop              # reapply the latest stash and delete it
git stash apply stash@{1}  # reapply a specific stash, keep it in the list

A pegadinha: pop e apply não são intercambiáveis. O git stash pop aplica suas alterações guardadas e apaga o stash; o git stash apply as aplica, mas mantém o stash, o que é mais seguro caso a reaplicação possa gerar conflito. Se um pop encontrar um conflito de merge, o stash não é descartado. Resolva o conflito primeiro e depois verifique, antes de presumir que ele sumiu.

git reflog: recupere trabalho que você achava perdido

Use quando um reset --hard mal feito, um rebase atrapalhado ou um branch apagado fazem commits sumirem e o pânico bater. O git reflog registra todas as posições que o HEAD ocupou no seu repositório local, então o commit “perdido” quase sempre ainda existe. Você só precisa do hash dele.

git reflog
# ab12cd3 HEAD@{0}: reset: moving to HEAD~1
# ef45gh6 HEAD@{1}: commit: the work you thought vanished
git reset --hard ef45gh6   # restore HEAD to that commit
# or, to inspect it on a new branch first:
git switch -c recovery ef45gh6

Encontre a ref do estado que você quer e então use git reset --hard <ref> para voltar até ele, ou faça o checkout em um novo branch para inspecioná-lo com segurança antes. Este é o herói do “ah não, perdi meu trabalho” do kit de ferramentas.

A pegadinha: o reflog é estritamente local e específico de cada clone. Ele não viaja para o remoto e não existe em um clone novo, então re-clonar para “recuperar seu trabalho” não vai ajudar. As entradas também são removidas ao longo do tempo pelo garbage collection, então recupere o quanto antes.

git cherry-pick: mova um commit entre branches

Use quando um único commit de hotfix precisa chegar a um branch de release, mas você não quer fazer merge de todo o branch de feature de onde ele veio. O git cherry-pick <hash> copia um commit específico para o seu branch atual, deixando todo o resto para trás.

git switch release-2.4
git cherry-pick 9f3c1a7        # apply one commit here
git cherry-pick 9f3c1a7 3b8e2d0   # apply several, in order

A pegadinha: o cherry-pick cria um novo commit com um novo hash. O original não é preservado nem movido. Se esse mesmo commit chegar depois a este branch através de um merge normal, você pode acabar com alterações duplicadas no histórico. Use-o de forma deliberada, não como substituto rotineiro do merge.

git rebase -i: limpe o histórico antes de um PR

Use quando seu branch de feature tem cinco commits de “fix typo” e “wip” e você quer um histórico organizado e revisável antes de abrir um pull request. O git rebase -i <base-branch> abre um editor onde você pode reordenar, esmagar (squash), editar ou descartar commits.

git rebase -i main
# pick   a1b2c3d Add feature scaffold
# squash e4f5g6h fix typo
# reword h7i8j9k Wire up handler
# drop   k0l1m2n debug logging

Marcar um commit como squash o funde com o de cima, reword altera apenas a mensagem dele e drop o deixa completamente de fora do resultado. Se você só precisa condensar um branch inteiro em uma única alteração no stage, o git merge --squash <branch> é a ferramenta irmã. Ele coloca as alterações combinadas no stage sem criar um commit, então você ainda executa o git commit você mesmo.

A pegadinha, e a regra de ouro: reescreva o histórico à vontade enquanto ele ainda for local, mas nunca faça rebase de commits que você já enviou para um branch compartilhado. Reescrever histórico compartilhado força todo mundo a uma reconciliação dolorosa, um risco que o Pro Git chama de “Os Perigos do Rebase”.

git bisect: encontre o commit que introduziu um bug

Use quando algo funcionava na semana passada e está quebrado agora, e você não faz ideia de qual dos 200 commits causou isso. O git bisect executa uma busca binária pelo histórico: marque um commit ruim e um commit bom, teste os pontos médios que o Git faz checkout, e ele localiza o primeiro commit ruim em log₂(n) passos.

git bisect start
git bisect bad                 # current commit is broken
git bisect good v2.3.0         # this older tag worked
# Git checks out a midpoint — test it, then tell Git:
git bisect good                # this one is fine
git bisect bad                 # this one is broken
# ...repeat until Git reports "<hash> is the first bad commit"
git bisect reset               # return HEAD to where you started

Você pode automatizar toda a busca: git bisect run <script> usa o status de saída de um script para marcar cada commit como bom ou ruim, sem nenhuma entrada manual. Encerre toda sessão com git bisect reset para devolver o HEAD ao ponto em que você estava antes da busca.

A pegadinha: o bisect presume que cada commit checado compila e roda seu teste sem problemas. Um commit que falha ao compilar por um motivo não relacionado distorce o resultado. Marque esses casos com git bisect skip em vez de chutar bom ou ruim.

Uma rede de segurança para os destrutivos

Dois desses comandos reescrevem o histórico, e a regra para ambos é a mesma: git rebase -i e git reset --hard são seguros em trabalho local não publicado e perigosos em branches compartilhados. Quando você precisa de um desfazer seguro em um branch que outras pessoas já puxaram, prefira o git revert, que registra um novo commit revertendo a alteração sem modificar o histórico existente. E quando uma reescrita local dá errado, o git reflog é a saída de emergência que traz seus commits de volta.

Estes cinco merecem seu lugar porque cada um responde a uma pergunta que commit e push não conseguem: salve isto, recupere aquilo, mova um, organize, cace o bug. Associe cada um ao seu gatilho e recorra a ele no momento em que a situação aparecer.

Perguntas Frequentes

Qual é a diferença entre git reset --hard e git revert?

O git reset --hard rebobina o HEAD e descarta commits, reescrevendo o histórico, o que o torna perigoso em qualquer branch que outras pessoas já tenham puxado. Já o git revert registra um novo commit que reverte a alteração desejada, mantendo o histórico existente intacto. Use reset --hard apenas em trabalho local não publicado; use revert como o desfazer seguro em branches compartilhados. Se um reset der errado, o git reflog pode recuperar os commits descartados pelo hash.

Como recupero um commit depois que o git reset --hard o apagou?

Execute git reflog, que registra todas as posições que o HEAD ocupou no seu repositório local. Encontre a entrada do estado que você quer, anote o hash e então execute git reset --hard <hash> para restaurá-lo, ou git switch -c recovery <hash> para inspecioná-lo primeiro em um novo branch. O reflog é local e específico de cada clone, então re-clonar não vai recuperar o trabalho, e as entradas são removidas ao longo do tempo pelo garbage collection, então recupere o quanto antes.

O git switch substitui o git checkout para trocar de branch?

O git switch e o git restore foram introduzidos no Git 2.23 (agosto de 2019) para dividir os papéis sobrecarregados do git checkout: o switch cuida da movimentação entre branches e o restore cuida da restauração de arquivos. Ambas as páginas de manual carregaram um aviso de experimental por anos, mas esse aviso foi removido a partir do Git 2.55.0, então agora eles são simplesmente os comandos recomendados para essas operações. O git checkout continua funcionando e não está descontinuado, então fluxos de trabalho existentes permanecem válidos.

Quando devo usar git cherry-pick em vez de merge?

Use o git cherry-pick quando você precisa exatamente de um commit em outro branch (por exemplo, mover um único hotfix para um branch de release) sem trazer o restante do histórico do branch de origem. Um merge traz as alterações do branch inteiro, o que é a ferramenta errada para isolar uma única correção. Note que o cherry-pick cria um novo commit com um novo hash, então, se a mesma alteração chegar depois através de um merge normal, você pode acabar com alterações duplicadas no histórico.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.