Desde el tiempo que git cherry-pick
aprendí para poder aplicar múltiples confirmaciones, la distinción se volvió algo discutible, pero esto es algo que se puede llamar evolución convergente ;-)
La verdadera distinción radica en la intención original de crear ambas herramientas:
git rebase
La tarea es reenviar una serie de cambios que un desarrollador tiene en su repositorio privado, creado contra la versión X de alguna rama ascendente, a la versión Y de esa misma rama (Y> X). Esto cambia efectivamente la base de esa serie de confirmaciones, por lo tanto, "rebase".
(También permite al desarrollador trasplantar una serie de confirmaciones a cualquier confirmación arbitraria, pero esto tiene un uso menos obvio).
git cherry-pick
es para llevar un compromiso interesante de una línea de desarrollo a otra. Un ejemplo clásico es el backporting de una corrección de seguridad realizada en una rama de desarrollo inestable a una rama estable (mantenimiento), donde merge
no tiene sentido, ya que traería muchos cambios no deseados.
Desde su primera aparición, git cherry-pick
ha podido elegir varias confirmaciones a la vez, una por una.
Por lo tanto, posiblemente la diferencia más llamativa entre estos dos comandos es cómo tratan la rama en la que trabajan: git cherry-pick
generalmente trae una confirmación de otro lugar y la aplica en la parte superior de su rama actual, registrando una nueva confirmación, mientras git rebase
toma su rama actual y reescribe una serie de su propia sugerencia se compromete de una forma u otra. Sí, esta es una descripción muy simplificada de lo que se git rebase
puede hacer, pero es intencional, para tratar de asimilar la idea general.
Actualice para explicar mejor un ejemplo de uso que se git rebase
está discutiendo.
Ante esta situación,
The Book afirma:
Sin embargo, hay otra forma: puede tomar el parche del cambio que se introdujo en C3 y volver a aplicarlo sobre C4. En Git, esto se llama rebase. Con el comando rebase, puede tomar todos los cambios que se confirmaron en una rama y aplicarlos en otra.
En este ejemplo, ejecutaría lo siguiente:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
El "problema" aquí es que, en este ejemplo, la rama "experimento" (el tema de la reorganización) se bifurcó originalmente de la rama "maestra" y, por lo tanto, comparte las confirmaciones C0 a C2 con ella; de hecho, "experimento" es " master "hasta, e incluido, C2 más el compromiso C3 encima. (Este es el caso más simple posible; por supuesto, "experimento" podría contener varias docenas de confirmaciones además de su base original).
Ahora git rebase
se le dice que vuelva a basar "experimento" en la punta actual de "maestro", y git rebase
dice así:
- Se ejecuta
git merge-base
para ver cuál es la última confirmación compartida por el "experimento" y el "maestro" (en otras palabras, cuál es el punto de desviación). Este es C2.
- Guarda todas las confirmaciones realizadas desde el punto de desvío; en nuestro ejemplo de juguete, es solo C3.
- Rebobina HEAD (que apunta a la confirmación de punta de "experimento" antes de que la operación comience a ejecutarse) para apuntar a la punta de "maestro"; estamos reajustando sobre ella.
- Intenta aplicar cada una de las confirmaciones guardadas (como si fuera con
git apply
) en orden. En nuestro ejemplo de juguete es solo una confirmación, C3. Digamos que su aplicación producirá un commit C3 '.
- Si todo salió bien, la referencia del "experimento" se actualiza para señalar la confirmación resultante de aplicar la última confirmación guardada (C3 'en nuestro caso).
Ahora volvamos a tu pregunta. Como puede ver, aquí técnicamente de git rebase
hecho trasplanta una serie de confirmaciones de "experimento" a la punta de "maestro", por lo que puede decir con razón que hay "otra rama" en el proceso. Pero la esencia es que la confirmación de sugerencias de "experimento" terminó siendo la nueva confirmación de sugerencias en "experimento", simplemente cambió su base:
Una vez más, técnicamente se puede decir que git rebase
aquí se incorporaron ciertas confirmaciones del "maestro", y esto es absolutamente correcto.