git rebase
git rebase cambia el historial de commits pero crea un historial lineal moviendo feature a la punta del main.
Step 1. Clone the repository
Igual que el paso 1 de antes, empezamos de nuevo.
Step 2. Perform rebase
Con los siguientes comandos
git switch feature
git rebase origin/main
Tendremos este output con el conflicto en mayúsculas.
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
error: could not apply d64444a... feature increases every number by 20
Resolve all conflicts manually, mark them as resolved with
"git add/rm ", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply d64444a... feature increases every number by 20
Se puede verificar por git status
interactive rebase in progress; onto d5ba99b
Last command done (1 command done):
pick d64444a feature increases every number by 20
No commands remaining.
You are currently rebasing branch 'feature' on 'd5ba99b'.
(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 ..." to unstage)
(use "git add ..." to mark resolution)
both modified: file.txt
no changes added to commit (use "git add" and/or "git commit -a")
Tanto la salida de git rebase como de git status listan tres opciones:
- Arreglar los conflictos y luego ejecutar git rebase –continue.
- Usar git rebase –skip para omitir este parche.
- Usar git rebase –abort para revisar la rama original.
Estamos en medio de rebase. Lo podemos ver con git branch
* (no branch, rebasing feature)
feature
main
No está permitido dejar un rebase inacabado.
git switch -f feature
#Output
fatal: cannot switch branch while rebasing
Consider "git rebase --quit" or "git worktree add".
---
git switch -f feature
#Output
fatal: cannot switch branch while rebasing
Consider "git rebase --quit" or "git worktree add".
Paso 3. Resolver los conflictos
Debemos elegir una de las tres opciones. La opción 1 es para resolver los conflictos manualmente. Como hicimos con git merge. Pero después de confirmar los cambios y comitear tendremos que continuar el rebase.
git add .
git commit -m "feature resolves conflicts"
git rebase --continue
#Output
Successfully rebased and updated refs/heads/feature.
Paso 4. Push rebase al remote
Estamos listos para el push.
git push
#Output
To https://github.com/JenniferFuBook/git-rebase
! [rejected] feature -> feature (non-fast-forward)
error: failed to push some refs to 'https://github.com/JenniferFuBook/git-rebase'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
¿Qué ha pasado? 🤯
¿Debemos seguir el consejo del output y hacer un pull? 🤔
git pull origin master
#Output
hint: Pulling without specifying how to reconcile divergent branches is
hint: discouraged. You can squelch this message by running one of the following
hint: commands sometime before your next pull:
hint:
hint: git config pull.rebase false # merge (the default strategy)
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
error: Pulling is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
La salida del pull muestra claramente que el consejo es engañoso. 😩
Después de ejecutar el comando rebase, la rama remota no puede ser adelantada al commit fusionado. Con lo cual, git push –force es necesario para el rebase. 👍
git push --force
#Output
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 396 bytes | 396.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/JenniferFuBook/git-rebase
+ d64444a...ba4c3fb feature -> feature (forced update)
Ahora si vamos al repositorio remoto de git-rebase veremos que el resultado de nuestro git rebase ha sido pusheado
Paso 5. Examinar el historial de rebase
Vamos a revisar el historial con git log –all –graph.
* commit ba4c3fbd670c08f30d7a16371719a81714ea8899 (HEAD -> feature, origin/feature)
| Author: Jennifer Fu <jennifer.fu@dominodatalab.com>
| Date: Sat Mar 13 12:24:24 2021 -0800
|
| feature resolves conflicts
|
* commit d5ba99b96eedc106040aa63973e9fc7c08ee6f78 (origin/main, origin/HEAD, main)
| Author: Jennifer Fu <jennifer.fu@dominodatalab.com>
| Date: Wed Mar 10 19:35:22 2021 -0800
|
| main adds a new file
|
* commit 9ff737a22d918f5781363b244104f394ef4a67e3
| Author: Jennifer Fu <jennifer.fu@dominodatalab.com>
| Date: Wed Mar 10 19:15:56 2021 -0800
|
| main increases every number by 10
|
* commit a6cd6c726a7d9bca0aec7d2af88914d79ceeedf3
| Author: Jennifer Fu <jennifer.fu@dominodatalab.com>
| Date: Wed Mar 10 19:13:08 2021 -0800
|
| Create file.txt
|
* commit 78444c6cd523a305de2b7e8874b1ea6cc22f2afd
Author: Jennifer Fu <54613999+JenniferFuBook@users.noreply.github.com>
Date: Wed Mar 10 19:06:25 2021 -0800
Initial commit
En la representación gráfica del git rebase vemos las rutas de commits lineales. La confirmación en la rama se reescribe para ser ba4c3fbd670c08f30d7a16371719a81714ea8899, desde la punta de main. En lugar de crear un commit de fusión adicional, rebase reescribe la historia del proyecto creando nuevos commits para cada commit en la rama main. El commit original, d64444a78401995781a3efce9ab250d43c19a022, es reemplazado por ba4c3fbd670c08f30d7a16371719a81714ea8899.
El siguiente es el diagrama conceptual del historial de commits.
Precioso ¿Verdad? Pues aun nos queda otra opción.