28. Rebase
Metas
- Usar o comando
rebase
ao invés do merge.
Revertemos o branch style
para o ponto no histórico antes da primeira mesclagem. Há dois commits que estão no ramo main
, mas não no ramo style
: o novo arquivo README
e a alteração conflitante no arquivo index.html
. Desta vez, moveremos essas alterações para o ramo style
usando o comando rebase
em vez do merge
.
01 Rebase do ramo style
para o main
Execute
git switch style
git rebase main
git status
Resultado
$ git switch style
Already on 'style'
$ git rebase main
Rebasing (1/3)
Rebasing (2/3)
Auto-merging hello.html
CONFLICT (content): Merge conflict in hello.html
error: could not apply 903eb1d... Included stylesheet into hello.html
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 903eb1d... Included stylesheet into hello.html
$ git status
interactive rebase in progress; onto 85c14e9
Last commands done (2 commands done):
pick 555372e Added css stylesheet
pick 903eb1d Included stylesheet into hello.html
Next command to do (1 remaining command):
pick 0ee0113 Renamed hello.html; moved style.css
(use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'style' on '85c14e9'.
(fix conflicts and then run "git rebase --continue")
(use "git rebase --skip" to skip this patch)
(use "git rebase --abort" to check out the original branch)
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: hello.html
no changes added to commit (use "git add" and/or "git commit -a")
Há um conflito novamente! Observe que o conflito está em hello.html
e não em index.html
como da última vez. Isso ocorre porque o rebase
estava no processo de aplicar as alterações de style
sobre a ramificação main
. O arquivo hello.html
ainda não foi renomeado no main
, portanto, ainda tem o nome antigo.
Ao fazer a mesclagem, teríamos um conflito "reverso". Durante a mesclagem, as alterações da ramificação main
seriam aplicadas sobre a ramificação style
. A ramificação style
tem o arquivo renomeado, portanto, o conflito estaria em index.html
.
Arquivo: hello.html
<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
<head>
<<<<<<< HEAD
<title>Hello World Page</title>
=======
<link type="text/css" rel="stylesheet" media="all" href="style.css" />
>>>>>>> 903eb1d (Included stylesheet into hello.html)
</head>
<body>
<h1>Hello, World!</h1>
<p>Let's learn Git together.</p>
</body>
</html>
02 Resolver o conflito
O conflito em si pode ser resolvido da mesma forma que fizemos anteriormente. Primeiro, editamos o arquivo hello.html
para atender às nossas expectativas.
Arquivo: hello.html
<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
<head>
<title>Hello World Page</title>
<link type="text/css" rel="stylesheet" media="all" href="style.css" />
</head>
<body>
<h1>Hello, World!</h1>
<p>Let's learn Git together.</p>
</body>
</html>
Mas depois disso, não precisamos confirmar as alterações. Podemos simplesmente adicionar o arquivo ao índice e continuar o processo de rebase. É por isso que adoro o rebase! Ele me permite corrigir conflitos sem criar um monte de conflitos de mesclagem feios.
Por uma questão de simplicidade, podemos adicionar todos os arquivos usando
.
, que representa o caminho do diretório atual. O Git interpreta isso como "adicionar todos os arquivos no diretório atual e seus subdiretórios".
Execute
git add .
git rebase --continue
Aqui, muito provavelmente, o Git abrirá o editor novamente, para que possamos alterar a mensagem do commit. Podemos deixar a mensagem como está. Ao salvar as alterações, o Git concluirá o processo de rebase e poderemos prosseguir com os comandos a seguir:
Execute
git status
git log --all --graph
Resultado
$ git add .
$ git rebase --continue
[detached HEAD 23149b5] Included stylesheet into hello.html
1 file changed, 1 insertion(+)
Rebasing (3/3)
[KSuccessfully rebased and updated refs/heads/style.
$ git status
On branch style
nothing to commit, working tree clean
$ git log --all --graph
* 39a1e0f 2023-11-28 | Renamed hello.html; moved style.css (HEAD -> style) [Alexander Shvets]
* 23149b5 2023-11-28 | Included stylesheet into hello.html [Alexander Shvets]
* b9e6de1 2023-11-28 | Added css stylesheet [Alexander Shvets]
* 85c14e9 2023-11-28 | Added meta title (main) [Alexander Shvets]
* ee16740 2023-11-28 | Added README [Alexander Shvets]
* 9288a33 2023-11-28 | Added copyright statement with email [Alexander Shvets]
* b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
* 46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
* 78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
* 5836970 2023-11-28 | Initial commit [Alexander Shvets]
03 Merge VS Rebase
O resultado do comando rebase
parece muito com o do merge
. O branch style
atualmente contém todas as suas mudanças, além das mudanças do branch main
. A árvore de commits, porém, está um pouco diferente. A árvore de commit do branch style
foi reescrita para fazer o branch main
parte do histórico de commits. Isso faz com que a cadeia de commits seja mais linear e legível.
04 Quando usar o comando rebase
e quando usar o comando merge
?
Use o comando rebase
:
- Quando você obtém alterações de um repositório remoto e deseja aplicá-las ao seu branch local.
- Se você quiser manter o histórico de commits linear e fácil de ler.
Não use o comando rebase
:
- Se o branch atual for público e compartilhado. A reescrita dessas ramificações atrapalhará o trabalho de outros membros da equipe.
- Quando o histórico exato do branch de commit for importante (porque o comando
rebase
reescreve o histórico de commits).
Considerando as recomendações acima, prefiro usar o rebase
para branches locais de curto prazo e o comando merge
para branches no repositório público.