git merge-file falla con el operador de sustitución de processs bash que usa git show

Estoy intentando fusionar los cambios de un file que está en git en uno que no está bajo control de versión ( más context ) usando una combinación de 3 vías.

Como hay un git merge-file <local> <base> <other> que espera 3 files y como no me gusta crear files intermedios y olvidarme de limpiarlos, utilicé la sustitución de processs bash <(...) operador como hago bastante a menudo.

Resulta que esto no parece funcionar como se espera, como muestra el siguiente ejemplo en git 2.4.2 y 2.4.3 en dos sistemas diferentes.

Ejemplo:

Vamos a crear una pequeña testing para que sepamos de lo que estamos hablando. Crearemos un file foo.txt (el que está en git con al less 2 versiones) y un file bar.txt que no está bajo control de versión:

 git init echo -e 'foo\nbar' > foo.txt git add foo.txt git commit -m'init' echo -e 'foo\nbar\nend' > foo.txt git commit -a -m'end' echo -e 'start\nfoo\nbar' > bar.txt git show HEAD^:foo.txt > foo.txt.base git show master:foo.txt > foo.txt.end 

Esto nos deja con un par de files que se ven así:

foo.txt @ HEAD ^ y foo.txt.base:

 foo bar 

foo.txt @ master y foo.txt.end:

 foo bar end 

bar.txt:

 start foo bar 

Con files intermedios:

Así que ahora git merge-file -p bar.txt foo.txt.base foo.txt.end :

 start foo bar end 

Este es el resultado que me gustaría get con el siguiente método también.

Con la sustitución del process:

Pero si ejecuto: git merge-file -p bar.txt <(git show HEAD^:foo.txt) <(git show master:foo.txt) , obtengo esta salida:

 start foo bar 

Esto no se espera y (¡a veces!) echo $? imprime 1 indicando un error.

Lo que es aún más extraño es que como no podía entender este comportamiento, decidí volver a ejecutar el command anterior (flecha arriba) y me quedé aún más perplejo cuando apareció esta salida:

 <<<<<<< bar.txt start foo bar ======= foo bar end >>>>>>> /dev/fd/62 

Como realmente no esperaba que esto fallara, y mucho less para ser no determinista, volví a correr un par de veces para encontrar esta salida también:

 <<<<<<< bar.txt start foo bar ======= >>>>>>> /dev/fd/62 

Para networkingucir el problema, intenté git merge-file -p bar.txt <(echo -e 'foo\nbar') <(echo -e 'foo\nbar\nend') que imprime de manera confiable la combinación esperada:

 start foo bar end 

Pregunta

¿Alguien puede explicar este extraño comportamiento?

Obviamente, puedo solucionarlo sin utilizar la sustitución de processs, pero me gustaría entender por qué sucede esto, ya que estoy usando la sustitución de processs en muchos scripts bash. También estaría interesado en soluciones alternativas que me permitan seguir utilizando la sustitución de processs.

Además, si crees que es un error, me interesa saber de qué componente proviene: git show , git merge-file o bash?

Como se señaló en los comentarios y aquí podría ser un problema con <(...) proporcionar un file FIFO like que no admite seek . El mismo comportamiento se muestra en ZSH a less que se invoque así:

 git merge-file -p bar.txt =(git show HEAD^:foo.txt) =(git show master:foo.txt) 

Esto significa que el problema se origina en git merge-file esperando files que puede seek , mientras que <(...) no los proporciona.