¿Cómo puedo obtener una vista previa de una combinación en git?
Tengo una rama de git (la principal, por ejemplo) y quiero fusionarme en otra rama de desarrollo. ¿O yo?
Para decidir si realmente quiero fusionar esta rama, me gustaría ver algún tipo de vista previa de lo que hará la fusión. Preferiblemente con la capacidad de ver la lista de confirmaciones que se están aplicando.
Hasta ahora, lo mejor que se me ocurre es merge --no-ff --no-commit
y luego diff HEAD
.
git log ..otherbranch
- lista de cambios que se fusionarán en la rama actual.
git diff ...otherbranch
- diferencia del ancestro común (base de fusión) al encabezado de lo que se fusionará. Tenga en cuenta los tres puntos , que tienen un significado especial en comparación con dos puntos (ver más abajo).
gitk ...otherbranch
- representación gráfica de las sucursales desde que se fusionaron la última vez.
La cadena vacía implica HEAD
, por eso simplemente ..otherbranch
en lugar de HEAD..otherbranch
.
Los dos versus tres puntos tienen un significado ligeramente diferente para diff que para los comandos que enumeran revisiones (log, gitk, etc.). Para log y otros, dos puntos ( a..b
) significan todo lo que está en b
pero no a
y tres puntos ( a...b
) significan todo lo que está en solo uno de a
o b
. Pero diff funciona con dos revisiones y allí el caso más simple representado por dos puntos ( a..b
) es una diferencia simple de a
a b
y tres puntos ( a...b
) significan una diferencia entre un ancestro común y b
( git diff $(git merge-base a b)..b
).
Descubrí que la solución que mejor me funciona es simplemente realizar la fusión y cancelarla si hay conflictos . Esta sintaxis particular me parece limpia y sencilla. Esta es la Estrategia 2 a continuación.
Sin embargo, si desea asegurarse de no estropear su rama actual, o simplemente no está listo para fusionarse independientemente de la existencia de conflictos, simplemente cree una nueva subrama a partir de ella y combínela:
Estrategia 1: La forma segura: fusionarse con una rama temporal:
git checkout mybranch
git checkout -b mynew-temporary-branch
git merge some-other-branch
De esa manera puedes simplemente desechar la rama temporal si sólo quieres ver cuáles son los conflictos. No necesita molestarse en "abortar" la fusión y puede volver a su trabajo; simplemente revise 'mybranch' nuevamente y no tendrá ningún código fusionado ni conflictos de fusión en su rama.
Esto es básicamente un ensayo.
Estrategia 2: cuando definitivamente quieres fusionarte, pero solo si no hay conflictos
git checkout mybranch
git merge some-other-branch
Si git informa conflictos (y SÓLO SI HAY conflictos), puede hacer:
git merge --abort
Si la fusión se realiza correctamente, no puede cancelarla (solo restablecerla).
Si no está listo para fusionarse, utilice la forma más segura mencionada arriba.
[EDITAR: noviembre de 2016: cambié la estrategia 1 por 2, porque parece que la mayoría de las personas buscan "el camino seguro". La estrategia 2 ahora es más bien una nota de que simplemente puede cancelar la fusión si ésta tiene conflictos que no está listo para resolver. ¡Tenga en cuenta si lee comentarios!]
La mayoría de las respuestas aquí requieren un directorio de trabajo limpio y múltiples pasos interactivos (malos para las secuencias de comandos), o no funcionan en todos los casos, por ejemplo, fusiones pasadas que ya traen algunos de los cambios pendientes a su rama de destino, o selecciones selectivas que hacen el mismo.
Para ver realmente qué cambiaría en la master
rama si se fusionara develop
con ella, ahora mismo:
git merge-tree $(git merge-base master develop) master develop
Como es un comando de plomería, no adivina lo que quieres decir, tienes que ser explícito. Tampoco colorea la salida ni usa su buscapersonas, por lo que el comando completo sería:
git merge-tree $(git merge-base master develop) master develop | colordiff | less -R
— https://git.seveas.net/previewing-a-merge-result.html
(gracias a David Normington por el enlace)
PD:
Si obtiene conflictos de fusión, aparecerán con los marcadores de conflicto habituales en el resultado, por ejemplo:
$ git merge-tree $(git merge-base a b ) a b
added in both
our 100644 78981922613b2afb6025042ff6bd878ac1994e85 a
their 100644 61780798228d17af2d34fce4cfbdf35556832472 a
@@ -1 +1,5 @@
+<<<<<<< .our
a
+=======
+b
+>>>>>>> .their
El usuario @dreftymac tiene un buen punto: esto lo hace inadecuado para secuencias de comandos, porque no se puede detectar fácilmente en el código de estado. Los marcadores de conflicto pueden ser bastante diferentes según las circunstancias (eliminados o modificados, etc.), lo que también dificulta la búsqueda. Tener cuidado.
Si eres como yo, estás buscando el equivalente a svn update -n
. Lo siguiente parece funcionar. Tenga en cuenta que asegúrese de hacer lo git fetch
primero para que su repositorio local tenga las actualizaciones adecuadas con las que comparar.
$ git fetch origin
$ git diff --name-status origin/master
D TableAudit/Step0_DeleteOldFiles.sh
D TableAudit/Step1_PopulateRawTableList.sh
A manbuild/staff_companies.sql
M update-all-slave-dbs.sh
o si quieres una diferencia desde tu cabeza hasta el control remoto:
$ git fetch origin
$ git diff origin/master
En mi opinión, esta solución es mucho más fácil y menos propensa a errores (y, por lo tanto, mucho menos riesgosa) que la solución principal que propone "fusionar y luego cancelar".
Si ya recuperaste los cambios, mi favorito es:
git log ...@{u}
Sin embargo, creo que eso necesita git 1.7.x. La @{u}
notación es una "taquigrafía" para la rama ascendente, por lo que es un poco más versátil que git log ...origin/master
.
Nota: Si usas zsh y el glog extendido, probablemente tengas que hacer algo como:
git log ...@\{u\}