tipos tag qué existen etiquetas crear git version-control

tag - git rebase



Cómo dividir el último commit en dos en Git (9)

Tengo dos ramas de trabajo, maestro y foro, y acabo de hacer algunas modificaciones en la rama del foro , que me gustaría seleccionar en maestro . Pero, desafortunadamente, la confirmación que quiero seleccionar también contiene algunas modificaciones que no deseo.

La solución probablemente sería eliminar de alguna manera la confirmación incorrecta y reemplazarla con dos confirmaciones separadas, una con los cambios que quiero seleccionar en master y otras que no pertenecen a ella.

He tratado de hacer

git reset --hard HEAD^

que eliminó todos los cambios, así que tuve que volver con

git reset ORIG_HEAD

Entonces, mi pregunta es, ¿cuál es la mejor manera de dividir el último compromiso en dos confirmaciones separadas?


El método de doble revertir-squash.

  1. Haz otra confirmación que elimine los cambios no deseados. (Si es por archivo, esto es realmente sencillo: git checkout HEAD~1 -- files with unwanted changes y git commit . De lo contrario, los archivos con cambios mixtos se pueden configurar parcialmente. git reset file y git add -p file como paso intermedio .) Llama a este revertir .
  2. git revert HEAD : realiza otra confirmación, que agrega los cambios no deseados. Este es el doble revertir.
  3. De los 2 envíos que hiciste, aplasta el primero sobre el compromiso de dividir ( git rebase -i HEAD~3 ). Este compromiso ahora se libera de los cambios no deseados, ya que están en el segundo compromiso.

Beneficios

  • Conserva el mensaje de confirmación.
  • Funciona incluso si el compromiso de dividir no es el último. Solo requiere que los cambios no deseados no entren en conflicto con las confirmaciones posteriores.

Metas:

  • Quiero dividir un commit anterior ( splitme ) en dos.
  • Quiero mantener el mensaje de confirmación .

Plan:

  1. Rebase interactivo desde uno antes de splitme .
  2. editar splitme .
  3. Restablecer los archivos para dividir en una segunda confirmación.
  4. Modificar la confirmación, mantener el mensaje, modificar según sea necesario.
  5. Vuelva a agregar los archivos divididos a partir de la primera confirmación.
  6. Comprometete con un nuevo mensaje.
  7. Continuar rebase.

Los pasos de rebase (1 y 7) se pueden omitir si el splitme es la confirmación más reciente.

git rebase -i splitme^ # mark splitme commit with ''e'' git reset HEAD^ -- $files git commit --amend git add $files git commit -m "commit with just some files" git rebase --continue

Si quisiera que los archivos divididos se confirmaran primero, entonces volvería a cambiar -i y cambiaría el orden

git rebase -i splitme^ # swap order of splitme and ''just some files''


Deberías usar el índice. Después de hacer un reinicio mixto (" git reset HEAD ^"), agregue el primer conjunto de cambios en el índice, luego confírmelos. Entonces cometer el resto.

Puede usar " git add " para colocar todos los cambios realizados en un archivo en el índice. Si no desea realizar todas las modificaciones realizadas en un archivo, solo algunas de ellas, puede usar "git add -p".

Veamos un ejemplo. Supongamos que tengo un archivo llamado myfile, que contiene el siguiente texto:

something something else something again

Lo modifiqué en mi última confirmación para que ahora se vea así:

1 something something else something again 2

Ahora decido que quiero dividirlo en dos, y quiero que la inserción de la primera línea esté en la primera confirmación, y que la inserción de la última línea esté en la segunda confirmación.

Primero vuelvo con el padre de HEAD, pero quiero mantener las modificaciones en el sistema de archivos, así que uso "git reset" sin argumentos (lo que hará un llamado reinicio "mixto"):

$ git reset HEAD^ myfile: locally modified $ cat myfile 1 something something else something again 2

Ahora uso "git add -p" para agregar los cambios que quiero confirmar en el índice (= los escalé). "git add -p" es una herramienta interactiva que le pregunta qué cambios en el archivo deben agregarse al índice.

$ git add -p myfile diff --git a/myfile b/myfile index 93db4cb..2f113ce 100644 --- a/myfile +++ b/myfile @@ -1,3 +1,5 @@ +1 something something else something again +2 Stage this hunk [y,n,a,d,/,s,e,?]? s # split this section into two! Split into 2 hunks. @@ -1,3 +1,4 @@ +1 something something else something again Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y # yes, I want to stage this @@ -1,3 +2,4 @@ something something else something again +2 Stage this hunk [y,n,a,d,/,K,g,e,?]? n # no, I don''t want to stage this

Entonces me comprometo este primer cambio:

$ git commit -m "Added first line" [master cef3d4e] Added first line 1 files changed, 1 insertions(+), 0 deletions(-)

Ahora puedo confirmar todos los demás cambios (a saber, el número "2" en la última línea):

$ git commit -am "Added last line" [master 5e284e6] Added last line 1 files changed, 1 insertions(+), 0 deletions(-)

Vamos a revisar el log para ver qué compromisos tenemos:

$ git log -p -n2 | cat Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8 Author: ... Date: ... Added last line Diff --git a/myfile b/myfile Index f9e1a67..2f113ce 100644 --- a/myfile +++ b/myfile @@ -2,3 +2,4 @@ something something else something again +2 Commit cef3d4e0298dd5d279a911440bb72d39410e7898 Author: ... Date: ... Added first line Diff --git a/myfile b/myfile Index 93db4cb..f9e1a67 100644 --- a/myfile +++ b/myfile @@ -1,3 +1,4 @@ +1 something something else something again


Ejecute git gui , seleccione el botón de opción "Modificar último compromiso", y deshaga los cambios (Confirmar> Desactivar etapa de confirmación o Ctrl - U ) que no desea que se realicen las primeras confirmaciones. Creo que esa es la forma más fácil de hacerlo.

Otra cosa que podrías hacer es seleccionar el cambio sin cometer cambios ( git cherry-pick -n ) y luego, manualmente o con git gui seleccionar los cambios deseados antes de cometer.


Esta podría ser otra solución dirigida a los casos en los que hay un gran compromiso y una pequeña cantidad de archivos deben trasladarse a un nuevo compromiso. Esto funcionará si se va a extraer un conjunto de <path> archivos de la última confirmación en HEAD y todos se moverán a una nueva confirmación. Si se necesitan múltiples confirmaciones, se pueden usar las otras soluciones.

Primero haga los parches en las áreas organizadas y no escalonadas que contendrían los cambios para revertir el código antes de la modificación y después de la modificación, respectivamente:

git reset HEAD^ <path> $ git status On branch <your-branch> Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: <path> Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: <path>

Para entender lo que va a pasar (la flecha y los comentarios no son parte del comando):

git diff --cached -> show staged changes to revert <path> to before HEAD git diff -> show unstaged changes to add current <path> changes

Revertir <path> cambios en la última confirmación:

git commit --amend -> reverts changes on HEAD by amending with staged changes

Crear nuevo commit con <path> cambios:

git commit -a -m "New Commit" -> adds new commit with unstaged changes

Esto tiene el efecto de crear una nueva confirmación que contiene los cambios extraídos de la última confirmación.


Me sorprende que nadie haya sugerido git cherry-pick -n forum . Esto preparará los cambios del último compromiso del forum pero no los confirmará; luego puede reset los cambios que no necesita y confirmar lo que desea mantener.


Para cambiar la confirmación actual en dos confirmaciones, puede hacer algo como lo siguiente.

Ya sea:

git reset --soft HEAD^

Esto deshace el último commit pero deja todo en escena. A continuación, puede desestabilizar ciertos archivos:

git reset -- file.file

Opcionalmente restaurar partes de esos archivos:

git add -p file.file

Haz un nuevo primer commit:

git commit

La etapa y cometer el resto de los cambios en una segunda confirmación:

git commit -a

O:

Deshacer y eliminar todas las modificaciones de la última confirmación:

git reset HEAD^

Escenario selectivo de la primera ronda de cambios:

git add -p

Cometer:

git commit

Comete el resto de los cambios:

git commit -a

(En cualquiera de los pasos, si deshizo una confirmación que agregó un nuevo archivo y desea agregarla a la segunda confirmación, tendrá que agregarla manualmente como commit -a solo etapas escalonadas a archivos ya rastreados).


Ya que estás recogiendo cerezas, puedes:

  1. cherry-pick con la --no-commit agregada.
  2. reset y use add --patch , add --edit o simplemente add a la etapa lo que desea conservar.
  3. commit los cambios por etapas.
    • Para reutilizar el mensaje de confirmación original, puede agregar las --reuse-message=<old-commit-ref> o --reedit-message=<old-commit-ref> al comando commit .
  4. Elimina los cambios sin reset --hard con reset --hard .

Otra forma, conservando o editando el mensaje de confirmación original:

  1. cherry-pick el compromiso original como normal.
  2. Invierta los cambios que no desea y use add para organizar la reversión.
    • Este paso sería fácil si está eliminando lo que agregó, pero un poco complicado si está agregando lo que eliminó o anulando un cambio.
  3. commit --amend para efectuar la reversión en el commit de cherry-recogido.
    • Recibirá nuevamente el mismo mensaje de confirmación, que puede conservar o revisar según sea necesario.

git reset HEAD^

el - duro es lo que está matando tus cambios.