Git: encuentra el antepasado común más reciente de dos ramas

844

¿Cómo encontrar el ancestro común más reciente de dos ramas Git?

Ted
fuente
3
Definir el más reciente: tiempo real, número de confirmaciones, ¿otra métrica?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
2
Relevante (fusiones entrecruzadas): stackoverflow.com/questions/26370185/…
jub0bs
1
@CiroSantilli 新疆 改造 中心 996ICU 六四 事件 es lo mismo en cualquier métrica, ¿no?
YakovL
@YakovL Creo que no debido a la ramificación y porque puede establecer fechas de confirmación arbitrarias en sus objetos de confirmación: esa fecha en sí misma probablemente no sea la que desea.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@CiroSantilli 新疆 改造 中心 996ICU 六四 事件 me parece que solo puede ser diferente si antes de la última confirmación común en el árbol hay una confirmación que tiene una marca de tiempo más antigua. ¿Puedes dar un ejemplo menos trivial?
YakovL

Respuestas:

1019

Que busca git merge-base. Uso:

$ git merge-base branch2 branch3
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2
CB Bailey
fuente
85
Tenga en cuenta que esto encuentra el ancestro común más reciente ... que creo que es lo que quiere el interrogador, por lo que +1. Solo notándolo, en caso de que alguien venga aquí tratando de encontrar el ancestro común más antiguo (como lo hice yo), para lo cual, vea también: stackoverflow.com/questions/1527234/…
lindes
16
@funroll: O la abreviatura para eso:git log master...HEAD
CB Bailey
17
@lindes, ¿el ancestro común más antiguo no sería el commit inicial?
Thorbjørn Ravn Andersen
8
@ ThorbjørnRavnAndersen, sí, supongo que es así ... La dificultad en la descripción viene del hecho de que git usa un Gráfico Acíclico Dirigido y, sin embargo, a menudo se lo considera un árbol, que técnicamente no lo es. Para ser más cuidadoso en mi redacción, estaba hablando del caso en el que desea que el padre de la primera instancia de las "ramas" diverja ... ya que pueden tener múltiples puntos donde se fusionaron y se dividieron nuevamente, esto es el "más antiguo" de estos, pero no es realmente el ancestro más antiguo, que es (creo) siempre el compromiso inicial.
lindes
55
Si bien esta pregunta se trata estrictamente de encontrar un antepasado común de dos ramas, cualquiera que desee el antepasado común de tres o más ramas debe tener en cuenta que deben pasar la --octopusbandera para obtener el resultado correcto. Lo obvio pero incorrecto git merge-base branch1 branch2 branch3le dará una confirmación, pero, como se describe en la sección Discusión en los documentos, no es necesariamente un antepasado común de las tres ramas.
Mark Amery
46

git diff master...feature

muestra todas las nuevas confirmaciones de su rama de característica actual (posiblemente de confirmación múltiple).

man git-diff documentos que:

git diff A...B

es lo mismo que:

git diff $(git merge-base A B) B

pero ...es más fácil de escribir y recordar.

Como lo mencionó Dave , HEADse puede omitir el caso especial de . Entonces:

git diff master...HEAD

es lo mismo que:

git diff master...

que es suficiente si la rama actual es feature.

Finalmente, recuerda que el orden importa! Hacer git diff feature...mastermostrará cambios que no están masteractivados feature.

Deseo que más comandos git admitan esa sintaxis, pero no creo que lo hagan. Y algunos incluso tienen una semántica diferente para ...: ¿Cuáles son las diferencias entre doble punto "..." y triple punto "..." en los rangos de confirmación de Git?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
8
O simplemente git diff master...en el caso especial de diferir aHEAD
Dave
el "..." no funcionó para mí en PowerShell, curioso, funcionó en la consola git, tal vez el repositorio no estaba completo, git diff $ (git merge-base AB) B sí lo hizo y, dado que soy un poco nuevo en git Estaba un poco escéptico de que esto pudiera fusionar las ramas :)
Moiz Ahmed
1
Guau. bastante sorprendente. y si la sucursal que desea no existe en su repositorio local porque nunca la revisó, simplemente puede hacerlogit diff origin/branchname...
Mark Ch
25

Como se señaló en una respuesta anterior, git merge-basefunciona:

$ git merge-base myfeature develop
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

pero si myfeaturees la rama actual, como es común, puede usar use --fork-point:

$ git merge-base --fork-point develop
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2

Este argumento solo funciona en versiones suficientemente recientes de git. Desafortunadamente, no siempre funciona, y no está claro por qué. Consulte las limitaciones observadas al final de esta respuesta .


Para obtener información de confirmación completa, considere:

$ git log -1 $(git merge-base --fork-point develop) 
Acumenus
fuente
Tengo git version 2.14.1.windows.1. Ejecutar git merge-base --fork-point branch2con una rama (con sus propios commits) que sé que se bifurcó desde la rama actual no produce ningún resultado, mientras que git merge-base branch1 branch2muestra correctamente el punto de bifurcación. ¿Cual podría ser el problema?
ADTC
@ADTC Checkout branch2y luego ejecutar git merge-base --fork-point branch1.
Acumenus
@ADTC Use un visor gráfico de confirmación, por ejemplo gitk, etc. para ver cómo se ve el árbol. Tal vez obtendrás tu respuesta.
Acumenus
No veo nada extraño en el árbol cuando lo veo gráficamente. Puedo rastrear los caminos y encontrar el ancestro común que coincide con el resultado de git merge-base branch1 branch2. Pero lo extraño es que --fork-pointno da nada de ninguna manera. ¿Ha confirmado que funciona para usted según lo previsto?
ADTC
1
Me sale lo mismo que @ADTC. El comando 'git log -1 $ (git merge-base --fork-point anotherBranch)' no muestra ningún resultado con git versión 2.16.2.windows.1.
masinger
10

Con gitkusted puede ver las dos ramas gráficamente:

gitk branch1 branch2

Y luego es fácil encontrar el antepasado común en la historia de las dos ramas.

Martin G
fuente
66
No todo se puede hacer visualmente en todos los casos. Hay razones por las cuales las cosas pueden necesitar ser automatizadas programáticamente.
ADTC