¿Cómo usar git merge --squash?

1210

Tengo un servidor Git remoto, este es el escenario que quiero realizar:

  • Para cada error / característica creo una rama Git diferente

  • Sigo confirmando mi código en esa rama de Git con mensajes Git no oficiales

  • En el repositorio superior, tenemos que hacer un commit para un error con el mensaje oficial de Git

Entonces, ¿cómo puedo fusionar mi sucursal con la sucursal remota para que obtengan solo una confirmación para todos mis registros (incluso quiero proporcionar un mensaje de confirmación para esto)?

SunnyShah
fuente
1
No estoy seguro si te entendí por completo, pero es posible que desees una "fusión de pulpo".
MatrixFrog
27
Normalmente uso git rebase -i para contraer todas mis confirmaciones en una confirmación y reescribir el mensaje de confirmación. Luego lo envío río arriba.
Edward Falk
17
git merge --squashlo hace todo en la línea de comando de una sola vez y solo espera que funcione. git rebase -iabre un editor y le permite afinar el rebase. Es más lento, pero puedes ver lo que estás haciendo. Además, hay una diferencia entre rebase y merge que son demasiado complicadas para abordarlas en un comentario.
Edward Falk
44
el problema con todas estas respuestas es que tienes que estar en la rama maestra localmente y ejecutar el comando merge --squash ... Quiero ejecutar la fusión --squash desde la rama característica, no desde la rama master ... para que cuando termine, puedo empujar la rama de funciones al control remoto y enviar un RP, ¿es posible?
Alexander Mills el
2
@AlexanderMills, creo que solo necesita una segunda rama de características (clonada de la rama maestra). Haga lo merge --squashanterior a lo nuevo, y luego combine la nueva rama para dominar. La antigua rama se vuelve obsoleta.
Gyromite

Respuestas:

2002

Supongamos que se llama a su rama de corrección de errores bugfixy desea fusionarla en master:

git checkout master
git merge --squash bugfix
git commit

Esto tomará todos los commits de la bugfixrama, los aplastará en 1 commit y los combinará con su masterbranch.


Explicacion :

git checkout master

Cambia a su masterrama.

git merge --squash bugfix

Toma todas las confirmaciones de la bugfixrama y las fusiona con su rama actual.

git commit

Crea una única confirmación a partir de los cambios combinados.

Omitir el -mparámetro le permite modificar un borrador de mensaje de confirmación que contiene cada mensaje de sus confirmaciones aplastadas antes de finalizar su confirmación.

abyx
fuente
222
Si desea mantener referencias a los mensajes de confirmación anteriores, puede escribir git commit(sin -mparámetro) y podrá modificar un mensaje de confirmación redactado que contiene todos los mensajes de confirmación que eliminó.
Alex
12
Puede lograr lo mismo haciendo git commit --amend -m '...'más adelante.
Janusz Lenar
19
En caso de que se produzcan conflictos de fusión y resuelva estos conflictos, git commitya no se mostrará el útil mensaje de confirmación que contiene todos los mensajes de confirmación que eliminó. En ese caso, intente git commit --file .git/SQUASH_MSG(a través de stackoverflow.com/a/11230783/923560 ).
Abdull
23
Tenga en cuenta que el aplastamiento por defecto atribuirá los commits al aplastador . Para conservar el autor original, debe especificarlo explícitamente así:git commit -a --author="Author" --message="Issue title #id"
gaborous
55
git merge --squashle permite crear una sola confirmación sobre la rama actual cuyo efecto es el mismo que fusionar otra rama. Pero no producirá el registro de combinación, lo que significa que su solicitud de extracción como resultado no tendrá cambios, ¡pero no se marcará como combinada! Por lo tanto, solo tendrá que eliminar esa rama para hacerlo.
am0wa
129

Lo que finalmente me aclaró esto fue un comentario que muestra que:

git checkout main
git merge --squash feature

es el equivalente a hacer:

git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .

Cuando quiero fusionar una rama de características con 105 (!!) confirmaciones y hacer que todas se agrupen en una sola, no quiero hacerlo git rebase -i origin/masterporque necesito resolver por separado los conflictos de fusión para cada una de las confirmaciones intermedias (o al menos las que Git no puede darse cuenta de sí mismo). El uso git merge --squashme da el resultado que quiero, de una sola confirmación para fusionar una rama de características completa. Y, solo necesito hacer como máximo una resolución manual de conflictos.

Dan Kohn
fuente
75
Recomiendo encarecidamente realizar la fusión en la rama de características primero git merge master, y solo luego git merge --squash featureen la rama maestra.
dotancohen
8
@dotancohen Perdón por desenterrar un comentario anterior :) ¿Qué se obtiene al fusionarse en la rama de características antes de realizar git merge --squash featuredesde la rama maestra?
Bitsmack 01 de
57
Desea fusionar el maestro en la rama de características primero, y tratar con cualquier corrección manual en su rama de características. Eso también le permite ejecutar pruebas y asegurarse de que su rama de características funcione correctamente. Entonces, tiene la garantía de que puede hacer una fusión automática de su rama de características en master.
Dan Kohn
44
@dankohn Le sugiero que agregue la explicación en su comentario anterior en su respuesta.
guntbert
3
@bitsmack: primero fusionarías master en feature. Esto le brinda la oportunidad de resolver conflictos en la función antes de fusionarla con la maestra
Mike
97

Desea fusionarse con la opción de squash. Eso si quieres hacerlo una rama a la vez.

git merge --squash feature1

Si desea fusionar todas las ramas al mismo tiempo que las confirmaciones individuales, primero vuelva a redactar de forma interactiva y elimine cada característica y luego combine pulpo:

git checkout feature1
git rebase -i master

Aplaste en una confirmación y luego repita para las otras características.

git checkout master
git merge feature1 feature2 feature3 ...

Esa última fusión es una "fusión de pulpo" porque está fusionando muchas ramas a la vez.

Espero que esto ayude

Adam Dymitruk
fuente
3
¿Por qué estás haciendo rebase?
Umair A.
12
@UmairAshraf es un rebase interactivo que te da la opción de hacer una calabaza dentro de tu rama.
andho
1
Rebasar es una mala idea. No rebases los commits ya publicados
Sebi2020
1
@ Sebi2020 git merge --squash modificará sus confirmaciones ya publicadas de una manera peor que una repetición interactiva. Un rebase interactivo (en una rama de características) tiene poco o ningún efecto adverso.
xiix
1
@xiix Esto solo es cierto si usted es el único que trabaja con la rama de características. Esto no es una suposición que puedas hacer. Recomiendo leer las páginas relacionadas con el rebase en Git-SCM . Establece " No vuelva a redactar los compromisos que existen fuera de su repositorio y las personas pueden haber basado su trabajo en ellos " . Y si no sabe con certeza si las personas ya basan su trabajo en los compromisos publicados (lo que no puede saber debido a la descentralización naturaleza de git) no deberías hacer eso.
Sebi2020
23

Si ya tiene git merge bugfixen main, puede aplastar la combinación de cometer en uno con:

git reset --soft HEAD^1
git commit
qwertzguy
fuente
git reset --soft HEAD^1parece deshacer la última confirmación realizada antes de la fusión, al menos en el caso de que la fusión sea un avance rápido.
Jesper Matthiesen
@JesperMatthiesen en caso de un avance rápido, no obtienes una confirmación de fusión, entonces lo harías git reset --soft HEAD^<number-of-commits-to-squash>.
qwertzguy
Esto me ayudó a aplastar todo en una sola confirmación después de una fusión aguas abajo.
killjoy
18

Fusionar newFeaturerama mastercon una confirmación personalizada:

git merge --squash newFeature && git commit -m 'Your custom commit message';

Si en cambio, lo haces

git merge --squash newFeature && git commit

recibirá un mensaje de confirmación que incluirá todas las newFeatureconfirmaciones de rama, que puede personalizar.

Lo explico a fondo aquí: https://youtu.be/FQNAIacelT4

Vagelis Prokopiou
fuente
10

Sé que esta pregunta no se trata específicamente de Github, pero dado que Github es muy utilizado y esta es la respuesta que estaba buscando, la compartiré aquí.

Github tiene la capacidad de realizar fusiones de squash, dependiendo de las opciones de fusión habilitadas para el repositorio.

Si las fusiones de squash están habilitadas, la opción "Squash and merge" debería aparecer en el menú desplegable debajo del botón "Merge".

Captura de pantalla de la función Github "Squash and merge"

Aaron
fuente
GitHub usa el correo electrónico predeterminado asociado con su cuenta. Si tiene varias direcciones de correo electrónico y necesita usar una secundaria, no puede usar GH UI.
Luca Guidi
4

Suponga que trabajó en feature / task1 con múltiples commits.

  1. Vaya a la rama de su proyecto (project / my_project)

    git checkout project/my_project
    
  2. Crear una nueva sucursal (feature / task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. Marge con la --squashopción

    git merge --squash feature/task1
    
  4. Crear una sola confirmación

    git commit -am "add single comments"
    
  5. Empuja tu rama

    git push --set-upstream origin feature/task1_bugfix
    
Farid Haq
fuente
1

Para Git

Crea una nueva característica

a través de Terminal / Shell:

git checkout origin/feature/<featurename>
git merge --squash origin/feature/<featurename>

Esto no lo compromete, le permite revisarlo primero.

Luego, confirme y termine la función de esta nueva rama, y ​​elimine / ignore la anterior (la que realizó).

Demian Berisford-Maynard
fuente
@Melebius La única referencia a "SourceTree" está en su oración, si era una etiqueta o una pregunta anterior: ya no existe.
Jordan Stefanelli
1
@JordanStefanelli SourceTree se utilizó en la versión original de esta respuesta . ¡Gracias por notificar que está arreglado!
Melebius
1

si obtiene un error: la confirmación no es posible porque tiene archivos no fusionados.

git checkout master
git merge --squash bugfix
git add .
git commit -m "Message"

reparó todos los archivos de conflicto

git add . 

también podrías usar

git add [filename]
ResUta
fuente
0

Para aplastar su rama local antes de empujarla:

  1. revise la rama en cuestión para trabajar si aún no está desprotegida.

  2. Encuentra el sha del compromiso más antiguo que deseas mantener.

  3. Crear / pagar una nueva rama (tmp1) a partir de esa confirmación.

    git checkout -b tmp1 <sha1-of-commit>

  4. Fusiona la rama original con la nueva aplastando.

    git merge --squash <original branch>

  5. Confirme los cambios creados por la fusión, con un mensaje de confirmación de resumen.

    git commit -m <msg>

  6. Verifique la rama original que desea aplastar.

    git checkout <branch>

  7. Restablezca el commit original que desea mantener.

    git reset --soft <sha1>

  8. Rebase esta rama basada en la nueva rama tmp1.

    git rebase tmp1

  9. Eso es todo, ahora elimine la rama temporal tmp1 una vez que esté seguro de que todo está bien.

Jool
fuente
0

Puede usar la herramienta que he creado para facilitar este proceso: git-squash . Por ejemplo, para aplastar todas las confirmaciones en la rama de características que se ha ramificado desde la rama maestra, escriba:

git squash master
git push --force
sheerun
fuente