Como reescrever o histórico
Git commit --amend e outros métodos de reescrever o histórico
Introdução
Este tutorial abrangerá vários métodos de reescrita e alteração do histórico de Git. O Git usa alguns métodos diferentes para gravar as alterações. Nós discutiremos os pontos fortes e fracos de diferentes métodos e daremos exemplos de como trabalhar com eles. Este tutorial discute alguns dos motivos mais comuns para sobrescrever instantâneos que passaram por commit e mostra como evitar as armadilhas de fazê-lo.
O principal trabalho do Git é garantir que você nunca perca uma alteração na qual fez commit. Mas, ele também foi desenvolvido para dar a você o controle total sobre seu fluxo de trabalho de desenvolvimento. Isto inclui deixar você definir exatamente como o histórico do seu projeto aparecerá; no entanto, ele também cria o potencial de perder commits. O Git fornece comandos de reescrita de histórico sob o aviso de isenção de que usá-los pode resultar em perda de conteúdo.
O Git possui vários mecanismos para armazenar seu histórico e salvar as mudanças. Estes mecanismos incluem: Commit--amend
, git rebase
e git reflog
. Estas opções dão a você opções poderosas de personalização do fluxo de trabalho. No final deste tutorial, você estará familiarizado com os comandos que permitirão reestruturar seus commits do Git, e será capaz de evitar as armadilhas que são encontradas comumente ao reescrever o histórico.
Material relacionado
Folha de consulta do Git
VER SOLUÇÃO
Aprenda a usar o Git com o Bitbucket Cloud
Alterarando o último commit: git commit --amend
O comando git commit --amend
é uma forma conveniente de modificar o commit mais recente. Ele permite que você combine alterações preparadas com o commit anterior, em vez de criar um novo commit. Ele também pode ser usado simplesmente para editar a mensagem do commit anterior sem alterar seu instantâneo. No entanto, emendar não apenas altera o commit mais recente, ele o substitui totalmente, o que significa que o commit emendado será uma nova entidade com sua própria referência. Para o Git, parecerá um novo commit, que é visualizado com um asterisco (*) no diagrama abaixo. Existem alguns cenários comuns para usar o git commit --amend
. Nós abordaremos os exemplos de uso nas seções seguintes.
Altere a mensagem mais recente de commit do Git
git commit --amend
Digamos que você acabou de realizar commit e você cometeu um erro na mensagem de log do commit. Executar este comando quando não existe nada preparado, permite que você edite a mensagem do commit anterior sem alterar seu instantâneo.
Os commits prematuros acontecem todo o tempo no curso do seu desenvolvimento diário. É fácil esquecer de preparar um arquivo ou formatar sua mensagem de commit de modo errada. O sinalizador --amend
é uma forma conveniente de corrigir estes pequenos erros.
git commit --amend -m "an updated commit message"
Adicionar a opção -m
permite que você transmita uma nova mensagem para a linha de comandos sem ser solicitado a abrir um editor.
Alterando arquivos com commit
O exemplo a seguir demonstra um cenário comum no desenvolvimento com base no Git. Digamos que nós editamos o que gostaríamos de realizar commit em um único instantâneo, mas esquecemos de adicionar um dos arquivos da primeira vez. Corrigir o erro é simplesmente uma questão de preparar o outro arquivo e fazer commit com o sinalizador --amend
:
# Edit hello.py and main.py
git add hello.py
git commit
# Realize you forgot to add the changes from main.py
git add main.py
git commit --amend --no-edit
O sinalizador --no edit
permitirá que você faça a emenda no seu commit sem alterar a mensagem do commit dele. O commit resultante substituirá o incompleto, e parecerá que nós fizemos commit das alterações em hello.py
e main.py
em um único instantâneo.
Não emende commits públicos
Os commits emendados são de fato commits totalmente novos e o commit anterior não estará mais na sua ramificação atual. Isto tem as mesmas consequências de redefinir um instantâneo público. Evite emendar um commit em que outros desenvolvedores basearam seu trabalho. Esta é uma situação confusa para os desenvolvedores e a recuperação é complicada.
Recapitulando
Para revisar, git commit --amend
permite que você pegue o commit mais recente e adicione novas alterações preparadas nele. Você pode adicionar ou remover alterações da área de preparação do Git com um commit --amend
. Se não houver nenhuma alteração preparada, um --amend
ainda será solicitado para modificar o último log da mensagem do commit. Tome cuidado ao usar --amend
em commits compartilhados com outros membros da equipe. Emendar um commit que é compartilhado com outro usuário provavelmente causará confusão e resoluções longas dos conflitos de mesclagem.
Alterando commits antigos ou múltiplos
Para modificar commits mais antigos ou múltiplos, você pode usar git rebase
para combinar uma sequência de commits em um novo commit de base. No modo padrão, o git rebase
permite que você reescreva o histórico literalmente — aplicando commits automaticamente em sua ramificação de trabalho atual à cabeça da ramificação transmitida. Já que seus novos commits estarão substituindo os antigos, é importante não usar git rebase
em commits que foram colocados como públicos, ou parecerá que seu histórico de projeto despareceu.
Nestas instâncias ou em semalhantes, onde for importante preservar um projeto limpo, adicionar a opção -i
ao git rebase
permite que você execute um rebase interativo
. Isso dá a você a oportunidade de alterar commits individuais no processo, em vez de mover todos os commits. Você pode aprender mais sobre o rebase interativo e sobre os comandos adicionais do rebase na página git rebase.
Alterando arquivos com commit
Durante um rebase, o editor ou comando e
pausará a reprodução do rebase naquele commit e permitirá que você faça alterações adicionais com git commit --amend
o Git interromperá a reprodução e apresentará uma mensagem:
Stopped at 5d025d1... formatting
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
Várias mensagens
Cada commit comum do Git terá uma mensagem de log explicando o que aconteceu no commit. Essas mensagens fornecem insights valiosos sobre o histórico do projeto. Durante um rebase, você pode executar alguns comandos em commits para modificar as mensagens dos commits.
Realize squash nos commits para um histórico limpo
O comando squash s
é onde vemos a verdadeira utilidade do rebase. O squash permite que você especifique quais commits deseja mesclar nos commits anteriores. É isto que permite um "histórico limpo". Durante a reprodução de rebase, o Git executará o comando especificado de rebase para cada commit. No caso de realizar squash nos commits, o Git abrirá seu editor de texto configurado e solicitará que você combine as mensagens especificadas de commit. Este processo inteiro pode ser visualizado da seguinte forma:
Observe que os commits modificados com um comando rebase possuem um ID diferente dos commits originais. Os commits marcados com pick terão um novo ID se os commits anteriores tiverem sido reescritos.
As soluções modernas de hospedagem do Git, como o Bitbucket, oferecem funcionalidades de "squash automático" na mesclagem. Estas funcionalidades fazem rebase e squash automaticamente em commits de uma ramificação para você, ao utilizarem a interface do usuário de soluções hospedadas. Para obter mais informações, consulte Fazer squash em commits ao mesclar uma ramificação de Git com o Bitbucket".
Recapitulando
O Git rebase dá a você o poder de modificar seu histórico e o rebase interativo permite que você faça isso sem deixar um rastro de "bagunça". Isso dá a liberdade de cometer e corrigir erros, bem como refinar seu trabalho, enquanto mantém um histórico de projeto limpo e linear.
A rede de segurança: git reflog
Logs de referência, ou "reflogs" são um mecanismo que o Git utiliza para registrar as atualizações aplicadas a pontas de ramificações e outras referências de commit. Um reflog permite que você volte a commits mesmo que eles são estejam referenciados por nenhuma ramificação ou marca. Depois de reescrever o histórico, o reflog contém informações sobre o estado antigo das ramificações e permite que você volte àquele estado, se necessário. Toda vez que a ponta da sua ramificação for atualizada por algum motivo (por trocar de ramificação, colocar novas alterações, reescrever o histórico ou simplesmente adicionar novos commits), uma nova entrada será adicionada ao reflog. Nesta seção, vamos considerar um olhar de alto nível no comando git reflog
e explorar alguns usos comuns.
Uso
git reflog
Isso exibe o reflog para o repositório local.
git reflog --relative-date
Isso exibe o reflog com informações relativas a data (ex. 2 semanas atrás).
Exemplo
Para entender o git reflog
, veja um exemplo.
0a2e358 HEAD@{0}: reset: moving to HEAD~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to main
c10f740 HEAD@{2}: checkout: moving from main to 2.2
O reflog acima mostra um checkout do mestre para a ramificação 2.2 e de volta. A partir daí, existe um hard reset para um commit mais antigo. A atividade mais recente é representada na parte superior denominada HEAD@{0}
.
Se acontecer de você voltar sem querer, o reflog vai conter o commit mestre apontado para (0254ea7)
antes de você descartar 2 commits sem querer.
git reset --hard 0254ea7
Usando o Git reset, agora é possível alterar o mestre para o commit que estava antes. Essa ação serve de rede de segurança, caso o histórico seja alterado sem querer.
É importante observar que o reflog somente fornece uma rede de segurança se as alterações passaram por commit em seu repositório local e que ele somente monitora movimentos da ponta da ramificação dos repositórios. Adicionalmente, as entradas de reflog possuem uma data de validade. O tempo de expiração padrão para as entradas de reflog é de 90 dias.
Para saber mais informações, consulte a página git reflog.
Resumo
Neste artigo nós discutimos vários métodos para alterar o histórico do git e desfazer alterações no git. Nós observamos com alto nível o processo git rebase. Alguns argumentos principais são:
- Existem muitas formas de reescrever o histórico com o git.
- Use
git commit --amend
para alterar sua mensagem de log mais recente. - Use
git commit --amend
para fazer modificações no commit mais recente. - Use
git rebase
para combinar commits e modificar o histórico de uma ramificação. - O
git rebase -i
oferece um controle muito mais granular sobre as modificações do histórico do que um git rebase padrão.
Saiba mais sobre os comandos que abordamos em suas páginas individuais:
Compartilhar este artigo
Próximo tópico
Leitura recomendada
Marque esses recursos para aprender sobre os tipos de equipes de DevOps ou para obter atualizações contínuas sobre DevOps na Atlassian.