Git: ¿Archivos eliminados se interponen en el path de la fusión?

Tengo un conflicto de fusión que no estoy seguro de cómo manejar, aquí está el escenario.

Tengo Alpha y Gamma .

Alpha se ve así porque se eliminó Thing.js

Folder |___Thing.html |___Thing.css 

Y beta se ve así

Gamma se ve así porque Thing.html y Thing.css fueron eliminados

 Folder |___Thing.js 

Imagino que fusionarlos en Gamma me daría esto:

 Folder |___Thing.html |___Thing.css |___Thing.js 

En su lugar, parece eliminar Thing.js y actualizar Thing.html y Thing.css.

He estado buscando en Google durante media hora tratando de get una razón concisa de por qué sucede esto y cómo solucionarlo y estoy llegando al vacío. ¿Alguien ha tenido una experiencia similar y, de ser así, cómo la corrigió? ¿Y por qué sucede?

Creo que estás imaginando eso:

 git merge blah 

mira blah en comparación con HEAD / la twig actual.

No es así

Lo que hace git merge , al less para los casos normales de fusiones, es encontrar la base de combinación entre la twig actual, es decir, HEAD , y la confirmación especificada por blah :

  C--D--E <-- curbranch (HEAD) / ...--o--o--B \ F--G--H--I <-- blah 

La base de fusión es, más o less, donde las dos twigs se unen a medida que avanzamos en la historia.

Cada una de las letras mayúsculas anteriores representa una confirmación (una cosa con una gran ID de hash fea, que guarda una instantánea de origen). Git ahora lo hace, en efecto:

 git diff --find-renames BE # what we did git diff --find-renames BI # what they did 

Estos son cambios (o sets de cambios). El primero muestra lo que hicimos, comenzando por el compromiso B que compartimos con ellos, omitiendo todos los pasos intermedios, para ver cómo se ve al final.

El segundo muestra lo que hicieron, comenzando desde el mismo punto de partida. Al igual que con nuestra sucursal, Git omite todas las confirmaciones intermedias; solo el resultado final es "interesante".

Git luego combina los dos sets de cambios. Si eliminamos dos files y ellos eliminaron uno de esos dos files más un tercer file, el resultado combinado es "eliminar los tres files".

Si no quiere que los files se eliminen después de todo, puede ejecutar:

 git merge --no-commit 

para evitar comprometer el resultado final. A continuación, puede get los files específicos de la confirmación B (deberá ubicarlo usted mismo para este caso particular):

 git checkout <hash-of-B> <path> 

y cuando tienes la fuente orderada de la manera que quieres que se vea el resultado de la fusión, ejecuta la git commit . Sin embargo, ten cuidado: esto crea lo que las personas llaman una fusión malvada . Es decir, es un resultado de fusión que no es lo mismo que las inputs a la combinación.

Otra alternativa es crear al less un nuevo compromiso (agregado a curbranch o blah , o incluso en una nueva sucursal) que devuelva los files que se deben volver a colocar, en preparación para la fusión. Si ambas sugerencias de twigs han eliminado un file que debe conservarse, deberá hacer esto con ambas twigs (o dos twigs nuevas).

Ahora puede fusionar la nueva confirmación con la otra confirmación o la otra nueva fusión, usando la misma combinación B Ahora las dos inputs no eliminan el file, por lo que el resultado de la fusión tendrá el file.

Un truco es hacer la fusión de cómo llegar a la parte superior de la twig. Luego obtenga los files que desea de una confirmación previa. Copie / modifique / elimine los files para get la situación que le gustaría tener (agregue si es necesario) y vuelva a cometer.

¿Por qué es el comportamiento tal como es?

El file .js se eliminó en Alpha y no se modificó en una confirmación posterior, por lo que debería eliminarse. Los otros dos files fueron eliminados en beta. Usted escribió, ¿eran actualizaciones en gamma? Supongo que una modificación paralela a la beta resulta en un conflicto de fusión (¿tal vez una nueva línea en alfa?). Debido a dos modificaciones paralelas e incompatibles.

Supongo que imaginas que gamma se vería de cierta manera, porque piensas en una fusión como combinación de contenido. Esto no es verdad, sin embargo. Una fusión combina cambios.

Eliminar un file es un cambio. En una sucursal, si elimina un file y confirma ese cambio, está diciendo "git" para implementar la característica para la cual se creó esta sucursal, necesito eliminar este file ". Casi siempre es el caso que el "otro lado" en el que se fusionará esto tampoco borró el file; por lo tanto, para que su caso se maneje de la manera en que lo visualiza, significaría que casi todos los bashs de eliminar un file se desharían en la siguiente fusión. La mayoría de los usuarios encontrarían eso bastante molesto.

Entonces, en lugar de eso, haces la fusión y git dice "bueno, de este lado para hacer el trabajo. Tenía que borrarse. Js tenía que ser eliminado, pero de este lado para hacer el trabajo, tenía que modificarse. Tenía que modificarse. No voy a hacerlo. para adivinar cómo resolver eso, por lo que el usuario que realiza la fusión debe decirme ". Eso es un conflicto

Cada vez veo más flujos de trabajo donde las personas quieren crear una twig y luego eliminar de esa twig todos los files en los que no planean trabajar en esa twig. Lo anterior es por qué esos flujos de trabajo son 100% incorrectos. Si debe tener treees de trabajo dispersos, puede usar el pago escaso; pero si confirma la eliminación de los files, obtendrá resultados no deseados en la fusión.

En el caso en que el "otro lado" de la fusión modificó el file, tiene mucha suerte porque tendrá un conflicto y puede resolver el conflicto tomando la versión de la sucursal que no eliminó el file. Si no hubiera conflicto, el file se eliminará de forma silenciosa.