in

Mueva las confirmaciones más recientes a una nueva rama con Git

apple touch icon@2

¡La mayoría de las respuestas anteriores están peligrosamente equivocadas!

No hagas esto:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch

Como la próxima vez que corras git rebase (o git pull --rebase) esas 3 confirmaciones se descartarían silenciosamente de newbranch! (ver explicación a continuación)

En su lugar, haz esto:

git reset --keep HEAD~3
git checkout -t -b newbranch
git cherry-pick ..HEAD@{2}
  • Primero descarta las 3 confirmaciones más recientes (--keep es como --hard, pero más seguro, ya que falla en lugar de tirar los cambios no comprometidos).
  • Entonces se bifurca newbranch.
  • Luego selecciona esos 3 compromisos de nuevo en newbranch. Como ya no se hace referencia a ellos por una rama, lo hace usando git’s volver a iniciar sesión: HEAD@{2} es el compromiso que HEAD solía referirse a 2 operaciones atrás, es decir, antes de 1. verificamos newbranch y 2. usado git reset para descartar las 3 confirmaciones.

Advertencia: el reflog está habilitado de forma predeterminada, pero si lo ha deshabilitado manualmente (por ejemplo, usando un repositorio de git «desnudo»), no podrá recuperar las 3 confirmaciones después de ejecutar git reset --keep HEAD~3.

Una alternativa que no depende del reflog es:

# newbranch will omit the 3 most recent commits.
git checkout -b newbranch HEAD~3
git branch --set-upstream-to=oldbranch
# Cherry-picks the extra commits from oldbranch.
git cherry-pick ..oldbranch
# Discards the 3 most recent commits from oldbranch.
git branch --force oldbranch oldbranch~3

(si lo prefieres puedes escribir @{-1} – la rama previamente verificada – en lugar de oldbranch).


Explicación técnica

¿Por qué git rebase descartar las 3 confirmaciones después del primer ejemplo? Eso es porque git rebase sin argumentos habilita el --fork-point opción por defecto, que usa el reflog local para tratar de ser robusto contra la rama ascendente que está siendo forzada.

Supongamos que se bifurcó el origen / maestro cuando contenía las confirmaciones M1, M2, M3 y luego realizó tres confirmaciones usted mismo:

M1--M2--M3  <-- origin/master
         
          T1--T2--T3  <-- topic

pero luego alguien reescribe el historial forzando el origen / maestro para eliminar M2:

M1--M3'  <-- origin/master
 
  M2--M3--T1--T2--T3  <-- topic

Usando su reflog local, git rebase puede ver que se bifurcó de una encarnación anterior de la rama de origen / maestra y, por lo tanto, las confirmaciones de M2 ​​y M3 no son realmente parte de su rama de tema. Por lo tanto, asume razonablemente que dado que M2 se eliminó de la rama ascendente, ya no lo querrá en su rama de tema una vez que la rama de tema se vuelva a basar:

M1--M3'  <-- origin/master
     
      T1'--T2'--T3'  <-- topic (rebased)

Este comportamiento tiene sentido y, por lo general, es lo correcto al realizar un rebase.

Entonces, la razón por la que fallan los siguientes comandos:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch

es porque dejan el reflog en el estado incorrecto. Git ve newbranch como si se hubiera bifurcado de la rama ascendente en una revisión que incluye las 3 confirmaciones, luego la reset --hard reescribe el historial del flujo ascendente para eliminar las confirmaciones, por lo que la próxima vez que ejecute git rebase los descarta como cualquier otro compromiso que se haya eliminado del flujo ascendente.

Pero en este caso particular, queremos que esos 3 compromisos se consideren como parte de la rama del tema. Para lograr eso, necesitamos bifurcar el flujo ascendente en la revisión anterior que no incluye las 3 confirmaciones. Eso es lo que hacen mis soluciones sugeridas, por lo tanto, ambas dejan el reflog en el estado correcto.

Para obtener más detalles, consulte la definición de --fork-point en el git rebase y git merge-base docs.

Deja una respuesta

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

Primavera – Colección de inyección

01MOf435zSx7Zcqnp7pJD4o 1.1634956193.fit lim.size 1200x630

Reseña del proyector inteligente HD portátil Kodak Luma 400