Git Squash Commits
-
Uso de la herramienta interactiva
git rebase
para aplastar los commits de Git -
Uso de
git merge -squash
para aplastar los commits de Git
Aprenderemos a aplastar Git en este tutorial. La idea básica es tomar múltiples commits continuas y combinarlas en una.
La intención principal es condensar muchas commits en unas pocas commits relevantes. Por lo tanto, hacer esto hace que el historial de git se vea conciso y claro.
Otra forma de verlo es que hacemos múltiples commits relacionadas con alguna tarea. Después de un tiempo, cuando alcanzamos un estado satisfactorio, los muchos mensajes de commit saturan el historial de git.
En este punto, es posible que deseemos combinar las diferentes commits en una para que el historial de git se vea claro y refleje mejor la tarea realizada.
Otro caso de uso es aplastar mientras se fusionan ramas. Por lo general, creamos una rama de funciones a partir de la rama principal para el desarrollo de algunas funciones.
Después de completar la función, fusionamos la rama de la función con la rama principal. Aquí también, es posible que deseemos aplastar los diversos mensajes de commit realizados en la rama de funciones en uno cuando se fusionan con la rama principal.
Tenga en cuenta que no existe el comando git squash
.
Hay dos formas de lograr el aplastamiento de Git:
git rebase -i
como herramienta interactiva utilizada para aplastar commitsgit merge -squash
usando la opción-squash
mientras se fusiona
Uso de la herramienta interactiva git rebase
para aplastar los commits de Git
Considere el siguiente extracto de registro de git, que muestra las últimas cuatro commits de HEAD
que estamos interesados en aplastar.
25c38c4 remove .class files
da66e6a Delete version.ini
f4e3f09 Delete .log
b0e6655 Delete .lock
da66e6a github git notes
Podemos ver en el registro los primeros cuatro mensajes de commit que significan las operaciones de eliminación de diferentes archivos irrelevantes. Ahora, aplastaremos estos cuatro compromisos en uno.
A continuación se muestra la sintaxis del comando para aplastar las últimas X commits utilizando la herramienta interactiva de rebase.
git rebase -i HEAD~[X]
Por lo tanto, para aplastar las cuatro commits, haríamos lo siguiente.
$ git rebase -i HEAD~4
Después de emitir este comando, Git invocará el editor predeterminado con detalles de los commits para aplastar, como se muestra a continuación.
pick b0e6655 Delete .lock
pick f4e3f09 Delete .log
pick da66e6a Delete version.ini
pick 25c38c4 remove .class files
# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
# 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
# d, drop = remove commit
#
# 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
El editor muestra las distintas commits con el comando pick
. También muestra información sobre los comandos disponibles. Usaremos el comando squash
(o s
).
Como se muestra a continuación, mantendremos la primera confirmación con el comando pick
y cambiaremos de la orden pick
a la de s
(para aplastar) para las tres commits restantes.
pick b0e6655 Delete .lock
s f4e3f09 Delete .log
s da66e6a Delete version.ini
s 25c38c4 remove .class files
# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
...
los commits marcadas con squash
(o s
) se fusionarán con el commit principal, a saber. el marcado con pick
.
Ahora, guardaremos los cambios en el editor y saldremos. Después de esto, la herramienta rebase -i
abrirá otro editor para ingresar el mensaje de commit, como se muestra a continuación:
# This is a combination of 4 commits. The first commit's message is:
Delete .lock
# This is the 2nd commit message:
Delete .log
# This is the 3rd commit message:
Delete version.ini
# This is the 4th commit message:
remove .class files
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Sun Jan 3 16:39:23 2021 +0530
#
# interactive rebase in progress; onto 652d2fe
# Last commands done (4 commands done):
# pick b0e6655 Delete .lock
# s f4e3f09 Delete .log
# s da66e6a Delete version.ini
# s 25c38c4 remove .class files
# No commands remaining.
# You are currently editing a commit while rebasing branch 'master' on '652d2fe'.
#
# Changes to be committed:
# new file: github-git-notes.txt
#
Ahora, agregaremos el nuevo mensaje de commit en la parte superior del primer mensaje de commit.
Deleted irrelevant files
# This is a combination of 4 commits. The first commit's message is:
Delete .lock
# This is the 2nd commit message:
Delete .log
...
Después de guardar y salir del editor, la herramienta rebase -i
imprimirá el siguiente mensaje.
HEAD~2
Rebasing (2/2)
[detached HEAD caab6e8] Deleted irrelevant files
Date: Sun Jan 3 16:39:23 2021 +0530
1 file changed, 54 insertions(+)
create mode 100644 github-git-notes.txt
Successfully rebased and updated refs/heads/master.
Ahora, comprobaremos el git log
y veremos el mensaje de commit aplastado
(es decir) un solo mensaje de commit en lugar de los cuatro mensajes de commit.
$ git log --oneline
25c38c4 Deleted irrelevant files
da66e6a github git notes
...
Uso de git merge -squash
para aplastar los commits de Git
A continuación se muestra la sintaxis del comando para fusionar una rama con la rama actual (normalmente main
) y aplastar los commits de la rama fuente.
git merge --squash <source_branch_name_to_squash>
Ahora fusionaremos la rama de funciones a saber. feature1
con aplastamiento con la rama main
.
Primero, realizaremos el checkout en la rama main
.
$ git checkout main
Switched to branch 'main'
Luego, haremos un git merge
con la opción squash
de la siguiente manera.
$ git merge --squash feature1
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
Cuando hacemos una fusión
con la opción --squash
, Git no creará un commit de fusión en la rama de destino, como lo hace en una fusión normal. En cambio, Git toma todos los cambios en la rama de origen, a saber. feature1
y lo pone como cambios locales en la copia de trabajo de la rama de destino, es decir, main
.
Por favor ver más abajo.
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: config.ini
Aquí, el archivo config.ini
tiene los cambios realizados en la rama feature1
.
Ahora, todo lo que queda es confirmar los cambios en la rama main
como se muestra a continuación.
$ git commit -am 'Merged and squashed the feature1 branch changes'
[main 573b923] Squashed and merged the feature1 branch
1 file changed, 4 insertions(+)
Por lo tanto, ahora hemos fusionado los cambios en la rama feature1
en la rama main
, junto con aplastar los mensajes de commit de la rama feature1
. Ahora solo tenemos un único mensaje de commit en la rama main
.
Artículo relacionado - Git Rebase
- Git Rebase Origin/Branch vs. Git Rebase Origin Branch
- Rebase a una confirmación específica en Git
- Use Git Rebase en la línea de comando
- Rebase Git Branch
- Reorganizar la rama local al extraer cambios de la rama del repositorio remoto en Git
- Deshacer Rebase en Git