Aprenda / Git e controle de versão

IntermediárioAula 10 de 1416 min0% da trilha

reset, revert e cherry-pick: as três formas de desfazer

'Desfazer no git' não é um comando só — são três ferramentas diferentes, e usar a errada em histórico compartilhado causa dor de cabeça.

"Preciso desfazer isso" pode significar coisas bem diferentes: desfazer um commit que só existe localmente, desfazer um commit que já foi pushado e outras pessoas já viram, ou trazer só uma mudança específica de outra branch sem trazer tudo. Cada caso tem uma ferramenta certa — usar a errada pode reescrever histórico que não devia ser reescrito.

git reset — move o ponteiro da branch pra trás

reset move o HEAD (e a branch atual) pra um commit anterior, como se os commits depois dele nunca tivessem existido nessa branch. As três variantes controlam o que acontece com as mudanças desses commits "desfeitos":

terminal
git reset --soft HEAD~1    # desfaz o commit, mas mantém as mudanças staged (prontas pra commitar de novo)
git reset --mixed HEAD~1   # desfaz o commit e a staging area, mas mantém as mudanças no arquivo (padrão)
git reset --hard HEAD~1    # desfaz o commit E descarta as mudanças completamente — perde o trabalho

--hard é o único destrutivo de verdade — os outros dois só reorganizam onde a mudança "mora" (commit, staging, ou arquivo), sem apagar código.

git revert — desfaz publicamente, criando um commit novo

revert não apaga nem reescreve nada — ele cria um commit novo que aplica o efeito contrário do commit escolhido. O commit problemático continua no histórico (pra quem quiser auditar), e o revert some por cima dele.

terminal
git revert a3f9e2b   # cria um commit que desfaz a3f9e2b

reset vs. revert: a regra que importa em equipe

reset reescreve o histórico da branch (os commits desfeitos deixam de existir nela) — seguro só em commits locais, não pushados, exatamente pela mesma razão do rebase (lição anterior). revert não reescreve nada, só adiciona — por isso é a ferramenta certa pra desfazer algo em main ou qualquer branch que outras pessoas já têm localmente.

regra prática
Commit só local, ainda não pushado, quer apagar de vez → git reset
Commit já em main / já pushado / outras pessoas já viram → git revert

git cherry-pick — traz um commit específico, sem trazer a branch toda

Às vezes você quer só um commit de outra branch — não a branch inteira via merge. cherry-pick pega esse commit específico e reaplica na sua branch atual, como um commit novo com o mesmo conteúdo.

terminal
git checkout hotfix/producao
git cherry-pick a3f9e2b   # traz só esse commit específico, feito originalmente em outra branch

Uso clássico: alguém corrigiu um bug numa branch de feature ainda não finalizada, mas esse fix específico precisa ir pra produção agora — sem esperar o resto da feature ficar pronto.

Exercício

Um commit com um bug sério já foi pushado pra main há 2 dias, e outras 3 pessoas já deram pull. Você precisa desfazer o efeito desse commit agora. Por que git reset seria uma escolha arriscada aqui, e o que usar no lugar?

Quiz rápido

Qual a diferença essencial entre git revert e git reset?
Para que serve git cherry-pick?