Git se fusiona eliminando files

Es la segunda vez que sucede esto, cuando realizo una fusión, más tarde me di count de que algunos files que se encontraban en la twig fusionada ya no están fusionados en la twig.

El último ejemplo es que tenemos una twig de características en la que he estado fusionando los cambios desde la twig de desarrollo principal, hemos perdido muchos files después de una fusión y ahora no están presentes en la twig de características.

  1. ¿Por qué pasó esto?
  2. ¿Cuál es la mejor manera de get estos files? Estoy pensando en agregarlos manualmente.

aquí hay una descripción del repository cuando se perdieron los files:

964495c es donde se perdieron los files, es una fusión de la twig remota con una twig local. d1c457a es una combinación de la twig de desarrollo principal en la twig de características.

Cuando hago un diff de estas dos twigs, veo los files que he perdido como eliminados, pero nunca fueron configurados para eliminar. Esta no fue mi combinación, así que no estoy seguro de si fue un error del usuario, pero necesito encontrar la mejor manera de include estos files en mi twig de características …

enter image description here

Una respuesta a la parte 1

No tengo suficiente información aquí para decirte lo que sucedió … pero aquí está cómo ver qué debería suceder (o ha sucedido), en una git merge ... Podemos ver en la image de arriba que 964495c es una fusión y uno si su padre se compromete es d1c457a (el punto amarillo y la línea). No podemos ver el compromiso de su otro padre: el otro padre está en el otro extremo de la línea violeta. (Una línea es, imagino, una twig de desarrollo y la otra es una feature twig).

[ Editar : por comentario, el primer padre es 29a7b67 (en la feature twig), y el segundo es d1c457a (en el desarrollo de la twig como se esperaba).]

Lo primero que hace git merge es encontrar la "base de fusión". Por lo tanto, en una window de commands de shell, encuentre los dos ID principales:

 $ git rev-parse 964495c^1 29a7b67... $ git rev-parse 964495c^2 d1c457a... 

(En parte, estoy adivinando aquí, en base a los colors, que d1c457a es el segundo padre, es decir, que la cosa está fusionada, en lugar de fusionarse, no es que importe demasiado, el resultado de la fusión debería ser el lo mismo de cualquier manera). [ Editar : confirmado]

Ahora, usando los dos identificadores de compromiso producidos anteriormente, busca la base de combinación. Por simplicidad, asumiré que el primer command produjo 1234567... Por comentario, esto es 8967ae7...

 $ git merge-base 29a7b67 d1c457a 8967ae7... 

Ahora tiene tres ID de compromiso. Vamos a volver a hacer lo anterior con las variables del intérprete de órdenes, para no tener que adivinar las identificaciones de los commits más ya que los nombres simbólicos podrían ayudar:

 $ id_into=$(git rev-parse 964495c^1) $ id_from=$(git rev-parse 964495c^2) $ id_base=$(git merge-base $id_into $id_from) 

Ahora las variables de shell $id_base , $id_from y $id_into contienen el ID de confirmación de la combinación-base, la punta de la twig fusionada-from, 1 y el ID de la confirmación justo antes del 964495c mismo (la sugerencia original de la twig cuando la fusión se estaba haciendo).

Utilizándolos, podemos ver qué git merge se necesita fusionar, haciendo dos git diff . (El siguiente bit asume la networkingirección de shell de Unix / Linux / Mac.)

 $ git diff -M50% $id_base $id_into > /tmp/existing_changes $ git diff -M50% $id_base $id_from > /tmp/new_changes 

El primer diff se entera de "lo que ha sucedido en esta twig, es decir, feature , ya que el otro desarrollador de twig divergió de ella". El segundo diff se entera de "lo que ha sucedido en el otro desarrollador de twigs, ya que divergió de esta twig, es decir, feature ".

El command de merge luego intenta combinar estos dos. Dondequiera que dev tenga algún cambio:

  • si el cambio consiste en agregar un nuevo file, agregue el nuevo file (a less que la feature también lo haya agregado: entonces probablemente tengamos un conflicto que requiera una resolución manual)
  • si el cambio es cambiar el nombre de un file, cambie el nombre del file (de nuevo a less que la feature ya lo tenga)
  • si el cambio consiste en eliminar un file, elimine el file
  • si el cambio consiste en agregar o eliminar algunas líneas de un file, hágalo aquí (a less que la feature ya lo tenga, en cuyo caso, ignore el cambio, o si no podemos encontrar esas líneas exactas con los mismos contenidos, entonces tenemos un conflicto: este caso de conflicto incluye el caso en que el file fue eliminado en la feature ).

He marcado el caso donde git merge debería eliminar un file. Si la twig merge-from ( dev ) eliminó ese file desde la base de git merge , git merge eliminará silenciosamente el file del resultado de la fusión.


Ahora, con todo lo dicho, si quien realiza la fusión usa --no-commit , o si hay un conflicto, la fusión se detiene después de hacer todo lo que puede, y quien está haciendo la fusión tiene la posibilidad de hacer cambios adicionales . En el caso de conflictos de fusión, esto es, por supuesto, donde la persona que hace la fusión debe resolver los conflictos. Sin embargo, la persona que realiza la fusión puede usar --no-commit para llegar aquí incluso sin conflictos. En cualquier caso, en este punto, la persona que realiza la fusión puede eliminar files, agregar files y modificar files. Cuando él o ella (bueno, usemos "ellos" :-)) … cuando 964495c... , ellos git commit el resultado, y eso hizo que se cometiera 964495c...


1 Al less, es lo que era la punta del desarrollador en ese momento: el desarrollador puede haber crecido un poco desde entonces, al igual que la feature ha crecido desde entonces.

Una respuesta a la parte 2

No es necesariamente la mejor forma de recuperar los files que faltan, pero es fácil verificar los files de una confirmación en particular. Aquí el más obvio de usar es 29a7b67 (también conocido como $id_from anterior, la punta de la feature cuando quien hizo la fusión, hizo la combinación):

 $ git checkout 29a7b67 -- path/to/file 

(Enumere los files múltiples, o uno o más directorys, para get más files, o cada file en el directory, de esa identificación de compromiso.) Esto coloca los files en el tree de trabajo y el índice, a partir del estado en que se encontraban. en ese commit-ID, para que el próximo git commit los incluya en ese estado.

(Por supuesto, puede editarlos y git add el resultado para git add si es necesario).