imagen

Git Rebase: Ordenando el caos

Reescribiendo la historia

Solo el últimos commit

git commit --amend Nos permite agregar cambios que hayamos olvidado al ultimo commit y también nos permite modificar el mensaje del commit.

Pero y si son varios commits de la historia

Supongamos que tenemos los últimos 8 commits así (ordenados de forma DESC, el mas reciente al inicio)

5471c6d Merge branch 'feature/add-carDetail'
9e1419f Merge branch 'install-scaffold' into feature/add-carDetail
d16f148 chore: update .gitignore file macos garbage files
a5eeab9 chore: organizing if statements to evualuate border cases test
16eb612 chore: add more cases tu evualuated test
5a2ba39 chore: Add $ simbol to variables test
21a6d18 Revert "wip: Implementing carousel Swiper library"
3be0a6e wip: Implementing carousel Swiper library

Y necesitamos:

  • Eliminar 5471c6d
  • Editar el mensaje de a5eeab9
  • Editar el mensaje de 16eb612
  • Eliminar 5a2ba39
  • Eliminar 21a6d18
  • Eliminar 3be0a6e

Podemos ayudarnos del comando git rebase interactive git rebase -i HEAD~N, donde N es la cantidad de commits que queremos considerar en la modificación desde el ultimo commit que tenemos en nuestra rama, para nuestro caso de ejemplo queremos editar los ultimos 8 commits, usaremos git rebase -i HEAD~8

Nos mostrara lo siguiente:

pick 9c01e69 feats:  add general layout carDetail component
pick 7c3ad1e feat: add helper for number format
pick 3be0a6e wip: Implementing carousel Swiper library
pick 21a6d18 Revert "wip: Implementing carousel Swiper library"
pick 5a2ba39 chore: Add $ simbol to variables test
pick 16eb612 chore: add more cases tu evualuated test
pick a5eeab9 chore: organizing if statements to evualuate border cases test
pick d16f148 chore: update .gitignore file macos garbage files

# Rebase 11862b5..5471c6d onto 11862b5 (8 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
#                    commit's log message, unless -C is used, in which case
#                    keep only this commit's message; -c is same as -C but
#                    opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified); use -c <commit> to reword the commit message
#
# 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.
#

Se abre el editor de textos y primero nos muestra el grupo de commits que vamos a editar, luego el conjunto de acciones que podemos hacer con cada commit y finalmente algunos "warnings" importantes a considerar.

Los warnings que debemos considerar son:

  • Las lineas (commits) pueden ser re-ordenados y los commits sera reescritos en ese orden.
  • Si remueve una linea completa, el commit se perderá (eliminado)
  • Si remueves todas las lineas, el rebase sera abortado.

Adicionalmente es importante mencionar:

  • No incluya ningún commit que ya haya enviado a un servidor central, hacerlo confundirá a otros desarrolladores al proporcionar una versión alternativa (nuevo hash) del mismo commit.
  • Tenga en cuenta que las confirmaciones (commits) vacíos son ignoradas, no se muestran al momento de hacer el rebase y esos commits serán eliminados, por esa razon al hacer el rebase no vemos 5471c6d 9e1419f dado que son commits de un merge y son commits vacíos.
  • Es importante tener en cuenta que estos commits se enumeran en el orden opuesto al que normalmente los ve usando el comando de git log.

Considerando lo anterior, ahora podemos enfocarnos en aplicar los cambios sobre nuestros commits.

  • Para eliminar, podemos usar drop o d
  • Para modificar el mensaje podemos usar reword o r

solo debemos movernos con el cursos y reemplazar pick por el la acción que queremos realizar con cada commits, nos quedaría algo así

pick 9c01e69 feats:  add general layout carDetail component
pick 7c3ad1e feat: add helper for number format
drop 3be0a6e wip: Implementing carousel Swiper library
drop 21a6d18 Revert "wip: Implementing carousel Swiper library"
drop 5a2ba39 chore: Add $ simbol to variables test
reword 16eb612 chore: add more cases tu evualuated test
reword a5eeab9 chore: organizing if statements to evualuate border cases test
pick d16f148 chore: update .gitignore file macos garbage files

Lo anterior eliminara los commits que hemos indicado como drop y nos permitirá modificar el mensaje de los commits que hemos indicado como reword. Cuando ya tenemos todo listo, bastara con salir del editor, este nos preguntara si queremos guardar los cambios, y al confirmar es cuando git empezara a recorrer la cadena de commits uno a uno aplicando las modificaciones que indicamos.

Para los drop no preguntara nada, para los reword ira abriendo un commit a la vez para permitirnos editar los mensajes.

El proceso de rebase se detendrá en caso de que aparezcan conflictos, debes revisar los conflictos en tu editor, y aplicar un git add para agregar los cambios y luego un git rebase --continue para que el rebase continúe desde donde había quedado.

En caso que surjan conflictos y no quieras continuar, puede hacer un git rebase --abort y no se aplicara ningún cambio a la rama.

pero no me creas, ve a la docu oficial