Git: Rebase

Git rebase

Rebase é o comando do Git que eu mais gosto!

Ele possui duas funcionalidades principais. A primeira é aplicar uma sequência de commits em um commit base diferente (rebase, entende?).

A segunda, que eu mais gosto, é juntar commits, também sendo possível alterar commits.

Pois então vamos lá!

Rebase básico

Para aplicar commits sobre uma base diferente basta utilizar o comando rebase dando o nome do branch que deseja ter como nova base. O git vai identificar o ponto de divergência entre o branch atual e o branch da nova base e vai criar novos commits similares sobre a base indicada.

$ git rebase BRANCH_OU_COMMIT

Como exemplo, suponha que você clonou  repositório e realizou alguns commits. Então sincronizou o repositório remoto e agora ele possui novos commits e você quer estas modificações. Nesse caso você tem duas opções: merge ou rebase.

Adaptado da documentação. Veja em git merge --help.

	  A---B---C master
	 /
    D---E---F---G origin/master(novo)
        ^
        origin/master(velho)
$ # Obtém commit E como origin/master
$ git clone REPO

$ # Editar alguns arquivos, cria commits A, B e C
$ git add .
$ git commit ...

$ # Algum tempo passou e você quer sincronizar
$ # com o servidor remoto, que obtém commit H como origin/master
$ git fetch origin

O merge vai criar um novo commit H cujos pais são o seu branch C e o branch remoto G.

Adaptado da documentação. Veja em git merge --help.

	  A---B---C master(velho)
	 /         \
    D---E---F---G---H master(novo)
                ^
                origin/master
$ git merge origin/master

O rebase por sua vez vai recriar todos os commits do seu branch C no topo do branch remoto G.

Adaptado da documentação. Veja em git rebase --help.

            A---B---C master(velho)
           /
          /      A'--B'--C' master(novo)
         /      /
    D---E---F---G origin/master
$ git rebase origin/master

Rebase interativo

O rebase interativo permite você alterar a ordem que os commits são aplicados e ainda juntar vários commits em um só. Se não estiver feliz com a mensagem de algum commit você também pode requisitar para alterar ela.

Com o Git, você pode (e deve) separar as modificações no maior número de commits possível, depois usar rebase interativo para unir os commits.

A lógica por trás disso é que é difícil (e chato) quebrar um commit em dois ou mais, mas é extremamente fácil juntar commits com rebase interativo. Extremamente fácil.

Para ralizar um rebase interativo utilize a flag -i no comando rebase.

$ git rebase -i BRANCH_OU_COMMIT

O Git vai então abrir um editor de texto com a lista de commits referentes a este rebase. Abaixo um exemplo

$ git rebase -i 1111111^

pick 1111111 Define para remover função de debug
pick 2222222 Renomear define para letras maiusculas
pick 3333333 Corrige comparação de tamanho
pick 4444444 Move arquivo
pick 5555555 Teste das funções w()
pick 6666666 Muda nome da função x() para xx()
pick 7777777 fix Formata y()
pick 8888888 Comenta fim do namespace

# Rebase 1111111..8888888 onto 1111111
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Ao editar as linhas você modifica como os commits serão realizados.

  • Foi removido o commit 1111111 comentando a linha com um #
  • O commit 8888888 foi colocado como o primeiro
  • O commit 2222222 será editado logo antes de efetuar o commit
  • O commit 7777777 é juntado com o commit 3333333, reescrevendo a mensagem de commit (squash). Use fixup para não reescrever a mensagem.
  • O commit 5555555 terá a mensagem editada
#pick 1111111 Define para remover função de debug
pick 8888888 Comenta fim do namespace 
edit 2222222 Renomear define para letras maiusculas
pick 3333333 Corrige comparação de tamanho em y()
squash 7777777 fix Formata y()
pick 6666666 Muda nome da função x() para xx() 
reword 5555555 Teste das funções w() 
pick 4444444 Move arquivo

Por favor não se assuste com este exemplo complicado. Eu apenas queria mostrar o poder do rebase interativo em um único exemplo.

De qualquer maneira rebases interativos com muitos commits e correções são comuns e logo se verá fazendo uso.

Concluindo

Dessa forma fica fácil juntar commits e reorganizá-los, não é? Modificar a ordem dos commits é a facilidade que eu mais uso, seguido do comando o fixup e o pelo squash, para juntar commits que corrigem erros pequenos.

Espero que tenham gostado.

Aprendeu algo novo? Compartilhe com seus amigos!

 

Djones

Deixe uma resposta