2012-08-30 11 views
29

digamos que tenemos dos ramas (B y C) que se han ido de un ancestro común Un. Se fusionará desde B a C produce el mismo resultado que la fusión de C a B?¿Las fusiones en Git son simétricas?

A 
    | 
/\ 
B C 

Para aclarar: asumo que cualquier resolución de conflicto de combinación manual se producirá en ambas direcciones. Pero, ¿se producirá alguna fusión automática que resulte en la elección del mismo código? Esto es lo que asumo, ya que las fechas de confirmación son idénticas en ambas direcciones.

Para aclarar aún más: sé que la fusión real da como resultado "imágenes especulares" entre sí en función de la dirección. Solo estoy preguntando sobre los conflictos resueltos automáticamente.

+0

En una nota relacionada, puede encontrar relevante este hilo de tres años de la lista de correo de Git, sobre cómo la fusión de registros de Git es sensible a la "dirección" de la fusión: http: // thread .gmane.org/gmane.comp.version-control.git/127361 – seh

Respuesta

20

La respuesta es sí para las combinaciones predeterminadas. Una fusión de tres vías encuentra un ancestro común y luego aplica las diferencias de ambos lados, una operación que no depende del orden. El tema de orden de fusión y conmutatividad generó una discusión fascinante en el git list (si te gusta ese tipo de cosas, eso es). La nota B into C y C into B deben ser simétricas, pero no necesariamente se puede decir lo mismo para (B into C) into A contra B into (C into A).


Para elaborar un poco más, basado en el comentario de Vince abajo y el comentario de SEH sobre la cuestión, habrá dos diferencias notables entre B into C y C into B, ninguno de los cuales afectan a la resolución de fusión automática se hace referencia en la pregunta.

En primer lugar, la historia será diferente. Los padres de commit de fusión cambiarán según la orden de fusión. Para estos ejemplos, voy a usar "first_branch" y "second_branch", por lo que puedo reservar letras para representar commits.

git checkout first_branch && git merge second_branch 

E <- merge commit 
|\ 
| D <- second_branch's tip 
| | 
| C <- another commit on second_branch 
| | 
| B <- and another 
|/ 
A <- first_branch's tip before the merge 

En este caso, el "primer padre" de E, E^1, es la punta de first_branch antes de la fusión. second_branch es el "segundo padre" de la confirmación de fusión, también conocido como E^2. Ahora considere lo contrario:

git checkout second_branch && git merge first_branch 

E <- merge commit 
|\ 
| D <- first_branch's tip 
| | 
| C <- another commit on first_branch 
| | 
| B <- and another 
|/ 
A <- second_branch's tip before the merge 

Los padres están invertidos. E^1 es la sugerencia de second_branch antes de la fusión. E^2 es la punta de first_branch.

En segundo lugar, se invertirá el orden de visualización de los conflictos.En el primer caso, un conflicto podría tener este aspecto:

<<<<<<< HEAD 
This line was added from the first_branch branch. 
======= 
This line was added from the second_branch branch. 
>>>>>>> second_branch 

En el segundo caso, el mismo conflicto se vería así:

<<<<<<< HEAD 
This line was added from the second_branch branch. 
======= 
This line was added from the first_branch branch. 
>>>>>>> first_branch 

Ninguna de estas diferencias afectan resolución fusión automática, pero aparecen cuando invierte el orden de fusión de tres vías.

+0

¿Le importaría proporcionar un pequeño ejemplo, si lo probó? Quiero decir, tengo curiosidad, si solo se fusiona sin proporcionar ninguna estrategia/opción de combinación, sino forzando la combinación automática (si es posible), ¿qué ocurre si hay un conflicto en una línea? Tendrás: '<<<<<<< tuyo: sample.txt La resolución de conflictos es difícil; vamos de compras. ======= Git facilita la resolución de conflictos. >>>>>>> theirs: sample.txt'? o ¿tendrá uno de ellos elegido, y cuál? – Vince

+0

@Vince El orden es importante para el historial y la forma en que se presentan los conflictos, pero los resultados de la resolución de fusión automática serán los mismos. Edité con más detalles y algunos ejemplos. – Christopher

+0

La publicación de Hamano en la discusión vinculada a esta respuesta es una lectura obligada http://thread.gmane.org/gmane.comp.version-control.git/107737/focus=107895 - no estoy seguro de que brinde una respuesta a la pregunta aunque –

0

no, creo que no será simétrico. Primero puede establecer la opción de combinación de estrategia, particularmente en su caso el theirs o ours que determina si se elegirán B o C.

En las fusiones automáticas, creo que, por ejemplo, la rama remota tiene prioridad sobre sus cambios si se fusiona con la suya, por lo que significa que llamar a git merge C desde B dará como resultado que se elijan C cambios. Aunque no estoy 100% seguro, así que puedes probarlo tú mismo y avisarnos.

+0

el comando para establecer la opción de estrategia: 'git merge -s -X

+0

alguna página de referencia: http://www.kernel.org/ pub/software/scm/git/docs/git-merge.html – Vince

2

Depende de lo que quiera decir con el "mismo resultado". Desde una perspectiva de contenido, suponiendo que no hay conflictos, o que todos los conflictos existentes se resuelven meticulosamente de la misma manera, los contenidos de la nueva confirmación de fusión resultante deben ser los mismos.

Sin embargo, desde el punto de vista de la topología de la historia, los dos son muy diferentes. Si está en la rama B y se fusiona en C, la CABEZA de B se mueve para apuntar a la confirmación de fusión, pero C se queda donde está. Por el contrario, si estás en C y te unes en B, HEAD de C se mueve, mientras que B se queda donde está. Por lo tanto, la topología final es muy diferente, lo que tiene implicaciones para el desarrollo futuro en cualquiera de las ramas, aunque el contenido de la nueva confirmación sea idéntico en ambos casos.

Cuestiones relacionadas