Um Guia para o Rebase Interativo do Git, com Exemplos Práticos

O controle de versão com o Git tornou-se padrão em todo o cinto de ferramentas de qualquer desenvolvedor moderno. Comandos como commit, push e pull fizeram parte da memória muscular dos nossos dedos. Mas relativamente poucos desenvolvedores conhecem os recursos “mais avançados” do Git — e quão incrivelmente valiosos eles podem ser! Neste artigo, exploraremos o “rebase interativo”, uma das ferramentas mais poderosas do Git.

Por que o Rebase Interativo deve fazer parte do kit de ferramentas de todo desenvolvedor

Resumindo, e sem exagero, o rebase interativo pode ajudar você a se tornar um desenvolvedor melhor, permitindo que você crie um histórico de commits limpo e bem estruturado em seus projetos.

Por que um histórico de commits bem estruturado é importante? Imagine o contrário: um histórico de commits difícil de ler, onde você não tem ideia do que seus colegas realmente fizeram com suas mudanças recentes. Cada vez mais “cantos escuros” começam a surgir em tal projeto, e você só entende as pequenas partes em que trabalhou.

Compare isso com um histórico de commits limpo e bem estruturado: isso ajuda a tornar o código-fonte de um projeto mais legível e mais fácil de entender. Esta é uma peça fundamental para um projeto saudável e duradouro!

O que o Rebase Interativo pode fazer por você

O Rebase Interativo ajuda você a otimizar e limpar seu histórico de commits. Ele abrange muitos casos de uso diferentes, alguns dos quais permitem que você faça o seguinte:

  • editar uma mensagem de commit antiga
  • deletar um commit
  • fundir/combinar múltiplos commits
  • reordenar commits
  • corrigir commits antigos
  • dividir/reabrir commits antigos para edição

Quando Usar Rebase Interativo (E Quando Não Usar!)

Como algumas outras ferramentas do Git, o rebase interativo “reescreve a história”. Isso significa que, ao manipular uma série de commits usando rebase interativo, essa parte de sua história de commits será reescrita: os hashes SHA-1 dos commits terão mudado. São objetos de commit completamente novos, por assim dizer.

Esse fato exige uma regra simples, mas importante a ser seguida: não use rebase interativo (ou outras ferramentas que reescrevam a história) em commits que você já compartilhou com seus colegas em um repositório remoto. Em vez disso, use-o para limpar seus próprios commits locais – como em uma de suas próprias branches de recurso – antes de mesclá-los em uma branch de equipe.

O Mecanismo Básico de uma Operação de Rebase Interativo

Embora existam muitas coisas diferentes que o rebase interativo possa ser usado, o fluxo de trabalho básico é sempre o mesmo. Uma vez que você entendeu firmemente esse mecanismo básico, o rebase interativo perderá seu ar de “mistério complexo” e se tornará um item valioso e acessível em seu cinturão de ferramentas.

Passo 1: De onde você deve iniciar a sessão?

A primeira pergunta que você precisa responder é: “Que parte da minha história de commits eu quero manipular?” Isso indica onde você deve iniciar sua sessão de rebase interativo. Vamos fazer um exemplo prático e dizer que gostaríamos de editar uma mensagem de commit antiga (que é o que realmente faremos na prática em um momento).

Nossa situação inicial é ilustrada abaixo, onde estamos editando uma mensagem de commit antiga via rebase interativo.

Para poder alterar a mensagem de commit em C2, temos que iniciar nossa sessão de rebase interativo a partir do commit pai (ou mesmo antes disso, se desejar). Neste caso de exemplo, usaríamos C1 como ponto de partida para nossa sessão de rebase interativo.

Passo 2: iniciando a sessão real!

Iniciar a sessão real é bastante simples:

$ git rebase -i HEAD~3

Estamos usando o comando git rebase com a bandeira -i (para indicar que realmente queremos que seja “interativo”) e fornecemos o commit base (que elaboramos no primeiro passo acima). Neste exemplo, usei HEAD~3 para especificar o commit que está “3 atrás do commit HEAD”. Alternativamente, também poderia ter fornecido um hash SHA-1 específico.

Passo 3: dizendo ao Git o que você quer fazer

Após iniciar a sessão de rebase interativo, você será apresentado a uma janela de editor onde o Git lista uma série de commits — desde o commit mais recente, até (mas não incluindo) aquele que você escolheu como commit base no Passo 1.

Há duas coisas importantes a ter em mente neste passo:

  1. Os commits são listados em ordem reversa! O commit mais recente, que esperaríamos aparecer no topo, aparecerá no fundo da lista. Não se preocupe: seu repositório Git está em forma! 🥳 Lembre-se de que estamos no processo de realizar uma operação de rebase interativo, e isso requer que o Git reaplique os commits de mais antigos para mais recentes no final da operação.
  2. Não faça suas mudanças reais nesta janela de editor! Embora você possa estar com vontade de simplesmente ir em frente e alterar a mensagem de commit nesta janela de editor (afinal, é isso que realmente queremos fazer…), você precisa ter um pouco de paciência. Aqui, apenas vamos dizer ao Git o que queremos fazer — mas não faremos a mudança real. Eu demonstrarei isso em prática em breve!

Agora que o panorama teórico foi esclarecido, vamos mergulhar em alguns casos práticos juntos!

Editando uma Mensagem de Commit Antiga

Um dos casos de uso muito populares de rebase interativo é que você pode editar uma mensagem de commit antiga após o fato. Você pode estar ciente de que git commit --amend também permite que você mude a mensagem de um commit — mas apenas se for o último commit. Para qualquer commit mais antigo que isso, temos que usar o rebase interativo!

Vamos analisar uma situação concreta. Abaixo está uma imagem de uma mensagem de commit ruim que precisa ser corrigida.

Nota: Para uma melhor visualização e visualização mais clara, estou usando o cliente desktop Tower Git em algumas de minhas capturas de tela. Você não precisa do Tower para acompanhar este tutorial.

Para o nosso exemplo, digamos que gostaríamos de editar a mensagem do commit atualmente intitulado “Otimizar a estrutura do marcador no índice…”

Nosso primeiro passo é determinar o commit base para iniciar esta sessão de rebase interativo. Como temos que (pelo menos) voltar ao pai do nosso commit “maçã podre”, estamos começando nossa sessão em HEAD~3 (três commits atrás do commit HEAD, que é aquele com o título “Alterar títulos…”):

$ git rebase -i HEAD~3

Logo após executar este comando, seu editor favorito abrirá e apresentará a lista de commits que você acabou de selecionar (fornecendo um commit base).

Lembrando: apesar de ser tentador fazê-lo, não mudamos a mensagem do commit aqui. Apenas marcamos a linha respectiva com uma “palavra-chave de ação”. No nosso caso, queremos reword o commit (o que significa que gostaríamos de alterar a mensagem do commit, mas deixar o resto do commit como está).

Praticamente, todas as palavras-chave de ação disponíveis são documentadas no final desta janela — então não há necessidade de lembrar de nada de cor!

Depois de substituir a palavra-chave padrão pick (que significa “tomar o commit como está”) com a sua palavra-chave de ação preferida, você pode simplesmente salvar e fechar a janela.

Após fazer isso, uma nova janela de editor abrirá contendo a mensagem atual do commit. Finalmente, podemos fazer o que pretendíamos fazer desde o início: editar a mensagem deste antigo commit!

Após fazer nossa alteração e, em seguida, salvar e fechar a janela do editor, a sessão de rebase interativo está completa — e a mensagem do nosso commit está atualizada! 🎉

Excluindo um Commit Indesejado

O rebase interativo também permite que você delete um commit antigo de seu histórico que não precisa (ou quer) mais. Imagine que você incluiu acidentalmente uma senha pessoal em um commit recente: informações sensíveis como essa, na maioria dos casos, não devem ser incluídas em um repositório de código.

Lembre-se também de que simplesmente deletar a informação e commitar novamente não resolve realmente o seu problema: isso significaria que a senha ainda está salva no repositório, na forma de seu antigo commit. O que você realmente quer é limpar e completamente delete essa informação do repositório!

Vamos começar determinando o commit base para nossa sessão de rebase interativo. Como precisamos começar pelo menos no pai do commit ruim, estamos usando o commit “Optimize markup structure…” como base:

$ git rebase -i 6bcf266b

Observe que, desta vez, usei um hash SHA-1 concreto no comando git rebase -i. Em vez do hash do commit, é claro, poderia ter usado HEAD~2 para se referir a esse commit.

Após executar esse comando, somos apresentados novamente com uma lista de commits.

Desta vez, estamos usando a palavra-chave de ação drop para eliminar o commit indesejado. Alternativamente, neste caso especial, também poderíamos simplesmente deletar a linha inteira do editor. Se uma linha (representando um commit) não estiver mais presente ao salvar e fechar a janela, o Git deletará o commit respectivo.

No entanto você decida fazer isso, após salvar e fechar a janela do editor, o commit será deletado do histórico do seu repositório!

Combinando Múltiplos Commits em Um

Outro caso de uso para o rebase interativo é quando você deseja combinar múltiplos commits separados em um único. Antes de mergulharmos em como isso funciona, vamos dedicar alguns momentos para discutir quando ou por que isso pode ser valioso.

Geralmente, fazer commits “maiores” (combinando vários em um) não é uma boa estratégia na maioria dos casos. A regra geral é manter os commits o menor possível, pois “pequenos” significa “mais fáceis de ler e entender”. Mas há situações em que isso ainda pode fazer sentido. Aqui estão dois exemplos:

  • Imagine que você percebeu um problema com um commit mais antigo. Você poderia então prosseguir e produzir um novo commit que corrige o problema. Nessa situação, ser capaz de combinar esses commits em um único faz muito sentido: o commit mais recente, afinal, era apenas um “curativo” para corrigir um problema que não deveria estar lá em primeiro lugar. Ao combinar esses commits, parece que nunca houve um problema!
  • Outro exemplo é quando você percebe que fez as coisas um pouco demais granulares. Fazer commits pequenos é tudo muito bom, mas espalhar seu histórico de commits com muitos pequenos desnecessariamente significaria ultrapassar o alvo.

A justificativa é a mesma nos dois exemplos: ao combinar dois (ou múltiplos) commits que deveriam ter sido um único desde o início, você está produzindo um histórico de commits mais limpo e legível!

Vamos passar por um exemplo prático juntos e considerar a situação retratada abaixo como nosso ponto de partida.

Vamos supor que, semanticamente, faz mais sentido que esses dois commits sejam apenas um. Usando a ferramenta squash do rebase interativo, podemos realmente combiná-los:

$ git rebase -i HEAD~3

Até agora, você já está acostumado com o que acontece a seguir: uma janela de editor é aberta com uma lista de commits.

I already mentioned that we’re going to use the squash action keyword in this case. There’s an important thing to know about how squash works: the line you mark up with the keyword will be combined with the line directly above! This explains why I marked line 2 with the squash keyword in our example.

Após salvar e fechar essa janela, outra será aberta. Isso porque, ao combinar vários commits, estamos, é claro, criando um novo. E este precisa de uma mensagem de commit, como qualquer outro commit também!

O que você vê na imagem acima é o que o Git preparou para nós: combinou as mensagens de commit das respectivas mensagens originais junto com alguns comentários. Você é livre para excluir as mensagens antigas e começar do zero — ou mantê-las e adicionar mais algumas informações.

Após salvar e fechar essa janela de editor, podemos afirmar orgulhosamente: o que costumava ser dois commits separados agora é apenas um!

Aproveitando o Poder do Rebase Interativo

I hope you agree that Git’s interactive rebase tools can be very valuable! As developers, it’s important for us to strive for a clean and clear commit history. It’s a crucial ingredient in keeping a codebase healthy and easy to understand (both for your teammates, and yourself, after some time has passed).

Se você deseja aprender mais, recomendo fortemente o “Primeiro Kit de Socorro para Git”. É uma coleção (gratuita) de vídeos curtos que mostram como limpar e desfazer erros no Git.

Divirta-se!

Perguntas Frequentes (FAQs) sobre Rebase Interativo do Git

Qual é a diferença entre Git Rebase e Git Merge?

Git Rebase e Git Merge são duas maneiras diferentes de integrar alterações de uma branch em outra. Git Merge é uma maneira direta de combinar código de duas branches diferentes. Ele cria um novo commit na história, preservando a ordem cronológica dos commits. Por outro lado, Git Rebase é uma maneira de mover ou combinar uma sequência de commits para um novo commit base. É como dizer “quero basear minhas alterações no que todo mundo fez”. Em outras palavras, permite que você coloque as alterações da branch atual em cima de outra branch.

Como posso desfazer um Git Rebase?

Se você deseja desfazer um Git Rebase, pode usar o comando git reflog para encontrar o commit que deseja retornar, e então usar o comando git reset --hard HEAD@{number}. O comando git reflog mostra uma lista de todas as alterações feitas no HEAD, e o comando git reset permite que você defina o HEAD atual para o estado especificado.

Qual é o propósito do Git Interactive Rebase?

Git Interactive Rebase permite que você altere commits de várias maneiras, como editando, deletando e mesclando. Você não só pode alterar a mensagem do commit, mas também pode alterar o código real se cometeu um erro. É uma ferramenta poderosa que oferece controle total sobre a história de commits do seu projeto.

Como posso mesclar commits usando Git Interactive Rebase?

O ato de “esmagar” consiste em combinar vários commits em um só. No Git, você pode esmagar commits usando o comando git rebase -i seguido do hash do commit que deseja esmagar. No editor de texto que é aberto, você pode marcar os commits que deseja esmagar substituindo pick por squash ou s ao lado de cada commit.

Quais são os riscos de usar o Git Interactive Rebase?

Embora o Git Interactive Rebase seja uma ferramenta poderosa, pode ser perigoso se não for usado corretamente. Ele reescreve a história do commit, o que pode ser problemático se você estiver trabalhando em uma branch pública em que outras pessoas também estão trabalhando. É recomendado usá-lo em branches locais que ainda não foram enviadas.

Como posso resolver conflitos durante um Git Rebase?

Durante um rebase, podem ocorrer conflitos. O Git pausará e permitirá que você resolva esses conflitos antes de continuar. Você pode resolver conflitos editando os arquivos para corrigir as mudanças conflitantes e, em seguida, adicionando os arquivos resolvidos com git add. Após resolver todos os conflitos, você pode continuar o rebase com git rebase --continue.

Posso usar o Git Interactive Rebase para dividir um commit?

Sim, você pode usar o Git Interactive Rebase para dividir um commit em menores. Isso pode ser útil se você fez várias alterações em um único commit, mas mais tarde decidiu que elas deveriam ter sido commits separados.

Como posso editar uma mensagem de commit usando o Git Interactive Rebase?

Você pode editar uma mensagem de commit durante um rebase interativo. Na lista de commits, substitua pick por reword ou r ao lado do commit que deseja editar. Ao continuar, o Git abrirá um editor de texto para cada commit marcado com reword, permitindo que você altere a mensagem do commit.

Qual é a diferença entre Git Rebase e Git Pull?

O Git Pull é um comando que busca alterações de um repositório remoto e mescla-as na sua branch atual. Por outro lado, o Git Rebase é um comando que move ou combina uma sequência de commits para um novo commit base. Embora ambos os comandos sejam usados para integrar alterações, eles fazem isso de maneiras diferentes.

Posso usar o Git Interactive Rebase para mudar a ordem dos commits?

Sim, você pode mudar a ordem dos commits usando o Git Interactive Rebase. Na lista de commits, basta alterar a ordem das linhas para mudar a ordem dos commits. Isso pode ser útil se você quiser tornar sua história de commits mais lógica ou clara.

Source:
https://www.sitepoint.com/git-interactive-rebase-guide/