¿Cómo se fusiona git después del trabajo de selección?

Resuelto Paul asked hace 11 años • 2 respuestas

Imaginemos que tenemos una mastersucursal.

Luego creamos unnewbranch

git checkout -b newbranch

y haga dos nuevos compromisos para newbranch: compromiso1 y compromiso2

Luego cambiamos a master y hacemoscherry-pick

git checkout master
git cherry-pick hash_of_commit1

Al analizarlo, gitkvemos que commit1 y su versión seleccionada tienen hashes diferentes, por lo que técnicamente son dos commits diferentes.

Finalmente nos fusionamos newbranchen master:

git merge newbranch

y ver que estos dos commits con diferentes hashes se fusionaron sin problemas aunque implican que se deben aplicar dos veces los mismos cambios, por lo que uno de ellos debería fallar.

¿Git realmente hace un análisis inteligente del contenido de las confirmaciones mientras las fusiona y decide que los cambios no deben aplicarse dos veces o que estas confirmaciones se marcan internamente como vinculadas entre sí?

Paul avatar Jan 24 '13 00:01 Paul
Aceptado

Respuesta corta

No te preocupes, Git se encargará.

Respuesta larga

A diferencia de, por ejemplo, SVN 1 , Git no almacena confirmaciones en formato delta, sino que se basa en instantáneas 2,3 . Si bien SVN intentaría ingenuamente aplicar cada confirmación fusionada como un parche (y fallaría, por la razón exacta que usted describió), Git generalmente es capaz de manejar este escenario.

Al fusionarse, Git intentará combinar las instantáneas de ambas confirmaciones HEAD en una nueva instantánea. Si una parte del código o un archivo es idéntico en ambas instantáneas (es decir, porque ya se seleccionó una confirmación), Git no lo tocará.

Fuentes

1 Skip-Deltas en Subversion
2 Conceptos básicos de Git
3 El modelo de objetos de Git

helmbert avatar Jan 23 '2013 18:01 helmbert

Después de dicha fusión, es posible que haya seleccionado confirmaciones en el historial dos veces.

Solución para evitar esto, cito un artículo que recomienda que las ramas con confirmaciones duplicadas (seleccionadas) usen rebase antes de fusionar:

git merge después de git cherry-pick: evitar confirmaciones duplicadas

Imaginemos que tenemos la rama master y una rama b:

   o---X   <-- master
    \
     b1---b2---b3---b4   <-- b

Ahora necesitamos urgentemente las confirmaciones b1 y b3 en master, pero no las confirmaciones restantes en b. Entonces, lo que hacemos es verificar la rama maestra y seleccionar las confirmaciones b1 y b3:

$ git checkout master
$ git cherry-pick "b1's SHA"
$ git cherry-pick "b3's SHA"

El resultado sería:

   o---X---b1'---b3'   <-- master
    \
     b1---b2---b3---b4   <-- b

Digamos que hacemos otra confirmación en master y obtenemos:

   o---X---b1'---b3'---Y   <-- master
    \
     b1---b2---b3---b4   <-- b

Si ahora fusionáramos la rama b con la maestra:

$ git merge b

Obtendríamos lo siguiente:

   o---X---b1'---b3'---Y--- M  <-- master
     \                     /
      b1----b2----b3----b4   <-- b

Eso significa que los cambios introducidos por b1 y b3 aparecerían dos veces en la historia. Para evitar eso, podemos rebase en lugar de fusionar:

$ git rebase master b

Lo que daría como resultado:

   o---X---b1'---b3'---Y   <-- master
                        \
                         b2'---b4'   <-- b

Finalmente:

$ git checkout master
$ git merge b

Nos da:

   o---X---b1'---b3'---Y---b2'---b4'   <-- master, b

EDITAR Correcciones supuestas por el comentario de David Lemon

ephemerr avatar Jul 07 '2017 08:07 ephemerr