¿Por qué una sucursal git compartida con dos committers tiene muchos commits dos veces? (posible interacción con git-svn)

Cuando configuré mi sucursal, lo hice:

git svn rebase git checkout -b branch-a 

Luego llevé esa twig al repository remoto de git y un colega y yo trabajamos en ella usando git commit , git pull y git push .

Ahora, quería sacar todos los nuevos cambios de la subversión, así que lo hice:

 git checkout master git svn rebase git checkout branch-a git rebase master 

En este punto estoy confundido. Lo que parecía suceder era que Git llegaría a cometer uno o más conflictos y me obligaría a resolverlos. Sin embargo, lo que parecía ser el conflicto era tener HEAD apuntando a la punta del tree (con el código más reciente) y luego intentar aplicar cada cambio uno por uno en la parte superior como si los estuviera aplicando al punto de ramificación original .

Sentí como si estuviera volviendo a escribir todo el código otra vez y la mayor parte de la resolución fue mantener el fragment HEAD y deshacerme del trozo de compromiso.

Mi expectativa era que el command git rebase master comenzaría en la confirmación antes de la twig, agregaría cada confirmación desde el maestro y luego agregaría cada confirmación en la twig. Esto arrojaría una propina en la twig casi idéntica a lo que era antes de la rebase.

Entonces, ¿alguien puede explicar lo que estoy fallando en entender? Si eso falla, ¿alguien puede sugerir cómo averiguar por qué git está decidiendo hacer eso? ¿Qué estaría buscando en un git log para ver por qué estaba haciendo eso?

Editar: 2012-03-06 Investigaciones adicionales han demostrado que parece que tenemos múltiples copys de un par de confirmaciones en nuestra twig y una estructura de sucursal, a partir de git log --graph que muestra múltiples twigs cuando pensamos que solo había una.

Un fragment (los detalles de identificación eliminados y los posts de confirmación han sido reemplazados por post- n . Mensaje- se refiere a posts idénticos):

 | * | commit f5c48df66ed9d733364562d8f125866aa6483c1e | | | Author: commiter-b | | | Date: Mon Feb 27 16:18:05 2012 -0800 | | | | | | Message-4 | | | | * | commit e6115229e629c237b08d0b2e149353f33ff66bd1 | | | Author: commiter-a | | | Date: Mon Feb 27 15:49:02 2012 -0800 | | | | | | Message-3 | | | | * | commit f85981736c59231dc34a7cef4fceab5cffdbdff2 | |/ Author: committer-a | | Date: Mon Feb 27 14:20:56 2012 -0800 | | | | Message-2 | | | * commit b09ba82e6290f5905d4c98fdcfbe2220d221e762 | Author: committer-a | Date: Mon Feb 27 14:04:13 2012 -0800 | | Message-1 | * commit 4d2892c239acfab5c9845518fde98ba551f273e6 | Author: committer-a | Date: Mon Mar 5 09:13:19 2012 -0800 | | UN-3710 Fixes after merge from svn ---8<----- snip * commit 8307d1ae8214ebe3eac5bdc5b835c21f89d727bd | Author: committer-b | Date: Mon Feb 27 16:18:05 2012 -0800 | | Message-4 | * commit 859acc56de59877cb721914443c63ad97882cb41 | Author: committer-a | Date: Mon Feb 27 15:49:02 2012 -0800 | | Message-3 | * commit 93e15921d735333194970cefc673a8b953e80838 | Author: committer-a | Date: Mon Feb 27 14:20:56 2012 -0800 | | Message-2 | * commit 7a863bb44be5c5019a0e0958460324dc3cfb2e6b Author: committer-a Date: Mon Feb 27 14:04:13 2012 -0800 Message-1 

Nuestro flujo de trabajo de git es conservador, creo. Usamos git-svn para mantener el master que se envía a un repository remoto de git. Nosotros ramificamos el master y dos o más committers trabajan en él usando git pull origin branch-a y git push origin .

Ahora que hemos notado esta característica del problema, estaremos observando cuidadosamente en el futuro para qué evento lo causa.

Primero, un resumen rápido de lo que hace la git rebase .

Si tienes un historial que se ve así:

 trunk branch | / BC | / |/ A | | 

Y tienes el git rebase trunk cuando estás en una branch , esto es lo que obtienes:

 trunk/branch | C | B | A | | 

Es por eso que se llama una rebase – la base de la branch era commit A – ese es el punto en el cual se separó de su twig "upstream", trunk . Después de la operación, la nueva base es B , la HEAD más nueva del trunk . Lo has vuelto a basar.

git svn rebase simplemente hace esto de forma automática, trasplantando los cambios que ha realizado en las nuevas confirmaciones provenientes de SVN.

Ahora, hay una gotcha. git-svn , para pasas histéricas, no usa notas git para almacenar sus metadatos. En su lugar, reescribe los objects de compromiso, agregando líneas de git-svn-id al final de cada post de confirmación. Esto hace que los identificadores SHA1 de cada compromiso cambien. Por lo tanto, incluso los commits idénticos son diferentes, ¡y pueden entrar en conflicto con versiones de sí mismo de un universo alternativo!

Esto es probablemente lo que está viendo cuando intenta git rebase master de la branch-a : branch-a versión divergente de alguna no comprometida-a-SVN de un estado master , por lo que ahora cuando intenta fusionarse, Tendremos conflictos entre las cosas cambiadas en ambos lados.

Esta es una limitación de git-svn : una vez que inserta un cambio en SVN, debe tener cuidado de usar solo la versión reescrita de la confirmación enviada a SVN . No puede mezclar los formularios precomprometidos y postcomprometidos, ya que son cambios "diferentes" con los mismos contenidos.

Puede verificar que esto es lo que está intentando hacer al examinar los cambios desde git merge-base master branch-a a master y branch-a . Es probable que vea el mismo cambio en ambos lados.

Para salir de la rutina en este caso particular, elimine su twig, cree una nueva desde el master , luego git cherry-pick los cambios de la branch-a en order, omitiendo los que el master ya contiene. En el futuro, tenga más cuidado al usar las revisiones aún no incluidas en SVN …