Determine si el file binary cambió al resolver el conflicto git "ambos agregados"

Estoy realizando una rebase y encuentro conflictos "ambos agregados" para files binarys. Quiero aceptar 'nuestro' si los files binarys son iguales, 'ellos' si se cambian. Durante la resolución, ¿cómo puedo probar si los files binarys son iguales o diferentes?

No obtendrá un conflicto si los files coinciden.

Vamos a mostrar esto por ejemplo. Aunque está hablando de rebase (vs merge), los conflictos se manejan de la misma manera, ya que es el mismo código involucrado:

$ mkdir addadd; cd addadd; git init Initialized empty Git repository in /home/torek/tmp/addadd/.git/ $ echo a repository for testing add/add conflict > README $ git add README $ git commit -m initial [master (root-commit) f665e86] initial 1 file changed, 1 insertion(+) create mode 100644 README 

Ahora necesitamos algunos files binarys. Usaré /bin/ls y /bin/cat , y pondré binarys idénticos bajo un nombre en dos twigs, y versiones no idénticas bajo un nombre en dos twigs más:

 $ git checkout -b b1 master Switched to a new branch 'b1' $ cp /bin/ls some-file $ git add some-file && git commit -m 'add some-file on b1' [b1 5128ae4] add some-file on b1 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 some-file $ git checkout -b b2 master Switched to a new branch 'b2' $ cp /bin/ls some-file $ git add some-file && git commit -m 'add some-file on b2' [b2 0e7d771] add some-file on b2 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 some-file 

Ahora intentamos fusionar b1 en b2 o viceversa. Ya estamos en b2 así que vamos a fusionar b1 aquí:

 $ git merge --no-edit b1 Merge made by the 'recursive' strategy. $ git log --oneline --decorate --graph --all * 257e77a (HEAD -> b2) Merge branch 'b1' into b2 |\ | * 5128ae4 (b1) add some-file on b1 * | 0e7d771 add some-file on b2 |/ * f665e86 (master) initial 

Ahora intentemos lo mismo con diferentes binarys:

 $ git checkout -b b3 master Switched to a new branch 'b3' $ cp /bin/ls some-file $ git add some-file && git commit -m 'add some-file on b3' [b3 2ede434] add some-file on b3 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 some-file $ git checkout -b b4 master Switched to a new branch 'b4' $ cp /bin/cat some-file $ git add some-file && git commit -m 'add different some-file on b4' [b4 9e5f2cf] add different some-file on b4 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 some-file 

De nuevo, fusionaremos b3 en b4 aquí:

 $ git merge --no-edit b3 warning: Cannot merge binary files: some-file (HEAD vs. b3) Auto-merging some-file CONFLICT (add/add): Merge conflict in some-file Automatic merge failed; fix conflicts and then commit the result. $ git status --short AA some-file 

Esta vez, la combinación falló con un conflicto agregar / agregar. Eso significa que los files fueron diferentes: la fusión anterior tuvo éxito porque los files eran los mismos. La fusión no está completa pero aún podemos mirar el gráfico de confirmación:

 $ git log --oneline --decorate --graph --all * 9e5f2cf (HEAD -> b4) add different some-file on b4 | * 2ede434 (b3) add some-file on b3 |/ | * 257e77a (b2) Merge branch 'b1' into b2 | |\ | | * 5128ae4 (b1) add some-file on b1 | |/ |/| | * 0e7d771 add some-file on b2 |/ * f665e86 (master) initial 

Curiosamente, cuando los files son iguales, ni siquiera recibimos el post de advertencia. Esto se debe a que el mecanismo de fusión de Git omite todo el código de fusión habitual cuando los files coinciden. 1 En particular, los controlleres de combinación personalizados de files .gitattributes nunca se ejecutan.

Podemos ver que los files son diferentes (y que hubo un conflicto de agregar / agregar) al ejecutar git ls-files --stage :

 $ git ls-files --stage 100644 661d9d91972de27e4f787e3ad93ea3b7a1741ddf 0 README 100755 b75a044e06fb5e093a547c4ef9a388313d27f79a 2 some-file 100755 2ca93e76b4dedc9970cca9a708ab1cb94ca032ee 3 some-file 

Pathname some-file existe como etapas 2 y 3, pero no como etapa 1 (base). Esto significa que no hubo una versión base del file: por lo tanto, este es un conflicto de agregar / agregar. El hash para la etapa 2, --ours , es b75a044... , y el hash para la etapa 3 o --theirs es 2ca93e7... , que también podemos ver con git rev-parse :

 $ git rev-parse :2:some-file b75a044e06fb5e093a547c4ef9a388313d27f79a 

(repita para :3:some-file si lo desea).


1 Más precisamente, Git simplemente comtesting si el hash de la input del índice coincide con el hash en el otro o --theirs . Si es así, es por definición el mismo file y no se requiere ninguna acción de fusión.