Pregunta Divida un compromiso anterior en múltiples commits


Sin crear una sucursal y hacer un montón de trabajo funky en una nueva sucursal, ¿es posible dividir una única confirmación en varias confirmaciones después de que se haya enviado al repositorio local?


831
2018-06-02 16:11


origen


Respuestas:


git rebase -i lo haré.

Primero, comience con un directorio de trabajo limpio: git status no debe mostrar modificaciones pendientes, eliminaciones o adiciones.

Para dividir su compromiso más reciente, primero:

$ git reset HEAD~

Ahora ingrese las piezas individualmente de la manera habitual, produciendo tantos commits como necesite.

Si estaba más atrás en el árbol, entonces

$ git rebase -i HEAD~3

dónde 3 es cuántos commits devuelve.

Si estaba más atrás en el árbol de lo que quieres contar, entonces

$ git rebase -i 123abcd~

dónde 123abcd es el SHA1 de la confirmación que desea dividir.

Cuando obtenga la pantalla de edición de rebase, encuentre la confirmación que desea separar. Al comienzo de esa línea, reemplace pick con edit (e para abreviar). Guarde el buffer y salga. Rebase ahora se detendrá justo después de la confirmación que deseas editar. Entonces:

$ git reset HEAD~

Comience las piezas individualmente de la manera habitual, produciendo tantos commit como necesite, luego

$ git rebase --continue

1279
2018-06-02 16:26



De git-rebase manual (sección DIFERIR COMPROMISOS)

En el modo interactivo, puede marcar commits con la acción "editar". Sin embargo, esto no significa necesariamente que git rebase espera que el resultado de esta edición sea exactamente un commit. De hecho, puede deshacer la confirmación, o puede agregar otras confirmaciones. Esto se puede usar para dividir un compromiso en dos:

  • Comience una rebase interactiva con git rebase -i <commit>^, dónde <commit> es el compromiso que quieres dividir De hecho, cualquier rango de compromiso funcionará, siempre que contenga ese compromiso.

  • Marque la confirmación que desea dividir con la acción "editar".

  • Cuando se trata de editar ese commit, ejecuta git reset HEAD^. El efecto es que HEAD se rebobina en uno, y el índice sigue el juego. Sin embargo, el árbol de trabajo permanece igual.

  • Ahora agregue los cambios al índice que desea tener en la primera confirmación. Puedes usar git add (posiblemente interactivamente) o git gui (o ambos) para hacer eso.

  • Confirme el índice actual con cualquier mensaje de compromiso apropiado ahora.

  • Repita los dos últimos pasos hasta que su árbol de trabajo esté limpio.

  • Continúa la rebase con git rebase --continue.


244
2018-01-22 15:05



Utilizar git rebase --interactive para editar ese compromiso anterior, ejecuta git reset HEAD~, y entonces git add -p para agregar un poco, luego realice un commit, luego agregue un poco más y realice otro commit, tantas veces como desee. Cuando hayas terminado, corre git rebase --continue, y tendrás todos los commits divididos antes en tu stack.

Importante: Tenga en cuenta que puede jugar y hacer todos los cambios que desee, y no tener que preocuparse por perder los cambios anteriores, ya que siempre puede ejecutar git reflog para encontrar el punto en su proyecto que contiene los cambios que desea, (llamémoslo a8c4ab), y entonces 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 agrega esta línea a A:

two

git commit -am two

luego agrega esta línea a A:

three

git commit -am three

ahora el archivo A se ve así:

one
two
three

y nuestro git log se parece a lo siguiente (bueno, yo uso git 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 el segundo compromiso, two.

git rebase --interactive HEAD~2

Esto hace aparecer un mensaje que se ve así:

pick 2b613bc two
pick bfb8e46 three

Cambiar el primero pick a una e para editar ese compromiso.

git reset HEAD~

git diff nos muestra que acabamos de desglosar el compromiso que hicimos para el segundo compromiso:

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 una rebase interactiva donde correríamos git rebase --continue, porque normalmente solo queremos volver a la pila de confirmaciones para editar una confirmación anterior. Pero esta vez, queremos crear un nuevo compromiso. Así que correremos git commit -am 'two and a third'. Ahora editamos el archivo A y agrega 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 vamos a resolverlo:

Cambiaremos

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 -p Se ve como esto:

commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <roseperrone@fake.com>
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 <roseperrone@fake.com>
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 <roseperrone@fake.com>
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 <roseperrone@fake.com>
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

34
2017-07-07 21:10



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 commits, pero si desea separar los cambios en los archivos individuales, hay más que necesita saber.

Habiendo llegado al compromiso que desea dividir, usando rebase -i y marcarlo para edit, tienes dos opciones.

  1. Después de usar git reset HEAD~, revise los parches de forma individual utilizando git add -p para seleccionar los que desea en cada commit

  2. Edite la copia de trabajo para eliminar los cambios que no desea; cometer ese estado interino; y luego retire el compromiso completo para la próxima ronda.

La opción 2 es útil si está dividiendo una confirmación grande, ya que le permite verificar 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 y editing el compromiso, use

git reset --soft HEAD~

para deshacer la confirmación, pero deje los archivos comprometidos en el índice. También puede hacer un restablecimiento mixto omitiendo --soft, dependiendo de cuán cerca del resultado final será su compromiso inicial. La única diferencia es si comienza con todos los cambios ordenados o con todos ellos sin grabar.

Ahora ve y edita el código. Puedes eliminar cambios, eliminar archivos agregados y hacer lo que quieras para construir el primer commit de la serie que estás buscando. También puedes construirlo, ejecutarlo y confirmar que tienes un conjunto de fuentes consistente.

Una vez que esté satisfecho, ponga en escena / deje de grabar los archivos según sea necesario (me gusta usar git gui para esto), y comprometer los cambios a través de la interfaz de usuario o la línea de comando

git commit

Ese es el primer compromiso hecho. 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 cambios para su próxima confirmación. Para encontrar el sha1 de la confirmación 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 confirmación 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 compromiso que estoy editando tiene sha1 65dfb6a. Sabiendo eso, puedo verificar el contenido de esa confirmación sobre mi directorio de trabajo usando la forma de git checkout que toma tanto una confirmación como una ubicación de archivo. Aquí uso . como la 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 previa que realizó, por lo que los cambios que ya haya cometido no serán parte de la confirmación.

Puede continuar ahora y confirmarlo tal como está para terminar la división, o ir de nuevo, borrando algunas partes de la confirmación antes de hacer otra confirmación intermedia.

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 rebase:

git commit --file .git/rebase-merge/message

Finalmente, una vez que haya realizado todos los cambios,

git rebase --continue

continuará y completará la operación de rebase.


19
2018-03-31 10:23



git rebase --interactive se puede usar para dividir un commit en commits más pequeños. los Los documentos de Git en rebase tienen una guía concisa del proceso: Compromisos de división:

En el modo interactivo, puede marcar commits con la acción "editar". Sin embargo, esto no significa necesariamente que git rebase espera que el resultado de esta edición sea exactamente un commit. De hecho, puede deshacer la confirmación, o puede agregar otras confirmaciones. Esto se puede usar para dividir un compromiso en dos:

  • Comience una rebase interactiva con git rebase -i <commit>^, dónde <commit> es el compromiso que quieres dividir De hecho, cualquier rango de compromiso funcionará, siempre que contenga ese compromiso.

  • Marque la confirmación que desea dividir con la acción "editar".

  • Cuando se trata de editar ese commit, ejecuta git reset HEAD^. El efecto es que HEAD se rebobina en uno, y el índice sigue el juego. Sin embargo, el árbol de trabajo permanece igual.

  • Ahora agregue los cambios al índice que desea tener en la primera confirmación. Puedes usar git add (posiblemente interactivamente) o git gui (o ambos) para hacer eso.

  • Confirme el índice actual con cualquier mensaje de compromiso apropiado ahora.

  • Repita los dos últimos pasos hasta que su árbol de trabajo esté limpio.

  • Continúa la rebase con git rebase --continue.

Si no está absolutamente seguro de que las revisiones intermedias son consistentes (compilan, pasan el banco de pruebas, etc.) debe usar git stash para esconder los cambios aún no confirmados después de cada confirmación, prueba y modificación de la confirmación si las correcciones son necesarias.


17
2017-07-14 22:25



Puedes hacer una rebase interactiva git rebase -i. La página Man tiene exactamente lo que quieres:

http://git-scm.com/docs/git-rebase#_splitting_commits


10
2018-06-02 16:15



Tenga en cuenta que también hay git reset --soft HEAD^. Es similar a git reset (que por defecto --mixed) pero conserva los contenidos del índice. De modo que si ha agregado / eliminado archivos, ya los tiene en el índice.

Resulta ser muy útil en caso de compromisos gigantes.


7
2017-11-27 15:23



Ahora en el último TortoiseGit en Windows puedes hacerlo muy fácilmente.

Abra el diálogo de rebase, configurarloy haz los siguientes pasos.

  • Haga clic con el botón derecho en la confirmación que desea dividir y seleccione "Edit"(entre pick, squash, delete ...).
  • Haga clic en "Start"para comenzar a rebasar.
  • Una vez que llega al compromiso de dividir, verifica "Edit/Split"botón y haga clic en "Amend"directamente. Se abre el cuadro de diálogo de confirmación.
    Edit/Split commit
  • Deseleccione los archivos que desea colocar en una confirmación separada.
  • 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 hay más archivos para enviar, aún le preguntará si desea agregar un compromiso más.

Muy útil, gracias TortoiseGit!


7
2018-04-22 10:32



Creo que 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=3EzOz7e1ADI


1
2017-07-25 11:47