Dividir una confirmación anterior en múltiples confirmaciones

Resuelto koblas asked hace 13 años • 23 respuestas

Sin crear una rama y hacer un montón de trabajo extraño en una nueva rama, ¿es posible dividir una única confirmación en algunas confirmaciones diferentes después de que se haya confirmado en el repositorio local?

koblas avatar Jun 02 '11 23:06 koblas
Aceptado

git rebase -ilo haré.

Primero, comience con un directorio de trabajo limpio: git statusno debería mostrar modificaciones, eliminaciones o adiciones pendientes.

Ahora tienes que decidir qué confirmaciones quieres dividir.

A) Dividir el compromiso más reciente

Para dividir su confirmación más reciente, primero:

$ git reset HEAD~

Ahora confirme las piezas individualmente de la forma habitual, produciendo tantas confirmaciones como necesite.

B) Dividir un compromiso más atrás

Esto requiere rebasar , es decir, reescribir la historia. Para especificar la confirmación correcta, tiene varias opciones:

  • Si son tres confirmaciones, entonces

      $ git rebase -i HEAD~3
    

    ¿ Dónde 3está cuántas confirmaciones hay?

  • Si está más atrás en el árbol de lo que desea contar, entonces

      $ git rebase -i 123abcd~
    

    ¿Dónde 123abcdestá el SHA1 del compromiso que desea dividir?

  • Si está en una rama diferente (por ejemplo, una rama de funciones) en la que desea fusionarse master:

      $ git rebase -i master
    

Cuando aparezca la pantalla de edición de rebase, busque la confirmación que desea dividir. Al principio de esa línea, reemplácela 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~

Confirme las piezas individualmente de la forma habitual, produciendo tantas confirmaciones como necesite.

Finalmente

$ git rebase --continue
Wayne Conrad avatar Jun 02 '2011 16:06 Wayne Conrad

Del manual de git-rebase (sección DIVISIÓN DE COMPROMISOS)

En modo interactivo, puedes 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 agregar otras confirmaciones. Esto se puede utilizar para dividir una confirmación en dos:

  • Inicie una rebase interactiva con git rebase -i <commit>^, ¿dónde <commit>está el compromiso que desea dividir? De hecho, cualquier rango de confirmación servirá, siempre que contenga esa confirmación.

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

  • Cuando se trata de editar ese compromiso, ejecute git reset HEAD^. El efecto es que el HEAD se rebobina uno y el índice hace lo mismo. Sin embargo, el árbol de trabajo sigue siendo el mismo.

  • Ahora agregue los cambios al índice que desea tener en la primera confirmación. Puede utilizar git add(posiblemente de forma interactiva) o git gui(o ambos) para hacerlo.

  • Confirme el índice actual con cualquier mensaje de confirmación apropiado en este momento.

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

  • Continúe el rebase con git rebase --continue.

MBO avatar Jan 22 '2010 15:01 MBO

Las respuestas anteriores han cubierto el uso de git rebase -ipara editar la confirmación que desea dividir y su confirmación en partes.

Esto funciona bien al dividir los archivos en diferentes confirmaciones, pero si desea dividir los cambios en los archivos individuales, necesita saber más.

Una vez que haya llegado al compromiso que desea dividir, usándolo rebase -iy marcándolo edit, tiene dos opciones.

  1. Después de usarlo git reset HEAD~, revise los parches individualmente usando git add -ppara seleccionar los que desee en cada confirmación.

  2. Edite la copia de trabajo para eliminar los cambios que no desee; comprometer ese estado provisional; y luego retirar el compromiso 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 combinación. Esto procede de la siguiente manera.

Después de usar rebase -iy editrealizar el compromiso, use

git reset --soft HEAD~

para deshacer la confirmación, pero deje los archivos comprometidos en el índice. También puedes hacer un reinicio mixto omitiendo --soft, dependiendo de qué tan cerca del resultado final estará tu confirmación inicial. La única diferencia es si comienza con todos los cambios en etapas o con todos ellos sin etapas.

Ahora entra y edita el código. Puedes eliminar cambios, eliminar archivos agregados y hacer lo que quieras para construir la primera confirmación de la serie que estás buscando. También puede compilarlo, ejecutarlo y confirmar que tiene un conjunto de fuentes coherente.

Una vez que esté satisfecho, prepare o retire los archivos según sea necesario (me gusta usarlos git guipara esto) y confirme los cambios a través de la interfaz de usuario o la línea de comando.

git commit

Esa es la primera confirmación realizada. Ahora desea restaurar su copia de trabajo al estado que tenía después de la confirmación que está dividiendo, para que pueda realizar más cambios para su próxima confirmación. Para encontrar el sha1 de la confirmación que estás editando, usa git status. En las primeras líneas del estado verás el comando rebase que se está ejecutando actualmente, en el que puedes encontrar el sha1 de tu 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 en mi directorio de trabajo usando el formulario que git checkouttoma tanto una confirmación como una ubicación de archivo. Aquí utilizo .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 será parte de la confirmación.

Puede continuar ahora y confirmarlo tal como está para finalizar la división, o volver a hacerlo y eliminar 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 rebase:

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

Finalmente, una vez que hayas realizado todos los cambios,

git rebase --continue

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

Andy Mortimer avatar Mar 31 '2017 10:03 Andy Mortimer

Úselo git rebase --interactivepara editar esa confirmación anterior, ejecute git reset HEAD~y luego git add -pagregue algo, luego haga una confirmación, luego agregue algo más y haga otra confirmación, tantas veces como desee. Cuando haya terminado, ejecute git rebase --continuey tendrá todas las confirmaciones divididas anteriormente en su pila.

Importante : tenga en cuenta que puede jugar y realizar todos los cambios que desee, y no tener que preocuparse por perder 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 archivoA

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 el segundo compromiso two.

git rebase --interactive HEAD~2

Esto muestra un mensaje similar a este:

pick 2b613bc two
pick bfb8e46 three

Cambie el primero picka an epara editar esa confirmación.

git reset HEAD~

git diffnos muestra que acabamos de cancelar la confirmación que hicimos para la segunda confirmación:

diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two

Preparemos 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 ejecutaríamos git rebase --continue, porque normalmente solo queremos volver a nuestra pila de confirmaciones para editar una confirmación anterior. Pero esta vez queremos crear una nueva confirmación. Así que 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, threeasí que resolvámoslo:

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 -pse ve así:

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
Rose Perrone avatar Jul 07 '2013 21:07 Rose Perrone