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 repository local?

git rebase -i lo hará.

Para dividir su compromiso más reciente, primero:

 $ git reset HEAD~ 

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

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

 $ git rebase -i HEAD~3 

donde 3 es la cantidad de compromisos que se devuelve.

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

 $ git rebase -i 123abcd^ 

donde 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 

Del manual de git-rebase (sección SPLITTING COMMITS)

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>^ , donde <commit> es la confirmación que desea dividir. De hecho, cualquier range 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 esa confirmación, ejecute git reset HEAD^ . El efecto es que HEAD se rebobina en uno, y el índice sigue el juego. Sin embargo, el tree 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 post de compromiso apropiado ahora.

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

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

Use git rebase --interactive para editar ese commit anterior, ejecute git reset HEAD~ , y luego git add -p para agregar algunos, luego realice un commit, luego agregue algunos más y realice otro commit, tantas veces como desee. Cuando hayas terminado, ejecuta git rebase --continue , y tendrás todas las git rebase --continue split antes en tu stack.

Importante : tenga en count que puede jugar y hacer todos los cambios que desee, y no tener que preocuparse por perder los cambios anteriores, porque siempre puede ejecutar git reflog para encontrar el punto en su proyecto que contiene los cambios que desea, (llamemos es a8c4ab ), y luego git reset a8c4ab .

Aquí hay una serie de commands para mostrar cómo funciona:

mkdir git-test; cd git-test; git init

ahora agrega un file 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 file A se ve así:

 one two three 

y nuestro git log ve así (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 post que se ve así:

 pick 2b613bc two pick bfb8e46 three 

Cambie la primera pick a una e para editar esa confirmación.

git reset HEAD~

git diff nos muestra que acabamos de desglosar el compromiso 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 file A

git add .

Este suele ser el momento durante una rebase interactiva en la que ejecutamos git rebase --continue , porque normalmente solo queremos volver a la stack de confirmaciones para editar una confirmación anterior. Pero esta vez, queremos crear un nuevo compromiso. Entonces, ejecutaremos git commit -am 'two and a third' . Ahora editamos el file A y 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 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 ve así:

 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 

git rebase --interactive se puede usar para dividir un commit en commits más pequeños. Los documentos de Git en rebase tienen un recorrido conciso del process: Compromisos de split :

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>^ , donde <commit> es la confirmación que desea dividir. De hecho, cualquier range 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 esa confirmación, ejecute git reset HEAD^ . El efecto es que HEAD se rebobina en uno, y el índice sigue el juego. Sin embargo, el tree 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 post de compromiso apropiado ahora.

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

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

Si no está absolutamente seguro de que las revisiones intermedias sean consistentes (comstackn, pasan la suite de testings, etc.), debe usar git stash para save los cambios aún no confirmados después de cada confirmación, probar y modificar la confirmación si las correcciones son necesarios.

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

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

Tenga en count que también hay un git reset --soft HEAD^ . Es similar al git reset (que se pnetworkingetermina a --mixed ) pero conserva el contenido del índice. De modo que si ha agregado / eliminado files, ya los tiene en el índice.

Resulta ser muy útil en caso de compromisos gigantes.

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

Habiendo llegado al compromiso que desea dividir, utilizando rebase -i y marcándolo para edit , tiene dos opciones.

  1. Después de usar git reset HEAD~ , revise los parches individualmente usando git add -p para seleccionar los que desee en cada commit

  2. Edite la copy 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 comstackn y ejecutan correctamente como parte de la fusión. Esto procede de la siguiente manera.

Después de usar rebase -i y edit la confirmación, use

git reset --soft HEAD~

para deshacer la confirmación, pero deje los files 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 orderados o con todos ellos sin grabar.

Ahora ve y edita el código. Puedes eliminar cambios, eliminar files agregados y hacer lo que quieras para build el primer commit de la serie que estás buscando. También puedes buildlo, ejecutarlo y confirmar que tienes un set de fonts consistente.

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

git commit

Ese es el primer compromiso hecho. Ahora desea restaurar su copy 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 el git status . En las primeras líneas del estado, verá el command 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, la confirmación que estoy editando tiene sha1 65dfb6a . Sabiendo eso, puedo verificar el contenido de esa confirmación sobre mi directory de trabajo usando la forma de git checkout de git checkout que toma una location de confirmación y de file. Aquí uso . como la location del file para replace toda la copy de trabajo:

git checkout 65dfb6a .

¡No te pierdas el punto al final!

Esto verificará y organizará los files 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 split, o ir de nuevo, borrando algunas partes de la confirmación antes de hacer otra confirmación intermedia.

Si desea reutilizar el post de confirmación original para una o más confirmaciones, puede usarlo directamente desde los files 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.

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

Abra el cuadro de dialog Rebase, configúrelo y realice los siguientes pasos.

  • Haga clic con el button derecho en la confirmación que desea dividir y select " Edit " (entre selección, aplastar, eliminar …).
  • Haga clic en " Start " para iniciar la rebase.
  • Una vez que llegue al compromiso de dividir, marque el button " Edit/Split " y click " Amend " directamente. El dialog de confirmación se abre.
    Edición / Split commit
  • Deselect los files que desea colocar en una confirmación separada.
  • Edite el post de confirmación y luego click " commit ".
  • Hasta que haya files para confirmar, el dialog de confirmación se abrirá una y otra vez. Cuando no hay más files para enviar, aún le preguntará si desea agregar un compromiso más.

Muy útil, gracias TortoiseGit!

Lo más fácil de hacer sin una rebase interactiva es (probablemente) hacer una nueva twig que comience en la confirmación antes de la que desea dividir, select la confirmación, restablezca, oculte, comience a mover el file, vuelva a aplicar el alijo y confirmar los cambios, y luego fusionar con la anterior twig o seleccionar los commits siguientes. (Luego, cambie el nombre de la anterior twig a la cabecera actual.) (Probablemente sea mejor seguir el consejo de la MBO y realizar una rebase interactiva).

Creo que la mejor manera de usar git rebase -i . Creé un video para mostrar los pasos para dividir una confirmación: https://www.youtube.com/watch?v=3EzOz7e1ADI

Si tienes esto:

 A - B <- mybranch 

Donde has cometido algún contenido en commit B:

 /modules/a/file1 /modules/a/file2 /modules/b/file3 /modules/b/file4 

Pero desea dividir B en C – D, y get este resultado:

 A - C - D <-mybranch 

Puede dividir el contenido como este, por ejemplo (contenido de diferentes directorys en diferentes compromisos) …

Restablezca la twig de nuevo a la confirmación antes de la de split:

 git checkout mybranch git reset --hard A 

Crear primer compromiso (C):

 git checkout B /modules/a git add -u git commit -m "content of /modules/a" 

Crear segundo compromiso (D):

 git checkout B /modules/b git add -u git commit -m "content of /modules/b"