Saltar al contenido

¿Hay alguna diferencia entre git rebase y git merge –ff-only

Nuestro equipo de redactores ha estado largas horas investigando la respuesta a tu pregunta, te brindamos la solución así que nuestro objetivo es servirte de gran apoyo.

Solución:

Tenga en cuenta que git rebase tiene un diferente trabajo que git merge (con o sin --ff-only). Qué rebase hace es tomar confirmaciones existentes y Copiar ellos. Suponga, por ejemplo, que está en branch1 y he hecho dos confirmaciones A y B:

...-o--o--A--B   <-- HEAD=branch1
        
         o--C    <-- branch2

y decides que prefieres que esas dos confirmaciones estén en branch2 en lugar de. Usted puede:

  • obtener una lista de los cambios que realizó en A (diff A contra su padre)
  • obtener una lista de los cambios que realizó en B (diff B contra A)
  • cambiar a branch2
  • haz los mismos cambios que hiciste en A y cometerlos, copiando tu mensaje de compromiso de A; vamos a llamar a este compromiso A'
  • y luego haz los mismos cambios que hiciste en B y cometerlos, copiando tu mensaje de compromiso de B; vamos a llamar a esto B'.

Hay un comando git que hace este diff-and-then-copy-and-commit por ti: git cherry-pick. Entonces:

git checkout branch2      # switch HEAD to branch2 (commit C)
git cherry-pick branch1^  # this copies A to A'
git cherry-pick branch1   # and this copies B to B'

Ahora tienes esto:

...-o--o--A--B         <-- branch1
        
         o--C--A'-B'   <-- HEAD=branch2

Ahora puedes volver a branch1 y borra tu original A y B, utilizando git reset (Usaré --hard aquí, es más conveniente de esa manera, ya que también limpia el árbol de trabajo):

git checkout branch1
git reset --hard HEAD~2

Esto quita el original A y B,1 así que ahora tienes:

...-o--o               <-- HEAD=branch1
        
         o--C--A'-B'   <-- branch2

Ahora solo necesita volver a realizar el check-out branch2 para seguir trabajando allí.

Esto es lo que git rebase hace: "mueve" las confirmaciones (aunque no moviéndolas realmente, porque no puede: en git, una confirmación nunca se puede cambiar, por lo que incluso cambiar el ID de padre requiere copiarlo a una confirmación nueva y ligeramente diferente).

En otras palabras, mientras git cherry-pick es un diff-and-redo automatizado de uno cometer, git rebase es un proceso automatizado de rehacer múltiple confirma, además, al final, mover las etiquetas para "olvidar" u ocultar los originales.

Lo anterior ilustra el traslado de confirmaciones desde una rama local. branch1 a otra sucursal local branch2, pero git usa el exactamente el mismo proceso mover confirmaciones cuando tienes una rama de seguimiento remoto que adquiere algunas confirmaciones nuevas cuando haces una git fetch (incluyendo el fetch ese es el primer paso de git pull). Puede comenzar trabajando en la rama feature, que tiene un flujo ascendente de origin/featurey haz un par de confirmaciones por tu cuenta:

...-o        <-- origin/feature
     
      A--B   <-- HEAD=feature

Pero luego decides que deberías ver lo que ha sucedido río arriba, así que corres git fetch,2 y, ajá, alguien río arriba escribió un compromiso C:

...-o--C     <-- origin/feature
     
      A--B   <-- HEAD=feature

En este punto, simplemente puede reajustar su feature's A y B sobre C, donación:

...-o--C     <-- origin/feature
        
         A'-B'  <-- HEAD=feature

Estas son copias de su original. A y B, y los originales se desechan (pero consulte la nota 1 al pie de página) una vez que las copias están completas.


A veces no hay nada que reajustar, es decir, ningún trabajo que usted mismo hizo. Es decir, el gráfico antes del fetch se parece a esto:

...-o      <-- origin/feature
           `-- HEAD=feature

Si tu entonces git fetch y comprometerse C entra, sin embargo, te quedas con tufeature rama apuntando a la confirmación anterior, mientras que origin/feature ha avanzado:

...-o--C   <-- origin/feature
     `---- <-- HEAD=feature

Aquí es donde git merge --ff-only entra: si solicita fusionar su rama actual feature con origin/feature, git ve que es posible simplemente deslizar la flecha hacia adelante, por así decirlo, para que feature apunta directamente a comprometerse C. No se requiere una fusión real.

Si tuvieras tus propias confirmaciones A y B, sin embargo, y solicitó fusionarlos con C, git haría una fusión real, haciendo un nuevo compromiso de fusión M:

...-o--C        <-- origin/feature
        `-_
      A--B--M   <-- feature

Aquí, --ff-only se detendrá y le dará un error. Rebase, por otro lado, puede copiar A y B para A' y B' y luego esconde el original A y B.

Entonces, en resumen (ok, demasiado tarde :-)), simplemente hacen cosas diferentes. A veces, el resultado es el mismo y otras no. Si está bien copiar A y B, puedes usar git rebase; pero si hay alguna buena razón no para copiarlos, puedes usar git merge, tal vez con --ff-only, para fusionar o fallar según corresponda.


1De hecho, Git conserva los originales durante algún tiempo, normalmente un mes en este caso, pero los oculta. La forma más fácil de encontrarlos es con los "reflogs" de git, que mantienen un historial de dónde apunta cada rama y dónde HEAD apuntado, antes de cada cambio que actualizara la sucursal y / o HEAD.

Eventualmente, las entradas del historial de reflog caducan, momento en el que estas confirmaciones se vuelven elegibles para la recolección de basura.

2O, nuevamente, puede usar git pull, que es un script de conveniencia que comienza ejecutando git fetch. Una vez que se realiza la búsqueda, el script de conveniencia se ejecuta git merge o git rebase, dependiendo de cómo lo configure y ejecute.

Sí, hay una diferencia. git merge --ff-only abortará si no puede avanzar rápidamente, y requiere una confirmación (normalmente una rama) para fusionarse. Solo creará una confirmación de fusión si no puede avanzar rápidamente (es decir, nunca lo hará con --ff-only).

git rebase reescribe el historial en la rama actual, o se puede utilizar para volver a establecer la base de una rama existente en una rama existente. En ese caso, no creará una confirmación de fusión porque está reajustando, en lugar de fusionarse.

Sí, --ff-only siempre fallará donde un llano git merge fallaría, y podría fallar donde un llano git merge tendría éxito. Ese es el punto: si está tratando de mantener un historial lineal, y la fusión no se puede hacer de esa manera, querer que falle.

Una opción que agrega casos de falla a un comando no es inútil; es una forma de validar una condición previa, por lo que si el estado actual del sistema no es el esperado, no empeora el problema.

valoraciones y reseñas

Puedes secundar nuestro cometido fijando un comentario y puntuándolo te damos la bienvenida.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *