git rebase -i <any earlier commit>. Esto muestra una lista de confirmaciones en su editor de texto configurado.
Encuentre la confirmación que desea insertar después (supongamos que es a1b2c3d). En su editor, para esa línea, cambie picka edit.
Comience el rebase cerrando su editor de texto (guarde sus cambios). Esto lo deja en el símbolo del sistema con la confirmación que eligió anteriormente ( a1b2c3d) como si acabara de confirmarse .
Realiza tus cambios y git commit( NO enmiendas, a diferencia de la mayoría de los edits). Esto crea una nueva confirmación después de la que eligió.
git rebase --continue. Esto reproduce las confirmaciones sucesivas, dejando su nueva confirmación insertada en el lugar correcto.
Tenga en cuenta que esto reescribirá la historia y destruirá a cualquier otra persona que intente tirar.
Esto agregó el nuevo commit después del commit, que es después del que estaba haciendo un rebase (también el último commit), en lugar de justo después del que estaba haciendo el rebase. El resultado fue el mismo que si hubiera realizado una nueva confirmación al final con los cambios que quería insertar. Mi historia se convirtió en A -- B -- C -- Dlugar de lo deseado A -- D -- B -- C.
Xedin Desconocido
2
@XedinUnknown: Entonces no usaste Rebase correctamente.
SLaks
3
Ahora Dpodría ser un compromiso en cualquier lugar. Supongamos que tenemos A - B - Cy tenemos alguna confirmación Dque ni siquiera está en esta rama. Sin embargo, sabemos que es SHA. Podemos hacerlo git rebase -i HEAD~3. Ahora entre las líneas Ay Bpick, insertamos una nuevapick línea que dice pick SHA, dando el hash de lo deseado D. No tiene por qué ser el hash completo, solo el acortado. git rebase -isolo cherry selecciona las confirmaciones que se enumeran por picklíneas en el búfer; no tienen que ser los originales que enumeró para usted.
Kaz
1
@Kaz Esto parece una respuesta válida diferente.
BartoszKP
3
Aún más fácil, puede usar la breakpalabra clave en el editor en su propia línea entre dos confirmaciones (o en la primera línea, para insertar una confirmación antes de la confirmación especificada).
SimonT
30
Resulta ser bastante simple, la respuesta se encuentra aquí . Supongamos que estás en una rama branch. Realice estos pasos:
cree una rama temporal desde el commit después de que desee insertar el nuevo commit (en este caso, commit A):
git checkout -b temp A
realiza los cambios y los confirma, creando un commit, llamémoslo N:
git commit -a -m "Message"
(o git addseguido de git commit)
vuelva a redactar las confirmaciones que desea tener después de la nueva confirmación (en este caso, confirmaciones By C) en la nueva confirmación:
No pude seguir la respuesta aceptada por SLaks, pero esto funcionó para mí. Después de obtener el historial de confirmación que quería, tuve git push --forceque cambiar el repositorio remoto.
escapecharacter
1
Cuando se usa rebase usando la opción -Xtheirs, se resuelven los conflictos automáticamente, entonces git rebase temp branch -Xtheirs. ¡Respuesta útil para inyectar en un guión!
David C
Para novatos como yo, me gustaría agregar eso después git rebase temp branch, pero antes git branch -d temp, todo lo que tiene que hacer es arreglar y organizar la fusión de conflictos y problemas git rebase --continue, es decir, no es necesario cometer nada, etc.
Pugsley
19
Solución aún más fácil:
Crea tu nueva confirmación al final, D. Ahora tienes:
A -- B -- C -- D
Entonces corre:
$ git rebase -i hash-of-A
Git abrirá su editor y se verá así:
pick 8668d21 B
pick 650f1fc C
pick 74096b9 D
Simplemente mueva D a la parte superior de esta manera, luego guarde y salga
Buena idea, sin embargo, puede ser difícil introducir D en C, cuando pretende que estos cambios sean wrt. a A.
BartoszKP
Tengo una situación en la que tengo 3 commits que quiero reajustar juntos y un commit en el medio que no está relacionado. Es súper agradable poder mover esa confirmación antes o después por la línea de confirmaciones.
despliega el
13
Suponiendo que el historial de confirmación es preA -- A -- B -- C, si desea insertar una confirmación entre Ay B, los pasos son los siguientes:
git rebase -i hash-of-preA
Git abrirá tu editor. El contenido puede gustar esto:
pick 8668d21 A
pick 650f1fc B
pick 74096b9 C
Cambia el primero picka edit:
edit 8668d21 A
pick 650f1fc B
pick 74096b9 C
Guardar y Salir.
Modifica tu código y luego git add . && git commit -m "I"
git rebase --continue
Ahora tu historial de commit de Git es preA -- A -- I -- B -- C
Si encuentra un conflicto, Git se detendrá en esta confirmación. Puede utilizar git diffpara localizar marcadores de conflicto y resolverlos. Después de resolver todos los conflictos, debe usar git add <filename>para decirle a Git que el conflicto se ha resuelto y luego volver a ejecutarlo git rebase --continue.
Si desea deshacer el rebase, use git rebase --abort.
Aquí hay una estrategia que evita hacer un "hack de edición" durante el rebase visto en las otras respuestas que he leído.
Al usar git rebase -i, obtienes una lista de confirmaciones desde esa confirmación. Simplemente agregue un "salto" en la parte superior del archivo, esto hará que el rebase se rompa en ese punto.
Una vez lanzado, git rebaseahora se detendrá en el punto del "descanso". Ahora puede editar sus archivos y crear su confirmación normalmente. Luego puede continuar el rebase con git rebase --continue. Esto puede causar conflictos que tendrá que solucionar. Si te pierdes, no olvides que siempre puedes abortar el uso git rebase --abort.
Esta estrategia se puede generalizar para insertar un compromiso en cualquier lugar, simplemente coloque el "salto" en el lugar donde desea insertar un compromiso.
Después de reescribir el historial, no te olvides git push -f. Se aplican las advertencias habituales sobre otras personas que buscan su rama.
Lo siento, pero tengo problemas para entender cómo es esto "evitar rebase". Usted está ejecutando rebaseaquí. No hay mucha diferencia si creará el commit durante el rebase o de antemano.
BartoszKP
Woops, quise decir evitar el "hack de edición" durante el rebase, supongo que lo expresé mal.
axerologementy
Correcto. Mi respuesta tampoco usa la función "editar" de rebase. Aún así, este es otro enfoque válido, ¡gracias! :-)
BartoszKP
6
Muchas buenas respuestas aquí ya. Solo quería agregar una solución "sin rebase", en 4 sencillos pasos.
Resumen
git checkout A
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD
Explicación
(Nota: una ventaja de esta solución es que no toca su rama hasta el paso final, cuando está 100% seguro de que está de acuerdo con el resultado final, por lo que tiene un paso muy útil de "confirmación previa" permitiendo pruebas AB ).
Estado inicial (asumí masterel nombre de su sucursal)
A -- B -- C <<< master <<< HEAD
1) Comience señalando HEAD en el lugar correcto
git checkout A
B -- C <<< master
/
A <<< detached HEAD
(Opcionalmente aquí, en lugar de separar HEAD, podríamos haber creado una rama temporal con la git checkout -b temp Aque tendríamos que eliminar al final del proceso. Ambas variantes funcionan, haga lo que prefiera ya que todo lo demás sigue igual)
2) Cree el nuevo commit D para insertar
# at this point, make the changes you wanted to insert between A and B, then
git commit -am "Message for commit D"
B -- C <<< master
/
A -- D <<< detached HEAD (or <<< temp <<< HEAD)
3) Luego traiga copias de los últimos commits faltantes B y C (sería la misma línea si hubiera más commits)
git cherry-pick A..C
# (if any, resolve any potential conflicts between D and these last commits)
B -- C <<< master
/
A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)
(Prueba AB cómoda aquí si es necesario)
Ahora es el momento de inspeccionar su código, probar cualquier cosa que necesite ser probada, y también puede diferenciar / comparar / inspeccionar lo que tenía y lo que obtendría después de las operaciones.
4) Dependiendo de sus pruebas entre Cy C', está bien o es KO.
(CUALQUIERA) 4-OK) Finalmente, mueva la referencia demaster
git branch -f master HEAD
B -- C <<< (B and C are candidates for garbage collection)
/
A -- D -- B' -- C' <<< master
(O) 4-KO) Solo déjelo mastersin cambios
Si creó una bifurcación temporal, simplemente elimínela con git branch -d <name>, pero si optó por la ruta HEAD separada, no es necesaria ninguna acción en este momento, las nuevas confirmaciones serán elegibles para la recolección de basura justo después de volver HEADa unir con ungit checkout master
En ambos casos (OK o KO), en este punto simplemente mastervuelva a pagar para volver a adjuntar HEAD.
Respuestas:
Es incluso más fácil que en la respuesta de OP.
git rebase -i <any earlier commit>
. Esto muestra una lista de confirmaciones en su editor de texto configurado.a1b2c3d
). En su editor, para esa línea, cambiepick
aedit
.a1b2c3d
) como si acabara de confirmarse .git commit
( NO enmiendas, a diferencia de la mayoría de losedit
s). Esto crea una nueva confirmación después de la que eligió.git rebase --continue
. Esto reproduce las confirmaciones sucesivas, dejando su nueva confirmación insertada en el lugar correcto.Tenga en cuenta que esto reescribirá la historia y destruirá a cualquier otra persona que intente tirar.
fuente
A -- B -- C -- D
lugar de lo deseadoA -- D -- B -- C
.D
podría ser un compromiso en cualquier lugar. Supongamos que tenemosA - B - C
y tenemos alguna confirmaciónD
que ni siquiera está en esta rama. Sin embargo, sabemos que es SHA. Podemos hacerlogit rebase -i HEAD~3
. Ahora entre las líneasA
yB
pick
, insertamos una nuevapick
línea que dicepick SHA
, dando el hash de lo deseadoD
. No tiene por qué ser el hash completo, solo el acortado.git rebase -i
solo cherry selecciona las confirmaciones que se enumeran porpick
líneas en el búfer; no tienen que ser los originales que enumeró para usted.break
palabra clave en el editor en su propia línea entre dos confirmaciones (o en la primera línea, para insertar una confirmación antes de la confirmación especificada).Resulta ser bastante simple, la respuesta se encuentra aquí . Supongamos que estás en una rama
branch
. Realice estos pasos:cree una rama temporal desde el commit después de que desee insertar el nuevo commit (en este caso, commit
A
):realiza los cambios y los confirma, creando un commit, llamémoslo
N
:(o
git add
seguido degit commit
)vuelva a redactar las confirmaciones que desea tener después de la nueva confirmación (en este caso, confirmaciones
B
yC
) en la nueva confirmación:(posiblemente deba usar
-p
para preservar las fusiones, si hubiera alguna, gracias a un comentario ya no existente de ciekawy )eliminar la rama temporal:
Después de esto, la historia se ve de la siguiente manera:
Por supuesto, es posible que aparezcan algunos conflictos durante el rebase.
En caso de que su sucursal no sea solo local, esto introducirá el historial de reescritura, por lo que podría causar serios problemas.
fuente
git push --force
que cambiar el repositorio remoto.git rebase temp branch -Xtheirs
. ¡Respuesta útil para inyectar en un guión!git rebase temp branch
, pero antesgit branch -d temp
, todo lo que tiene que hacer es arreglar y organizar la fusión de conflictos y problemasgit rebase --continue
, es decir, no es necesario cometer nada, etc.Solución aún más fácil:
Crea tu nueva confirmación al final, D. Ahora tienes:
Entonces corre:
Git abrirá su editor y se verá así:
Simplemente mueva D a la parte superior de esta manera, luego guarde y salga
Ahora tendrás:
fuente
Suponiendo que el historial de confirmación es
preA -- A -- B -- C
, si desea insertar una confirmación entreA
yB
, los pasos son los siguientes:git rebase -i hash-of-preA
Git abrirá tu editor. El contenido puede gustar esto:
Cambia el primero
pick
aedit
:Guardar y Salir.
Modifica tu código y luego
git add . && git commit -m "I"
git rebase --continue
Ahora tu historial de commit de Git es
preA -- A -- I -- B -- C
Si encuentra un conflicto, Git se detendrá en esta confirmación. Puede utilizar
git diff
para localizar marcadores de conflicto y resolverlos. Después de resolver todos los conflictos, debe usargit add <filename>
para decirle a Git que el conflicto se ha resuelto y luego volver a ejecutarlogit rebase --continue
.Si desea deshacer el rebase, use
git rebase --abort
.fuente
Aquí hay una estrategia que evita hacer un "hack de edición" durante el rebase visto en las otras respuestas que he leído.
Al usar
git rebase -i
, obtienes una lista de confirmaciones desde esa confirmación. Simplemente agregue un "salto" en la parte superior del archivo, esto hará que el rebase se rompa en ese punto.Una vez lanzado,
git rebase
ahora se detendrá en el punto del "descanso". Ahora puede editar sus archivos y crear su confirmación normalmente. Luego puede continuar el rebase congit rebase --continue
. Esto puede causar conflictos que tendrá que solucionar. Si te pierdes, no olvides que siempre puedes abortar el usogit rebase --abort
.Esta estrategia se puede generalizar para insertar un compromiso en cualquier lugar, simplemente coloque el "salto" en el lugar donde desea insertar un compromiso.
Después de reescribir el historial, no te olvides
git push -f
. Se aplican las advertencias habituales sobre otras personas que buscan su rama.fuente
rebase
aquí. No hay mucha diferencia si creará el commit durante el rebase o de antemano.Muchas buenas respuestas aquí ya. Solo quería agregar una solución "sin rebase", en 4 sencillos pasos.
Resumen
Explicación
(Nota: una ventaja de esta solución es que no toca su rama hasta el paso final, cuando está 100% seguro de que está de acuerdo con el resultado final, por lo que tiene un paso muy útil de "confirmación previa" permitiendo pruebas AB ).
Estado inicial (asumí
master
el nombre de su sucursal)1) Comience señalando HEAD en el lugar correcto
(Opcionalmente aquí, en lugar de separar HEAD, podríamos haber creado una rama temporal con la
git checkout -b temp A
que tendríamos que eliminar al final del proceso. Ambas variantes funcionan, haga lo que prefiera ya que todo lo demás sigue igual)2) Cree el nuevo commit D para insertar
3) Luego traiga copias de los últimos commits faltantes B y C (sería la misma línea si hubiera más commits)
(Prueba AB cómoda aquí si es necesario)
Ahora es el momento de inspeccionar su código, probar cualquier cosa que necesite ser probada, y también puede diferenciar / comparar / inspeccionar lo que tenía y lo que obtendría después de las operaciones.
4) Dependiendo de sus pruebas entre
C
yC'
, está bien o es KO.(CUALQUIERA) 4-OK) Finalmente, mueva la referencia de
master
(O) 4-KO) Solo déjelo
master
sin cambiosSi creó una bifurcación temporal, simplemente elimínela con
git branch -d <name>
, pero si optó por la ruta HEAD separada, no es necesaria ninguna acción en este momento, las nuevas confirmaciones serán elegibles para la recolección de basura justo después de volverHEAD
a unir con ungit checkout master
En ambos casos (OK o KO), en este punto simplemente
master
vuelva a pagar para volver a adjuntarHEAD
.fuente