Divide una confirmación anterior en varias confirmaciones
1225
Sin crear una rama y hacer un montón de trabajo funky en una nueva rama, ¿es posible dividir una sola confirmación en unas pocas confirmaciones diferentes después de que se haya confirmado en el repositorio local?
Lo más fácil de hacer sin un rebase interactivo es (probablemente) hacer una nueva rama que comience en la confirmación antes de la que desea dividir, seleccione el compromiso, restablezca, oculte, confirme el movimiento del archivo, vuelva a aplicar la ocultación y cometer los cambios, y luego fusionarse con la rama anterior o elegir los commits que siguieron. (Luego cambie el nombre de la sucursal anterior al encabezado actual). (Probablemente sea mejor seguir los consejos de MBO y hacer un rebase interactivo.) (Copiado de la respuesta de 2010 a continuación)
William Pursell
1
Me encontré con este problema después de que accidentalmente aplasté dos commits durante un rebase en un commit anterior. Mi forma de solucionarlo fue a la caja de la aplastado cometer git reset HEAD~, git stashy luego git cherry-pickcometer el primero dentro de la calabaza, a continuación git stash pop. Mi caso cereza-Pick es bastante específica aquí, pero git stash, y git stash popes muy útil para los demás.
Primero, comience con un directorio de trabajo limpio: no git statusdebe mostrar modificaciones, eliminaciones o adiciones pendientes.
Ahora, debe decidir qué commit (s) desea dividir.
A) Dividir la confirmación más reciente
Para dividir su confirmación más reciente, primero:
$ git reset HEAD~
Ahora compromete las piezas individualmente de la forma habitual, produciendo tantos commits como necesites.
B) Dividir un commit más atrás
Esto requiere rebase , es decir, reescribir la historia. Para encontrar la confirmación correcta, tiene varias opciones:
Si fueron tres confirmaciones, entonces
$ git rebase -i HEAD~3
¿Dónde 3está la cantidad de confirmaciones?
Si estaba más atrás en el árbol de lo que quieres contar, entonces
$ git rebase -i 123abcd~
¿Dónde 123abcdestá el SHA1 de la confirmación que desea dividir?
Si está en una rama diferente (por ejemplo, una rama de características) que planea fusionar en maestra:
$ git rebase -i master
Cuando obtenga la pantalla de edición de rebase, busque la confirmación que desea separar. Al comienzo de esa línea, reemplace pickcon edit( epara abreviar). Guarde el búfer y salga. Rebase ahora se detendrá justo después de la confirmación que desea editar. Entonces:
$ git reset HEAD~
Compromete las piezas individualmente de la manera habitual, produciendo tantos compromisos como necesites, luego
Gracias por esta respuesta Quería tener algunos archivos previamente confirmados en el área de preparación, por lo que las instrucciones para mí fueron un poco diferentes. Antes de que pudiera git rebase --continue, de hecho tuve que git add (files to be added), git commity, a continuación git stash(para el resto de archivos). Después git rebase --continue, solía git checkout stash .obtener los archivos restantes
También querrá aprovechar git add -ppara agregar solo secciones parciales de archivos, posiblemente con la eopción de editar diferencias para confirmar solo un trozo. git stashTambién es útil si desea llevar adelante algún trabajo pero eliminarlo de la confirmación actual.
Craig Ringer
2
Si desea dividir y reordenar confirmaciones, lo que me gusta hacer es dividir primero y luego reordenar por separado con otro git rebase -i HEAD^3comando. De esta manera, si la división va mal, no tiene que deshacer tanto trabajo.
David M. Lloyd
44
@kralyk Los archivos que se confirmaron recientemente en HEAD se dejarán en el disco después git reset HEAD~. No están perdidos
Wayne Conrad
312
Del manual de git-rebase (sección COMPROMISOS DE DIVISIÓN)
En el modo interactivo, puede marcar confirmaciones con la acción "editar". Sin embargo, esto no significa necesariamente que git rebase espere que el resultado de esta edición sea exactamente una confirmación. De hecho, puede deshacer la confirmación o puede agregar otras confirmaciones. Esto se puede usar para dividir un commit en dos:
Comience un rebase interactivo con git rebase -i <commit>^, donde <commit>está la confirmación que desea dividir. De hecho, cualquier rango de confirmación funcionará, siempre que contenga esa confirmación.
Marque la confirmación que desea dividir con la acción "editar".
Cuando se trata de editar esa confirmación, ejecutar git reset HEAD^. El efecto es que la CABEZA se rebobina por uno y el índice sigue su ejemplo. Sin embargo, el árbol de trabajo permanece igual.
Ahora agregue los cambios al índice que desea tener en la primera confirmación. Puede usar git add(posiblemente de manera interactiva) o git gui(o ambos) para hacer eso.
Confirme el índice actual con cualquier mensaje de confirmación que sea apropiado ahora.
Repita los dos últimos pasos hasta que su árbol de trabajo esté limpio.
Palabra de advertencia: con este enfoque, perdí el mensaje de confirmación.
user420667
11
@ user420667 Sí, por supuesto. resetDespués de todo, estamos haciendo el commit, mensaje incluido. Lo más prudente que debe hacer, si sabe que va a dividir una confirmación pero desea conservar parte o la totalidad de su mensaje, es tomar una copia de ese mensaje. Por lo tanto, git showconfirme antes rebase, o si olvida o prefiere esto: vuelva más tarde a través de reflog. Nada de eso se "perderá" hasta que se recoja la basura en 2 semanas o lo que sea.
underscore_d
44
~y ^son cosas diferentes, incluso en Windows. Todavía quieres el cursor ^, así que solo tendrás que escapar de él según sea apropiado para tu caparazón. En PowerShell, es HEAD`^. Con cmd.exe, puede duplicarlo para escapar como HEAD^^. En la mayoría (todos?) Conchas, se puede rodear con citas como "HEAD^".
AndrewF
77
También puedes hacer git commit --reuse-message=abcd123. La opción corta para ello es -C.
j0057
41
Use git rebase --interactivepara editar ese compromiso anterior, ejecutar git reset HEAD~y luego git add -pagregar algunos, luego hacer un compromiso, luego agregar un poco más y hacer otro compromiso, tantas veces como desee. Cuando haya terminado, ejecute git rebase --continue, y tendrá todas las confirmaciones divididas anteriormente en su pila.
Importante : tenga en cuenta que puede jugar y hacer todos los cambios que desee, y no tener que preocuparse por perder los cambios antiguos, porque siempre puede ejecutar git reflogpara encontrar el punto en su proyecto que contiene los cambios que desea, (llamémoslo a8c4ab) y luego git reset a8c4ab.
Aquí hay una serie de comandos para mostrar cómo funciona:
mkdir git-test; cd git-test; git init
ahora agrega un archivo A
vi A
agregue esta línea:
one
git commit -am one
luego agregue esta línea a A:
two
git commit -am two
luego agregue esta línea a A:
three
git commit -am three
ahora el archivo A se ve así:
one
two
three
y nuestro git logaspecto es el siguiente (bueno, yo usogit log --pretty=oneline --pretty="%h %cn %cr ---- %s"
bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one
Digamos que queremos dividir la segunda cometió, two.
git rebase --interactive HEAD~2
Esto trae un mensaje que se ve así:
pick 2b613bc two
pick bfb8e46 three
Cambie el primero picka an epara editar esa confirmación.
git reset HEAD~
git diff nos muestra que acabamos de descifrar el commit que hicimos para el segundo commit:
diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two
Pongamos en escena ese cambio y agreguemos "y un tercero" a esa línea en el archivo A.
git add .
Este suele ser el punto durante un rebase interactivo en el que correríamos git rebase --continue, porque generalmente solo queremos volver a nuestra pila de confirmaciones para editar una confirmación anterior. Pero esta vez, queremos crear una nueva confirmación. Entonces correremos git commit -am 'two and a third'. Ahora editamos el archivo Ay agregamos la línea two and two thirds.
git add .git commit -am 'two and two thirds'git rebase --continue
Tenemos un conflicto con nuestro compromiso three, así que resolvámoslo:
Vamos a cambiar
one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three
a
one
two and a third
two and two thirds
three
git add .; git rebase --continue
Ahora nuestro git log -paspecto es el siguiente:
commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 13:57:00 2013 -0700
three
diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
one
two and a third
two and two thirds
+three
commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 14:07:07 2013 -0700
two and two thirds
diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
one
two and a third
+two and two thirds
commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 14:06:40 2013 -0700
two and a third
diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two and a third
commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 13:56:40 2013 -0700
one
diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one
Las respuestas anteriores han cubierto el uso de git rebase -ipara editar la confirmación que desea dividir y confirmarla en partes.
Esto funciona bien al dividir los archivos en diferentes confirmaciones, pero si desea separar los cambios en los archivos individuales, hay más que necesita saber.
Después de llegar al compromiso que desea dividir, usarlo rebase -iy marcarlo edit, tiene dos opciones.
Después de usar git reset HEAD~, revise los parches individualmente git add -ppara seleccionar los que desea en cada confirmación
Edite la copia de trabajo para eliminar los cambios que no desea; cometer ese estado provisional; y luego retira el commit completo para la siguiente ronda.
La opción 2 es útil si está dividiendo una confirmación grande, ya que le permite comprobar que las versiones provisionales se compilan y ejecutan correctamente como parte de la fusión. Esto procede de la siguiente manera.
Después de usar rebase -ie editing el commit, use
git reset --soft HEAD~
para deshacer la confirmación, pero deje los archivos confirmados en el índice. También puede hacer un restablecimiento mixto omitiendo --soft, dependiendo de qué tan cerca del resultado final estará su confirmación inicial. La única diferencia es si comienzas con todos los cambios organizados o con todos sin clasificar.
Ahora entra y edita el código. Puede eliminar cambios, eliminar archivos agregados y hacer lo que quiera para construir la primera confirmación de la serie que está buscando. También puede compilarlo, ejecutarlo y confirmar que tiene un conjunto de fuentes coherente.
Una vez que esté satisfecho, ponga en escena / elimine los archivos según sea necesario (me gusta usar git guipara esto) y confirme los cambios a través de la interfaz de usuario o la línea de comandos
git commit
Ese es el primer compromiso realizado. Ahora desea restaurar su copia de trabajo al estado que tenía después de la confirmación que está dividiendo, para que pueda tomar más de los cambios para su próxima confirmación. Para encontrar el sha1 del commit que está editando, use git status. En las primeras líneas del estado verá el comando rebase que se está ejecutando actualmente, en el que puede encontrar el sha1 de su commit original:
$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
pick 4847406 US135756: add debugging to the file download code
e 65dfb6a US135756: write data and download from remote
(see more in file .git/rebase-merge/done)
...
En este caso, el commit que estoy editando tiene sha1 65dfb6a. Sabiendo eso, puedo consultar el contenido de esa confirmación en mi directorio de trabajo utilizando la forma de la git checkoutcual se toma una confirmación y una ubicación de archivo. Aquí lo uso .como ubicación del archivo para reemplazar toda la copia de trabajo:
git checkout 65dfb6a .
¡No te pierdas el punto al final!
Esto verificará y organizará los archivos tal como estaban después de la confirmación que está editando, pero en relación con la confirmación anterior que realizó, por lo que cualquier cambio que ya haya confirmado no formará parte de la confirmación.
Puede continuar ahora y confirmarlo tal como está para terminar la división, o volver a hacerlo, eliminando algunas partes de la confirmación antes de realizar otra confirmación provisional.
Si desea reutilizar el mensaje de confirmación original para una o más confirmaciones, puede usarlo directamente desde los archivos de trabajo de la nueva versión:
git commit --file .git/rebase-merge/message
Finalmente, una vez que haya comprometido todos los cambios,
¡¡¡Gracias!!! Esta debería ser la respuesta aceptada. Me habría ahorrado mucho tiempo y dolor hoy. Es la única respuesta donde el resultado de la confirmación final lo lleva al mismo estado que la confirmación en edición.
Doug Coburn
1
Me gusta cómo usas el mensaje de confirmación original.
Salamandar
Usando la opción 2, cuando lo hago git checkout *Sha I'm Editing* .siempre dice Updated 0 paths from *Some Sha That's Not In Git Log*y no da cambios.
En el modo interactivo, puede marcar confirmaciones con la acción "editar". Sin embargo, esto no significa necesariamente que git rebaseespera que el resultado de esta edición sea exactamente una confirmación. De hecho, puede deshacer la confirmación o puede agregar otras confirmaciones. Esto se puede usar para dividir un commit en dos:
Comience un rebase interactivo con git rebase -i <commit>^, donde <commit>está la confirmación que desea dividir. De hecho, cualquier rango de confirmación funcionará, siempre que contenga esa confirmación.
Marque la confirmación que desea dividir con la acción "editar".
Cuando se trata de editar esa confirmación, ejecutar git reset HEAD^. El efecto es que la CABEZA se rebobina por uno y el índice sigue su ejemplo. Sin embargo, el árbol de trabajo permanece igual.
Ahora agregue los cambios al índice que desea tener en la primera confirmación. Puede usar git add(posiblemente de forma interactiva) o git gui (o ambos) para hacer eso.
Confirme el índice actual con cualquier mensaje de confirmación que sea apropiado ahora.
Repita los dos últimos pasos hasta que su árbol de trabajo esté limpio.
Continúa el rebase con git rebase --continue.
Si no está absolutamente seguro de que las revisiones intermedias son consistentes (se compilan, pasan la prueba, etc.), debe usar git stashpara guardar los cambios aún no confirmados después de cada confirmación, prueba y enmendar la confirmación si es necesario hacer arreglos. .
En Windows, recuerde que ^es un carácter de escape para la línea de comandos: debe duplicarse. Por ejemplo, emita en git reset HEAD^^lugar de git reset HEAD^.
Frédéric
@ Frédéric: s Nunca me he encontrado con esto. Al menos en PowerShell, este no es el caso. Luego, al usar ^dos veces, se restablecen dos confirmaciones por encima del HEAD actual.
Farway
@ Lejos, pruébelo en una línea de comando clásica. PowerShell es otra bestia, su carácter de escape es el backtilt.
Frédéric
Para resumir: "HEAD^"en cmd.exe o PowerShell, HEAD^^en cmd.exe, HEAD`^en PowerShell. Es útil aprender sobre cómo funcionan los shells y su shell particular (es decir, cómo un comando se convierte en partes individuales que se pasan al programa) para que pueda adaptar los comandos en línea a los caracteres correctos para su shell particular. (No específico para Windows.)
AndrewF
11
Ahora, en la última versión de TortoiseGit en Windows, puede hacerlo muy fácilmente.
Abra el cuadro de diálogo de rebase, configúrelo y siga los siguientes pasos.
Haga clic con el botón derecho en el commit que desea dividir y seleccione " Edit" (entre pick, squash, delete ...).
Haga clic en " Start" para comenzar a rebasar.
Una vez que llegue al commit para dividir, marque el Edit/Splitbotón " " y haga clic en " Amend" directamente. Se abre el diálogo de confirmación.
Anule la selección de los archivos que desea poner en una confirmación por separado.
Edite el mensaje de confirmación y luego haga clic en " commit".
Hasta que haya archivos para confirmar, el diálogo de confirmación se abrirá una y otra vez. Cuando no haya más archivos para confirmar, aún le preguntará si desea agregar una confirmación más.
Dar un poco más de contexto sobre cómo abordar los problemas en lugar de dar un RTFM sería un poco más útil.
Jordan Dea-Mattson
8
Tenga en cuenta que también hay git reset --soft HEAD^. Es similar a git reset(que está predeterminado --mixed) pero conserva el contenido del índice. De modo que si ha agregado / eliminado archivos, ya los tiene en el índice.
Resulta ser muy útil en caso de confirmaciones gigantes.
Aquí se explica cómo dividir una confirmación en IntelliJ IDEA , PyCharm , PhpStorm , etc.
En la ventana de registro de Control de versiones, seleccione la confirmación que desea dividir, haga clic derecho y seleccione el Interactively Rebase from Here
marque el que desea dividir como edit, haga clic enStart
Rebasing
Debería ver que se coloca una etiqueta amarilla, lo que significa que HEAD está configurado para esa confirmación. Haga clic derecho en esa confirmación, seleccioneUndo Commit
Ahora esas confirmaciones están de vuelta en el área de preparación, luego puede confirmarlas por separado. Después de que se hayan comprometido todos los cambios, el antiguo compromiso queda inactivo.
Lo más fácil de hacer sin un rebase interactivo es (probablemente) hacer una nueva rama que comience en la confirmación antes de la que desea dividir, seleccione el compromiso, restablezca, oculte, confirme el movimiento del archivo, vuelva a aplicar la ocultación y cometer los cambios, y luego fusionarse con la rama anterior o elegir los commits que siguieron. (Luego cambie el nombre de la sucursal anterior al encabezado actual). (Probablemente sea mejor seguir los consejos de MBO y hacer un rebase interactivo).
de acuerdo con los estándares de SO en estos días, esto debería calificarse como no una respuesta; pero esto aún puede ser útil para otros, así que si no te importa, pasa esto a los comentarios de la publicación original
YakovL
@YakovL parece razonable. Sobre el principio de acción mínima, no eliminaré la respuesta, pero no me opondría si alguien más lo hace.
William Pursell
Esto sería mucho más fácil que todas las rebase -isugerencias. Sin embargo, creo que esto no recibió mucha atención debido a la falta de formato. Tal vez podría revisarlo, ahora que tiene 126k puntos y probablemente sepa SO. ;)
Han pasado más de 8 años, pero tal vez alguien lo encuentre útil de todos modos. Pude hacer el truco sin él rebase -i. La idea es llevar a git al mismo estado que tenía antes git commit:
# first rewind back (mind the dot,# though it can be any valid path,# for instance if you want to apply only a subset of the commit)
git reset --hard <previous-commit>.# apply the changes
git checkout <commit-you-want-to-split># we're almost there, but the changes are in the index at the moment,# hence one more step (exactly as git gently suggests):# (use "git reset HEAD <file>..." to unstage)
git reset
Después de esto, verá esto brillante Unstaged changes after reset:y su repositorio está en un estado como si estuviera a punto de confirmar todos estos archivos. A partir de ahora, puede volver a cometerlo fácilmente, como suele hacer. Espero eso ayude.
git autorebase split COMMIT_ID
git reset HEAD~
,git stash
y luegogit cherry-pick
cometer el primero dentro de la calabaza, a continuacióngit stash pop
. Mi caso cereza-Pick es bastante específica aquí, perogit stash
, ygit stash pop
es muy útil para los demás.Respuestas:
git rebase -i
lo haré.Primero, comience con un directorio de trabajo limpio: no
git status
debe mostrar modificaciones, eliminaciones o adiciones pendientes.Ahora, debe decidir qué commit (s) desea dividir.
A) Dividir la confirmación más reciente
Para dividir su confirmación más reciente, primero:
Ahora compromete las piezas individualmente de la forma habitual, produciendo tantos commits como necesites.
B) Dividir un commit más atrás
Esto requiere rebase , es decir, reescribir la historia. Para encontrar la confirmación correcta, tiene varias opciones:
Si fueron tres confirmaciones, entonces
¿Dónde
3
está la cantidad de confirmaciones?Si estaba más atrás en el árbol de lo que quieres contar, entonces
¿Dónde
123abcd
está el SHA1 de la confirmación que desea dividir?Si está en una rama diferente (por ejemplo, una rama de características) que planea fusionar en maestra:
Cuando obtenga la pantalla de edición de rebase, busque la confirmación que desea separar. Al comienzo de esa línea, reemplace
pick
conedit
(e
para abreviar). Guarde el búfer y salga. Rebase ahora se detendrá justo después de la confirmación que desea editar. Entonces:Compromete las piezas individualmente de la manera habitual, produciendo tantos compromisos como necesites, luego
fuente
git rebase --continue
, de hecho tuve quegit add (files to be added)
,git commit
y, a continuacióngit stash
(para el resto de archivos). Despuésgit rebase --continue
, solíagit checkout stash .
obtener los archivos restantesgit add -p
para agregar solo secciones parciales de archivos, posiblemente con lae
opción de editar diferencias para confirmar solo un trozo.git stash
También es útil si desea llevar adelante algún trabajo pero eliminarlo de la confirmación actual.git rebase -i HEAD^3
comando. De esta manera, si la división va mal, no tiene que deshacer tanto trabajo.git reset HEAD~
. No están perdidosDel manual de git-rebase (sección COMPROMISOS DE DIVISIÓN)
fuente
~
lugar de^
.reset
Después de todo, estamos haciendo el commit, mensaje incluido. Lo más prudente que debe hacer, si sabe que va a dividir una confirmación pero desea conservar parte o la totalidad de su mensaje, es tomar una copia de ese mensaje. Por lo tanto,git show
confirme antesrebase
, o si olvida o prefiere esto: vuelva más tarde a través dereflog
. Nada de eso se "perderá" hasta que se recoja la basura en 2 semanas o lo que sea.~
y^
son cosas diferentes, incluso en Windows. Todavía quieres el cursor^
, así que solo tendrás que escapar de él según sea apropiado para tu caparazón. En PowerShell, esHEAD`^
. Con cmd.exe, puede duplicarlo para escapar comoHEAD^^
. En la mayoría (todos?) Conchas, se puede rodear con citas como"HEAD^"
.git commit --reuse-message=abcd123
. La opción corta para ello es-C
.Use
git rebase --interactive
para editar ese compromiso anterior, ejecutargit reset HEAD~
y luegogit add -p
agregar algunos, luego hacer un compromiso, luego agregar un poco más y hacer otro compromiso, tantas veces como desee. Cuando haya terminado, ejecutegit rebase --continue
, y tendrá todas las confirmaciones divididas anteriormente en su pila.Importante : tenga en cuenta que puede jugar y hacer todos los cambios que desee, y no tener que preocuparse por perder los cambios antiguos, porque siempre puede ejecutar
git reflog
para encontrar el punto en su proyecto que contiene los cambios que desea, (llamémosloa8c4ab
) y luegogit reset a8c4ab
.Aquí hay una serie de comandos para mostrar cómo funciona:
mkdir git-test; cd git-test; git init
ahora agrega un archivo
A
vi A
agregue esta línea:
one
git commit -am one
luego agregue esta línea a A:
two
git commit -am two
luego agregue esta línea a A:
three
git commit -am three
ahora el archivo A se ve así:
y nuestro
git log
aspecto es el siguiente (bueno, yo usogit log --pretty=oneline --pretty="%h %cn %cr ---- %s"
Digamos que queremos dividir la segunda cometió,
two
.git rebase --interactive HEAD~2
Esto trae un mensaje que se ve así:
Cambie el primero
pick
a ane
para editar esa confirmación.git reset HEAD~
git diff
nos muestra que acabamos de descifrar el commit que hicimos para el segundo commit:Pongamos en escena ese cambio y agreguemos "y un tercero" a esa línea en el archivo
A
.git add .
Este suele ser el punto durante un rebase interactivo en el que correríamos
git rebase --continue
, porque generalmente solo queremos volver a nuestra pila de confirmaciones para editar una confirmación anterior. Pero esta vez, queremos crear una nueva confirmación. Entonces correremosgit commit -am 'two and a third'
. Ahora editamos el archivoA
y agregamos la líneatwo and two thirds
.git add .
git commit -am 'two and two thirds'
git rebase --continue
Tenemos un conflicto con nuestro compromiso
three
, así que resolvámoslo:Vamos a cambiar
a
git add .; git rebase --continue
Ahora nuestro
git log -p
aspecto es el siguiente:fuente
Las respuestas anteriores han cubierto el uso de
git rebase -i
para editar la confirmación que desea dividir y confirmarla en partes.Esto funciona bien al dividir los archivos en diferentes confirmaciones, pero si desea separar los cambios en los archivos individuales, hay más que necesita saber.
Después de llegar al compromiso que desea dividir, usarlo
rebase -i
y marcarloedit
, tiene dos opciones.Después de usar
git reset HEAD~
, revise los parches individualmentegit add -p
para seleccionar los que desea en cada confirmaciónEdite la copia de trabajo para eliminar los cambios que no desea; cometer ese estado provisional; y luego retira el commit completo para la siguiente ronda.
La opción 2 es útil si está dividiendo una confirmación grande, ya que le permite comprobar que las versiones provisionales se compilan y ejecutan correctamente como parte de la fusión. Esto procede de la siguiente manera.
Después de usar
rebase -i
eedit
ing el commit, usepara deshacer la confirmación, pero deje los archivos confirmados en el índice. También puede hacer un restablecimiento mixto omitiendo --soft, dependiendo de qué tan cerca del resultado final estará su confirmación inicial. La única diferencia es si comienzas con todos los cambios organizados o con todos sin clasificar.
Ahora entra y edita el código. Puede eliminar cambios, eliminar archivos agregados y hacer lo que quiera para construir la primera confirmación de la serie que está buscando. También puede compilarlo, ejecutarlo y confirmar que tiene un conjunto de fuentes coherente.
Una vez que esté satisfecho, ponga en escena / elimine los archivos según sea necesario (me gusta usar
git gui
para esto) y confirme los cambios a través de la interfaz de usuario o la línea de comandosEse es el primer compromiso realizado. Ahora desea restaurar su copia de trabajo al estado que tenía después de la confirmación que está dividiendo, para que pueda tomar más de los cambios para su próxima confirmación. Para encontrar el sha1 del commit que está editando, use
git status
. En las primeras líneas del estado verá el comando rebase que se está ejecutando actualmente, en el que puede encontrar el sha1 de su commit original:En este caso, el commit que estoy editando tiene sha1
65dfb6a
. Sabiendo eso, puedo consultar el contenido de esa confirmación en mi directorio de trabajo utilizando la forma de lagit checkout
cual se toma una confirmación y una ubicación de archivo. Aquí lo uso.
como ubicación del archivo para reemplazar toda la copia de trabajo:¡No te pierdas el punto al final!
Esto verificará y organizará los archivos tal como estaban después de la confirmación que está editando, pero en relación con la confirmación anterior que realizó, por lo que cualquier cambio que ya haya confirmado no formará parte de la confirmación.
Puede continuar ahora y confirmarlo tal como está para terminar la división, o volver a hacerlo, eliminando algunas partes de la confirmación antes de realizar otra confirmación provisional.
Si desea reutilizar el mensaje de confirmación original para una o más confirmaciones, puede usarlo directamente desde los archivos de trabajo de la nueva versión:
Finalmente, una vez que haya comprometido todos los cambios,
continuará y completará la operación de rebase.
fuente
git checkout *Sha I'm Editing* .
siempre diceUpdated 0 paths from *Some Sha That's Not In Git Log*
y no da cambios.git rebase --interactive
se puede usar para dividir una confirmación en confirmaciones más pequeñas. Los documentos de Git sobre rebase tienen un recorrido conciso del proceso - Compromisos de división :fuente
^
es un carácter de escape para la línea de comandos: debe duplicarse. Por ejemplo, emita engit reset HEAD^^
lugar degit reset HEAD^
.^
dos veces, se restablecen dos confirmaciones por encima del HEAD actual."HEAD^"
en cmd.exe o PowerShell,HEAD^^
en cmd.exe,HEAD`^
en PowerShell. Es útil aprender sobre cómo funcionan los shells y su shell particular (es decir, cómo un comando se convierte en partes individuales que se pasan al programa) para que pueda adaptar los comandos en línea a los caracteres correctos para su shell particular. (No específico para Windows.)Ahora, en la última versión de TortoiseGit en Windows, puede hacerlo muy fácilmente.
Abra el cuadro de diálogo de rebase, configúrelo y siga los siguientes pasos.
Edit
" (entre pick, squash, delete ...).Start
" para comenzar a rebasar.Edit/Split
botón " " y haga clic en "Amend
" directamente. Se abre el diálogo de confirmación.commit
".Muy útil, gracias TortoiseGit!
fuente
Puedes hacer rebase interactivo
git rebase -i
. La página del manual tiene exactamente lo que quieres:http://git-scm.com/docs/git-rebase#_splitting_commits
fuente
Tenga en cuenta que también hay
git reset --soft HEAD^
. Es similar agit reset
(que está predeterminado--mixed
) pero conserva el contenido del índice. De modo que si ha agregado / eliminado archivos, ya los tiene en el índice.Resulta ser muy útil en caso de confirmaciones gigantes.
fuente
Aquí se explica cómo dividir una confirmación en IntelliJ IDEA , PyCharm , PhpStorm , etc.
En la ventana de registro de Control de versiones, seleccione la confirmación que desea dividir, haga clic derecho y seleccione el
Interactively Rebase from Here
marque el que desea dividir como
edit
, haga clic enStart Rebasing
Debería ver que se coloca una etiqueta amarilla, lo que significa que HEAD está configurado para esa confirmación. Haga clic derecho en esa confirmación, seleccione
Undo Commit
Ahora esas confirmaciones están de vuelta en el área de preparación, luego puede confirmarlas por separado. Después de que se hayan comprometido todos los cambios, el antiguo compromiso queda inactivo.
fuente
Lo más fácil de hacer sin un rebase interactivo es (probablemente) hacer una nueva rama que comience en la confirmación antes de la que desea dividir, seleccione el compromiso, restablezca, oculte, confirme el movimiento del archivo, vuelva a aplicar la ocultación y cometer los cambios, y luego fusionarse con la rama anterior o elegir los commits que siguieron. (Luego cambie el nombre de la sucursal anterior al encabezado actual). (Probablemente sea mejor seguir los consejos de MBO y hacer un rebase interactivo).
fuente
rebase -i
sugerencias. Sin embargo, creo que esto no recibió mucha atención debido a la falta de formato. Tal vez podría revisarlo, ahora que tiene 126k puntos y probablemente sepa SO. ;)Creo que es la mejor manera que uso
git rebase -i
. Creé un video para mostrar los pasos para dividir una confirmación: https://www.youtube.com/watch?v=3EzOz7e1ADIfuente
Si tienes esto:
Donde ha comprometido algún contenido en commit B:
Pero desea dividir B en C - D y obtener este resultado:
Puede dividir el contenido de esta manera, por ejemplo (contenido de diferentes directorios en diferentes confirmaciones) ...
Restablezca la rama de nuevo a la confirmación antes de la división:
Crear primer commit (C):
Crear segunda confirmación (D):
fuente
Han pasado más de 8 años, pero tal vez alguien lo encuentre útil de todos modos. Pude hacer el truco sin él
rebase -i
. La idea es llevar a git al mismo estado que tenía antesgit commit
:Después de esto, verá esto brillante
Unstaged changes after reset:
y su repositorio está en un estado como si estuviera a punto de confirmar todos estos archivos. A partir de ahora, puede volver a cometerlo fácilmente, como suele hacer. Espero eso ayude.fuente
Una referencia rápida de los comandos necesarios, porque básicamente sé qué hacer pero siempre olvido la sintaxis correcta:
Créditos a la publicación del blog de Emmanuel Bernard .
fuente