Tengo un repositorio con ramas master y A y mucha actividad de fusión entre los dos. ¿Cómo puedo encontrar el commit en mi repositorio cuando se creó la rama A basada en master?
Mi repositorio básicamente se ve así:
-- X -- A -- B -- C -- D -- F (master)
\ / \ /
\ / \ /
G -- H -- I -- J (branch A)
Estoy buscando la revisión A, que no es lo que git merge-base (--all)
encuentra.
Respuestas:
Estaba buscando lo mismo, y encontré esta pregunta. Gracias por preguntar!
Sin embargo, encontré que las respuestas que vemos aquí no parecen bastante dar la respuesta que solicitó (o que yo estaba buscando) - que parecen dar la
G
confirmación, en lugar de laA
confirmación.Entonces, he creado el siguiente árbol (letras asignadas en orden cronológico), para poder probar las cosas:
Esto se ve un poco diferente al tuyo, porque quería asegurarme de que obtuve (refiriéndome a este gráfico, no el tuyo) B, pero no A (y no D o E). Aquí están las letras adjuntas a los prefijos SHA y mensajes de confirmación (mi repositorio se puede clonar desde aquí , si eso es interesante para alguien):
Por lo tanto, el objetivo: Encontrar B . Aquí hay tres formas que encontré, después de un poco de retoques:
1. visualmente, con gitk:
Debería ver visualmente un árbol como este (como se ve desde el maestro):
o aquí (como se ve desde el tema):
En ambos casos, he seleccionado la confirmación que está
B
en mi gráfico. Una vez que hace clic en él, su SHA completo se presenta en un campo de entrada de texto justo debajo del gráfico.2. visualmente, pero desde la terminal:
git log --graph --oneline --all
(Editar / nota al margen: agregar
--decorate
también puede ser interesante; agrega una indicación de nombres de ramas, etiquetas, etc. No agrega esto a la línea de comandos anterior ya que el resultado a continuación no refleja su uso).que muestra (suponiendo
git config --global color.ui auto
):O, en texto directo:
En cualquier caso, vemos el 6aafd7f commit como el punto común más bajo, es decir,
B
en mi gráfico oA
en el suyo.3. Con magia de concha:
No especifique en su pregunta si desea algo como lo anterior, o un solo comando que solo le dará una revisión, y nada más. Bueno, aquí está lo último:
Lo que también puede poner en su ~ / .gitconfig como (nota: el guión final es importante; gracias Brian por llamar la atención sobre eso) :
Lo que podría hacerse a través de la siguiente línea de comandos (complicada con comillas):
Nota:
zsh
podría fácilmente haber sidobash
, perosh
lo hará sin trabajo - la<()
sintaxis no existe en la vainillash
. (¡Gracias de nuevo, @conny, por informarme en un comentario sobre otra respuesta en esta página!)Nota: Versión alternativa de lo anterior:
Gracias a liori por señalar que lo anterior podría caerse al comparar ramas idénticas y crear una forma de diferencia alternativa que elimine la forma sed de la mezcla y la haga "más segura" (es decir, devuelve un resultado (es decir, el confirmación más reciente) incluso cuando compara maestro con maestro):
Como una línea .git-config:
De la cáscara:
Entonces, en mi árbol de prueba (que no estuvo disponible por un tiempo, lo siento; está de regreso), eso ahora funciona tanto en el maestro como en el tema (dando confirmaciones G y B, respectivamente). Gracias de nuevo, liori, por la forma alternativa.
Entonces, eso es lo que yo [y liori] inventamos. Parece funcionar para mí También permite un par adicional de alias que pueden resultar útiles:
¡Feliz git-ing!
fuente
diff
que está if-then-else modo de borrado y cambiar / borrar las líneas de su salida en lugar de contar en tener contexto lo suficientemente grande, por.:diff --old-line-format='' --new-line-format='' <(git rev-list …) <(git rev-list …)|head -1
.git log -n1 --format=format:%H $(git log --reverse --format=format:%H master..topic | head -1)~
también funcionará, creogit merge-base --fork-point ...
commit B (commit6aafd7f
) para este árbol? Estaba ocupado con otras cosas cuando publicaste eso, y sonaba bien, pero finalmente lo probé y no estoy logrando que funcione ... O recibo algo más reciente o simplemente una falla silenciosa (sin error mensaje, pero el código de salida 1), tratando argumentos comogit co master; git merge-base --fork-point topic
,git co topic; git merge-base --fork-point master
,git merge-base --fork-point topic master
(ya sea para la salida), etc. ¿hay algo que estoy haciendo mal o que falta?--fork-point
se basa en el registro, por lo que solo funcionará si realizó los cambios localmente. Incluso entonces, las entradas de reflog podrían haber expirado. Es útil pero no confiable en absoluto.Quizás estés buscando
git merge-base
:fuente
--all
opción de "git merge-base
"git merge-base
cinco horas después de que se publicara mi respuesta (probablemente en respuesta a mi respuesta). Sin embargo, dejaré esta respuesta tal como está porque aún puede ser útil para alguien más que encuentre esta pregunta a través de la búsqueda.Lo he usado
git rev-list
para este tipo de cosas. Por ejemplo, (tenga en cuenta los 3 puntos)escupirá el punto de ramificación. Ahora, no es perfecto; ya que has fusionado maestro en rama A un par de veces, eso dividirá un par de posibles puntos de ramificación (básicamente, el punto de ramificación original y luego cada punto en el que fusionó el maestro en la rama A). Sin embargo, al menos debería reducir las posibilidades.
He agregado ese comando a mis alias
~/.gitconfig
como:entonces puedo llamarlo como:
fuente
G
lugar deA
, según el gráfico de la pregunta original). Tengo una respuesta que reciboA
, que publicaré en este momento.git checkout topic
y luego ejecutar esto contopic
en lugar debranch-a
), enumera648ca357b946939654da12aaf2dc072763f3caee
y37ad15952db5c065679d7fc31838369712f0b338
- ambos37ad159
y648ca35
están en el ancestro de las ramas actuales (esta última es la CABEZA actual detopic
) pero tampoco es el punto antes de que ocurriera la ramificación. ¿Obtienes algo diferente?Si te gustan los comandos concisos,
Aquí hay una explicación.
El siguiente comando le proporciona la lista de todas las confirmaciones en el maestro que ocurrieron después de que se creó branch_name
Como solo te importa la primera de esas confirmaciones, quieres la última línea de la salida:
El padre de la primera confirmación que no es un antepasado de "branch_name" está, por definición, en "branch_name", y está en "master" ya que es un antepasado de algo en "master". Entonces tienes la primera confirmación que está en ambas ramas.
El comando
es solo una forma de mostrar la referencia de confirmación principal. Podrías usar
o lo que sea.
PD: No estoy de acuerdo con el argumento de que el orden de los antepasados es irrelevante. Depende de lo que quieras. Por ejemplo, en este caso
tiene mucho sentido generar C2 como la confirmación de "ramificación". Esto es cuando el desarrollador se ramificó de "maestro". Cuando se bifurcó, ¡la rama "B" ni siquiera se fusionó en su rama! Esto es lo que da la solución en esta publicación.
Si lo que desea es la última confirmación C de modo que todas las rutas desde el origen hasta la última confirmación en la rama "A" pasen por C, entonces desea ignorar el orden de ascendencia. Eso es puramente topológico y te da una idea de cuándo tienes dos versiones del código funcionando al mismo tiempo. Fue entonces cuando usaría enfoques basados en la combinación de bases, y devolverá C1 en mi ejemplo.
fuente
git rev-list commit^^!
se puede simplificar comogit rev-parse commit^
git rev-list --first-parent ^branch_name master
congit rev-list --first-parent branch_name ^master
porque si la rama principal es 0 compromete por delante de la otra rama (rápido-remitible a ella), se crearía ninguna salida. Con mi solución, no se crea ningún resultado si el maestro está estrictamente adelantado (es decir, la rama se ha fusionado por completo), que es lo que quiero.git rev-list --first-parent ^topic master
solo lo llevará de regreso a la primera confirmación después de la última combinación demaster
entopic
(si eso incluso existe).Dado que muchas de las respuestas en este hilo no dan la respuesta que pedía la pregunta, aquí hay un resumen de los resultados de cada solución, junto con el script que utilicé para replicar el repositorio dado en la pregunta.
El registro
Al crear un repositorio con la estructura dada, obtenemos el registro git de:
Mi única adición es la etiqueta que lo hace explícito sobre el punto en el que creamos la rama y, por lo tanto, la confirmación que deseamos encontrar.
La solución que funciona.
La única solución que funciona es la que proporciona lindes correctamente
A
:Sin embargo, como señala Charles Bailey , esta solución es muy frágil.
Si
branch_A
enmaster
y luego fusionarsemaster
enbranch_A
sin intervenir compromete a continuación, la solución lindes' sólo le da la más reciente primero divergance .Eso significa que para mi flujo de trabajo, creo que tendré que seguir etiquetando el punto de ramificación de las sucursales de larga ejecución, ya que no puedo garantizar que se puedan encontrar de manera confiable más adelante.
Esto realmente se reduce a
git
la falta de lo que sehg
llama ramas denominadas . El blogger jhw llama a estos linajes vs. familias en su artículo Why I Like Mercurial More Than Git y su artículo de seguimiento More On Mercurial vs. Git (con Graphs!) . Os recomiendo que lean ellos para ver qué algunos conversos no mercuriales de menos tener el nombre ramas engit
.Las soluciones que no funcionan
La solución proporcionada por mipadi devuelve dos respuestas
I
yC
:La solución provista por Greg Hewgill regresa
I
La solución proporcionada por Karl devuelve
X
:La secuencia de comandos
Dudo que la versión git haga mucha diferencia en esto, pero:
Gracias a Charles Bailey por mostrarme una forma más compacta de guiar el repositorio de ejemplos.
fuente
diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1
. Gracias por proporcionar instrucciones para crear el repositorio :)En general, esto no es posible. En la historia de una rama, una rama y fusión antes de que una rama con nombre se bifurcara y una rama intermedia de dos ramas con nombre se vea igual.
En git, las ramas son solo los nombres actuales de los consejos de las secciones de la historia. Realmente no tienen una identidad fuerte.
Esto no suele ser un gran problema, ya que la base de fusión (ver la respuesta de Greg Hewgill) de dos confirmaciones suele ser mucho más útil, dado la confirmación más reciente que las dos ramas compartieron.
Obviamente, una solución basada en el orden de los padres de un commit no funcionará en situaciones en las que una sucursal se haya integrado completamente en algún momento de la historia de la sucursal.
Esta técnica también se cae si se ha realizado una fusión de integración con los padres invertidos (p. Ej., Se usó una rama temporal para realizar una fusión de prueba en maestro y luego se reenvió rápidamente en la rama de características para seguir avanzando).
fuente
git
tenía un equivalente a lahg
que está llamado ramas, sería hacer la gestión de las ramas de mantenimiento de larga vida de manera mucho más fácil.¿Qué tal algo como
fuente
diverges = !bash -c 'git rev-parse $(diff <(git log --pretty=oneline ${1}) <(git log --pretty=oneline ${2}) | tail -1 | cut -c 3-42)^'
(sin archivos temporales)G
lugar deA
, según el gráfico de la pregunta original). Sin embargo, creo que he encontrado una respuesta, que publicaré en el presente.diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1
seguramente me estoy perdiendo algo, pero en mi opinión, todos los problemas anteriores están causados porque siempre estamos tratando de encontrar el punto de ramificación en la historia, y eso causa todo tipo de problemas debido a las combinaciones de fusión disponibles.
En cambio, he seguido un enfoque diferente, basado en el hecho de que ambas ramas comparten una gran cantidad de historia, exactamente toda la historia antes de la ramificación es 100% igual, por lo que en lugar de retroceder, mi propuesta es seguir adelante (desde el 1 commit), buscando la primera diferencia en ambas ramas. El punto de ramificación será, simplemente, el padre de la primera diferencia encontrada.
En la práctica:
Y está resolviendo todos mis casos habituales. Claro que hay bordes que no están cubiertos, pero ... ciao :-)
fuente
comm --nocheck-order -1 -2 <(git rev-list --reverse --topo-order topic) <(git rev-list --reverse --topo-order master) | head -1
Hace poco también necesitaba resolver este problema y terminé escribiendo un script de Ruby para esto: https://github.com/vaneyckt/git-find-branching-point
fuente
Después de mucha investigación y discusiones, está claro que no hay una bala mágica que funcione en todas las situaciones, al menos no en la versión actual de Git.
Es por eso que escribí un par de parches que agregan el concepto de una
tail
rama. Cada vez que se crea una rama, también se crea un puntero al punto original, latail
referencia. Esta referencia se actualiza cada vez que se vuelve a crear la rama.Para averiguar el punto de ramificación de la ramificación de desarrollo, todo lo que tiene que hacer es usar
devel@{tail}
, eso es todo.https://github.com/felipec/git/commits/fc/tail
fuente
Aquí hay una versión mejorada de mi respuesta anterior respuesta anterior . Se basa en los mensajes de confirmación de las fusiones para encontrar dónde se creó la rama por primera vez.
Funciona en todos los repositorios mencionados aquí, e incluso he abordado algunos complicados que se generaron en la lista de correo . También escribí pruebas para esto.
fuente
El siguiente comando revelará el SHA1 de Commit A
git merge-base --fork-point A
fuente
Parece que estoy disfrutando un poco con
La última línea que obtienes es la primera confirmación en la rama, por lo que se trata de obtener el padre de eso. Entonces
Parece funcionar para mí y no necesita diffs, etc. (lo cual es útil ya que no tenemos esa versión de diff)
Corrección: esto no funciona si está en la rama maestra, pero lo estoy haciendo en un script, así que eso no es un problema
fuente
Para encontrar confirmaciones desde el punto de ramificación, puede usar esto.
fuente
A veces es efectivamente imposible (con algunas excepciones de dónde podría tener la suerte de tener datos adicionales) y las soluciones aquí no funcionarán.
Git no conserva el historial de referencia (que incluye ramas). Solo almacena la posición actual de cada rama (la cabeza). Esto significa que puede perder parte del historial de sucursales en git con el tiempo. Cada vez que se bifurca, por ejemplo, se pierde de inmediato qué rama era la original. Todo lo que hace una rama es:
Puede suponer que el primero comprometido es la rama. Este suele ser el caso, pero no siempre es así. No hay nada que le impida comprometerse con cualquiera de las ramas primero después de la operación anterior. Además, no se garantiza que las marcas de tiempo de git sean confiables. No es hasta que te comprometes con ambos que realmente se convierten en ramas estructuralmente.
Mientras que en los diagramas tendemos a numerar los commits conceptualmente, git no tiene un concepto estable real de secuencia cuando el commit se ramifica. En este caso, puede suponer que los números (que indican el orden) están determinados por la marca de tiempo (puede ser divertido ver cómo una interfaz de usuario de git maneja las cosas cuando establece todas las marcas de tiempo en el mismo).
Esto es lo que un humano espera conceptualmente:
Esto es lo que realmente obtienes:
Asumirías que B1 es la rama original, pero podría ser simplemente una rama muerta (alguien realizó el pago -b pero nunca se comprometió). No es hasta que te comprometes con ambos que obtienes una estructura de rama legítima dentro de git:
Siempre sabe que C1 vino antes que C2 y C3, pero nunca sabe de manera confiable si C2 vino antes que C3 o C3 vino antes que C2 (porque puede configurar la hora en su estación de trabajo a cualquier cosa, por ejemplo). B1 y B2 también son engañosos ya que no puedes saber qué rama vino primero. Puede hacer una suposición muy buena y generalmente precisa en muchos casos. Es un poco como una pista de carreras. En general, en igualdad de condiciones con los autos, puede suponerse que un auto que viene en una vuelta atrás comenzó una vuelta atrás. También tenemos convenciones que son muy confiables, por ejemplo, master casi siempre representará las ramas más longevas, aunque lamentablemente he visto casos en los que incluso este no es el caso.
El ejemplo dado aquí es un ejemplo de preservación de la historia:
Real aquí también es engañoso porque nosotros, como humanos, lo leemos de izquierda a derecha, de raíz a hoja (ref). Git no hace eso. Donde hacemos (A-> B) en nuestras cabezas git hace (A <-B o B-> A). Lo lee de ref a root. Las referencias pueden estar en cualquier lugar, pero tienden a ser hojas, al menos para ramas activas. Una referencia apunta a un compromiso y los compromisos solo contienen un me gusta para sus padres, no para sus hijos. Cuando un commit es un commit de fusión, tendrá más de un padre. El primer padre es siempre el commit original en el que se fusionó. Los otros padres siempre son commits que se fusionaron en el commit original.
Esta no es una representación muy eficiente, sino una expresión de todos los caminos que git puede tomar de cada referencia (B1 y B2).
El almacenamiento interno de Git se parece más a esto (no es que A como padre aparezca dos veces):
Si vuelcas un commit de git sin procesar, verás cero o más campos principales. Si hay cero, significa que no hay padre y la confirmación es una raíz (en realidad puede tener múltiples raíces). Si hay uno, significa que no hubo fusión y no es una confirmación de raíz. Si hay más de uno, significa que el commit es el resultado de una fusión y todos los padres después del primero son commits de fusión.
Cuando ambos golpeen A, su cadena será la misma, antes de eso su cadena será completamente diferente. La primera confirmación que otras dos confirmaciones tienen en común es el antepasado común y de dónde divergieron. Puede haber alguna confusión aquí entre los términos commit, branch y ref. De hecho, puede fusionar un commit. Esto es lo que realmente hace la fusión. Una referencia simplemente apunta a una confirmación y una rama no es más que una referencia en la carpeta .git / refs / heads, la ubicación de la carpeta es lo que determina que una referencia es una rama en lugar de algo más como una etiqueta.
Donde pierde la historia es que la fusión hará una de dos cosas dependiendo de las circunstancias.
Considerar:
En este caso, una combinación en cualquier dirección creará un nuevo commit con el primer padre como el commit señalado por la rama desprotegida actual y el segundo padre como el commit en la punta de la rama que fusionó en su rama actual. Tiene que crear una nueva confirmación ya que ambas ramas tienen cambios desde su antepasado común que deben combinarse.
En este punto, D (B1) ahora tiene ambos conjuntos de cambios de ambas ramas (en sí y B2). Sin embargo, la segunda rama no tiene los cambios de B1. Si combina los cambios de B1 a B2 para que estén sincronizados, entonces puede esperar algo que se vea así (puede forzar git merge para que lo haga así sin embargo con --no-ff):
Obtendrá eso incluso si B1 tiene confirmaciones adicionales. Mientras no haya cambios en B2 que B1 no tenga, las dos ramas se fusionarán. Hace un avance rápido que es como un rebase (los rebases también comen o linealizan el historial), excepto que, a diferencia de un rebase, ya que solo una rama tiene un conjunto de cambios, no tiene que aplicar un conjunto de cambios de una rama encima de otra.
Si deja de trabajar en B1, las cosas están muy bien para preservar la historia a largo plazo. Solo B1 (que podría ser maestro) avanzará normalmente, por lo que la ubicación de B2 en el historial de B2 representa con éxito el punto en que se fusionó con B1. Esto es lo que git espera que hagas, para bifurcar B de A, luego puedes fusionar A en B tanto como quieras a medida que se acumulan los cambios, sin embargo, al fusionar B de nuevo en A, no se espera que trabajes en B y más . Si continúa trabajando en su sucursal después de avanzar rápidamente fusionándola nuevamente en la sucursal en la que estaba trabajando, borre el historial anterior de B cada vez. Realmente estás creando una nueva bifurcación cada vez después de un avance rápido, compromete a la fuente y luego confirma a la bifurcación.
1 a 3 y 5 a 8 son ramas estructurales que aparecen si sigue el historial de 4 o 9. No hay forma en git de saber a cuál de estas ramas estructurales sin nombre y sin referencia pertenecen las ramas con nombre y de referencia como Fin de la estructura. Puede suponer de este dibujo que 0 a 4 pertenece a B1 y 4 a 9 pertenece a B2, pero aparte de 4 y 9 no se sabe qué rama pertenece a qué rama, simplemente lo he dibujado de una manera que da ilusión de eso. 0 podría pertenecer a B2 y 5 podrían pertenecer a B1. Hay 16 posibilidades diferentes en este caso de qué rama nombrada podría pertenecer cada una de las ramas estructurales.
Hay una serie de estrategias git que funcionan alrededor de esto. Puede forzar git merge para que nunca avance rápido y siempre cree una rama de fusión. Una forma horrible de preservar el historial de sucursales es con etiquetas y / o ramas (se recomiendan realmente las etiquetas) de acuerdo con alguna convención de su elección. Realmente no recomendaría una confirmación vacía ficticia en la rama en la que se está fusionando. Una convención muy común es no fusionarse en una rama de integración hasta que realmente desee cerrar su rama. Esta es una práctica a la que las personas deberían intentar adherirse, ya que de lo contrario estás trabajando en el punto de tener sucursales. Sin embargo, en el mundo real, el ideal no siempre es práctico, lo que significa que hacer lo correcto no es viable para cada situación. Si lo que tu
fuente
man git-reflog
y la parte sobre las fechas: "master@{one.week.ago} significa" donde el maestro solía señalar hace una semana en este repositorio local "". O la discusión sobre<refname>@{<date>}
enman gitrevisions
. Ycore.reflogExpire
enman git-config
.No es una solución para la pregunta, pero pensé que valía la pena señalar el enfoque que uso cuando tengo una rama de larga vida:
Al mismo tiempo que creo la rama, también creo una etiqueta con el mismo nombre pero con un
-init
sufijo, por ejemplofeature-branch
yfeature-branch-init
.(¡Es un poco extraño que sea una pregunta tan difícil de responder!)
fuente
Una manera simple de hacer que sea más fácil ver el punto de ramificación
git log --graph
es usar la opción--first-parent
.Por ejemplo, tome el repositorio de la respuesta aceptada :
Ahora agregue
--first-parent
:¡Eso lo hace más fácil!
Tenga en cuenta que si el repositorio tiene muchas ramas, querrá especificar las 2 ramas que está comparando en lugar de usar
--all
:fuente
El problema parece ser encontrar el corte de compromiso único más reciente entre ambas ramas en un lado, y el antepasado común más antiguo en el otro (probablemente el compromiso inicial del repositorio). Esto coincide con mi intuición de cuál es el punto de "ramificación".
Eso en mente, esto no es nada fácil de calcular con los comandos normales de git shell, ya que
git rev-list
, nuestra herramienta más poderosa, no nos permite restringir la ruta por la cual se alcanza un commit. Lo más cercano que tenemos esgit rev-list --boundary
, lo que nos puede dar un conjunto de todos los commits que "bloquearon nuestro camino". (Nota:git rev-list --ancestry-path
es interesante, pero no sé cómo hacerlo útil aquí).Aquí está el script: https://gist.github.com/abortz/d464c88923c520b79e3d . Es relativamente simple, pero debido a un bucle es lo suficientemente complicado como para justificar una esencia.
Tenga en cuenta que la mayoría de las otras soluciones propuestas aquí no pueden funcionar en todas las situaciones por una simple razón:
git rev-list --first-parent
no es confiable en la linealización del historial porque puede haber fusiones con cualquier pedido.git rev-list --topo-order
, por otro lado, es muy útil, para realizar commits de caminata en orden topográfico, pero hacer diffs es frágil: existen múltiples posibles ordenamientos topográficos para un gráfico dado, por lo que dependerá de una cierta estabilidad de los ordenamientos. Dicho esto, la solución de strongk7 probablemente funciona muy bien la mayor parte del tiempo. Sin embargo, es más lento que el mío como resultado de tener que recorrer toda la historia del repositorio ... dos veces. :-)fuente
Lo siguiente implementa git equivalente de svn log --stop-on-copy y también se puede usar para encontrar el origen de la rama.
Acercarse
Como todos los ríos corren hacia el mar, todas las ramas corren para dominar y, por lo tanto, encontramos una base de fusión entre ramas aparentemente no relacionadas. A medida que retrocedemos desde la cabeza de la rama a través de los antepasados, podemos detenernos en la primera base de fusión potencial, ya que en teoría debería ser el punto de origen de esta rama.
Notas
detalles: https://stackoverflow.com/a/35353202/9950
fuente
Puede usar el siguiente comando para devolver la confirmación más antigua en branch_a, a la que no se puede acceder desde el maestro:
Tal vez con una comprobación de cordura adicional de que el padre de ese compromiso es realmente accesible desde el maestro ...
fuente
Puede examinar el registro de la rama A para encontrar desde qué confirmación se creó, así como el historial completo de las confirmaciones a las que apuntó esa rama. Los registros están en
.git/logs
.fuente
Creo que he encontrado una manera de lidiar con todos los casos de esquina mencionados aquí:
Charles Bailey tiene toda la razón en que las soluciones basadas en el orden de los antepasados tienen un valor limitado; al final del día, necesita algún tipo de registro de "esta confirmación vino de la rama X", pero dicho registro ya existe; de forma predeterminada, 'git merge' usaría un mensaje de confirmación como "Combinar rama 'branch_A' en maestro", esto le indica que todas las confirmaciones del segundo padre (commit ^ 2) provienen de 'branch_A' y se fusionaron con la primera padre (commit ^ 1), que es 'maestro'.
Armado con esta información, puede encontrar la primera combinación de 'branch_A' (que es cuando 'branch_A' realmente surgió), y encontrar la base de combinación, que sería el punto de ramificación :)
He intentado con los repositorios de Mark Booth y Charles Bailey y la solución funciona; como no pudo La única forma en que esto no funcionaría es si ha cambiado manualmente el mensaje de confirmación predeterminado para las fusiones, de modo que la información de la rama se pierda realmente.
Por utilidad:
Entonces puedes hacer '
git branch-point branch_A
'.Disfrutar;)
fuente
git merge -m
para decir lo que he fusionado en lugar del nombre de una rama potencialmente efímera (por ejemplo, "fusionar los cambios de la línea principal en la función xyz refactor"). ¿Y si hubiera sido menos útil con mi-m
en mi ejemplo? El problema simplemente no es soluble en su generalidad completa porque puedo hacer la misma historia con una o dos ramas temporales y no hay forma de notar la diferencia.