Cuando nos fusionamos guardamos la versión local de nuestros files Maven pom.xml:
git merge origin/remote_branch git checkout --ours **/pom.xml pom.xml git add **/pom.xml pom.xml git commit -m "Merge"
Esto funciona muy bien, excepto si se ha eliminado un file pom.xml en la sucursal local. Después de ejecutar el command n. ° 2 anterior, obtenemos un error:
d:\code>git checkout --ours **/pom.xml pom.xml error: path 'blah/pom.xml' does not have our version
… y después de este error, el siguiente command # 3 git add **/pom.xml pom.xml
agrega efectivamente los files remotos pom.xml, exactamente lo que no queremos.
¿Cómo podemos actualizar nuestro script para manejar esto?
Primero:
git merge origin/remote_branch
probablemente debería leer git merge --no-commit
para asegurarse de que Git no cometa estos cambios si no hay conflictos de fusión, de lo contrario, sus próximos pasos no tienen mucho sentido. Tenga en count que no habrá conflictos de fusión en absoluto si el --theirs
commit ha cambiado algunos files pom.xml
y no los ha modificado, o si Git piensa que fusionó con éxito sus cambios y los suyos. (Si quiere usar los suyos en uno de estos casos, eso también es un poco complicado, pero parece que quiere usar las versiones --ours
siempre.)
Siguiente:
git checkout --ours **/pom.xml pom.xml
Esto depende de tu caparazón (presumiblemente bash
o similar) para expandirse **
la manera que quieras; es posible que desee citar los asteriscos y hacer que Git realice la expansión global. Sin embargo, esto podría afectar tu caso particular, y no estoy seguro de cómo lo maneja Git durante un conflicto de fusión, así que antes de hacer algo como eso, querrás experimentar con cuidado.
Esto funciona muy bien, excepto si se ha eliminado un file pom.xml en la sucursal local. Después de ejecutar el command n. ° 2 anterior, obtenemos un error:
d:\code>git checkout --ours **/pom.xml pom.xml error: path 'blah/pom.xml' does not have our version
Derecha: en este caso, si desea mantener eliminado el file eliminado, debe anular la acción pnetworkingeterminada de Git de elegir mantener su versión en el índice y en el tree de trabajo.
Pasemos a la parte específica de Git de todo esto, el índice . Restring, el índice de Git es donde construyes el siguiente compromiso que harás. Durante una fusión, es también donde se resuelven los conflictos.
En los casos normales (sin fusiones), el índice tiene una input por cada file rastreado. Si el file F está en la confirmación actual (HEAD) y en el tree de trabajo, el índice tiene una input para F. Inicialmente, esta versión de input de índice coincide con la versión HEAD. Usted modifica el file en el tree de trabajo, luego git add
la versión del tree de trabajo para copyrlo en el índice en su lugar o en la versión HEAD; y luego el próximo git commit
saveá la versión del índice.
Durante una fusión en conflicto, donde el file F tiene un conflicto, el índice tiene hasta tres inputs para F en lugar de la habitual. Estas inputs van en los slots número 1, 2 y 3. (Slot zero está reservado para la input normal, no conflictiva). Slot 1 es para la versión base de combinación . El slot 2 es para --ours
, y el slot 3 es para --theirs
, y puedes usar estos nombres para 2 y 3, pero no hay un nombre para el slot 1.
Un conflicto de fusión ocurre cuando:
Para el conflicto modificar / modificar, las tres ranuras están ocupadas. Para los otros tres types de conflicto, una ranura está vacía: la ranura de la base de combinación está vacía (crear / crear), o --ours
está vacía (eliminar / X), o --theirs
está vacía (X / borrar).
El process de git checkout --ours
paso falla cuando el --ours
slot está vacío. Tiene éxito cuando el --ours
slot no está vacío: extrae la versión --ours
en el tree de trabajo.
La acción pnetworkingeterminada de Git en cualquier conflicto de eliminación / X o X / eliminar es dejar, en el tree de trabajo, la versión que haya sobrevivido. Es decir, si la ranura 3 (suyos) está vacía, el file del tree de trabajo coincide con la input de la ranura 2, pero si la ranura 2 (nuestra) está vacía, el file del tree de trabajo coincide con la input de la ranura 3.
Puede optar por manejar esto escaneando en busca de "ranura 2" vacías y git rm
el file para este caso:
git ls-files --stage | fancy-script-or-program
Si escribe esto como, por ejemplo, un progtwig de Python, use git ls-files -z --stage
para que sea fácilmente analizable por máquina. Incluso podría dejar de usar git checkout --ours
en absoluto, y dejar de depender de shell o Git globbing, y codificar las reglas para resolver files pom.xml
completo en el script.
Esencialmente, puede leer todo el índice, buscando files cuyo nombre base (todo después del final /
) coincida con pom.xml
:
Si hay una input de etapa cero, Git cree que resolvió el file correctamente. Compare la ID de hash con la de la confirmación HEAD
, porque es posible que Git no haya resuelto el file correctamente después de todo; en este caso, reemplace el hash de blobs de índice con el del commit de HEAD
. Consulte la documentation de git update-index
para más detalles. Debería poder usar --cacheinfo
, aunque no he probado esto con inputs de índice no fusionadas.
De lo contrario, hay inputs de etapa 1, 2 y / o 3. Si hay una input en la etapa 2, utilícela como resolución, es decir, proporciónela a git update-index
como se git update-index
anteriormente. Si no hay input en la etapa 2, use git update-index
para eliminar las inputs (usando 0
para el modo, y cualquier cosa, incluido el hash all-ceros, para el hash, el hash es irrelevante si el modo es 0).
Una vez que haya hecho esto con todas las routes de acceso pom.xml
, cualquier input de índice de etapa que no sea cero restante indica un conflicto de fusión que debe pasar de nuevo a su usuario. De lo contrario, puede estar listo para comprometerse.
(Un análisis rápido de http://gitpython.readthedocs.io/en/stable/reference.html#module-git.index.base sugiere que esto podría hacerse con bastante facilidad en GitPython, pero no tengo experiencia en su uso. )
Advertencia final: no tengo ninguna experiencia con Maven, pero entiendo que los files pom.xml
son files XML que controlan varias cosas y que Git se funde mal (el último es cierto para casi todos los files XML). Sin embargo, no tengo claro que el solo uso de la versión "nuestra" sea correcto.