Pregunta ¿Cómo modificar una confirmación especificada en git?


Por lo general, presento una lista de confirmaciones para su revisión. Si tengo:

  • HEAD 
  • Commit3 
  • Commit2 
  • Commit1

Sé que puedo modificar el compromiso de la cabeza con git commit --amend, pero ¿cómo puedo modificar Commit1, dado que no es el HEAD ¿cometer?


1700
2017-07-27 05:19


origen


Respuestas:


Puede usar git rebase, por ejemplo, si desea modificar de nuevo para confirmar bbc643cd, correr

$ git rebase --interactive 'bbc643cd^'

En el editor predeterminado, modificar pick a edit en la línea cuya confirmación quieres modificar Realice sus cambios y luego confírmelos con el mismo mensaje que tenía antes:

$ git commit --all --amend --no-edit

para modificar la confirmación, y después de eso

$ git rebase --continue

para volver al compromiso de la cabeza anterior.

ADVERTENCIA: Tenga en cuenta que esto cambiará el SHA-1 de ese compromiso así como a todos los niños - en otras palabras, esto reescribe la historia desde ese punto en adelante. Puede romper repos haciendo esto si empujas usando el comando git push --force


2232
2017-07-27 05:28



Usa la increíble rebase interactiva:

git rebase -i @~9   # Show the last 9 commits in a text editor

Encuentra el compromiso que deseas, cambia pick a e (edit), y guarda y cierra el archivo. Git rebobinará a ese compromiso, lo que le permite:

  • utilizar git commit --amend para hacer cambios, o
  • utilizar git reset @~ descartar el último compromiso, pero no los cambios en los archivos (es decir, llevarlo al punto en el que estaba cuando editó los archivos, pero aún no se había comprometido).

Este último es útil para hacer cosas más complejas como dividir en múltiples commits.

Entonces corre git rebase --continue, y Git reproducirá los cambios posteriores sobre la confirmación modificada. Se le puede pedir que solucione algunos conflictos de fusión.

Nota: @ es una abreviatura de HEADy ~ es la confirmación antes de la confirmación especificada.

Leer más sobre reescribiendo la historia en los documentos de Git.


No tengas miedo de rebase

ProTip: no tengas miedo de experimentar con comandos "peligrosos" que reescriban el historial * - Git no borra tus commits por 90 días por defecto; puedes encontrarlos en el reflog:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Cuidado con opciones como --hard y --force sin embargo, pueden descartar datos.
* Además, no reescriba el historial en ninguna de las sucursales en las que está colaborando.



En muchos sistemas, git rebase -i abrirá Vim por defecto. Vim no funciona como la mayoría de los editores de texto modernos, así que eche un vistazo a cómo volver a establecer la base usando Vim. Si prefiere usar un editor diferente, cámbielo por git config --global core.editor your-favorite-text-editor.


304
2018-04-29 17:50



Interactivo rebase con --autosquash es algo que uso con frecuencia cuando necesito corregir compromisos previos más profundos en la historia. En esencia, acelera el proceso que ilustra la respuesta de ZelluX, y es especialmente útil cuando tienes más de una confirmación que necesitas editar.

De la documentación:

--autosquash

Cuando el mensaje de registro de compromiso comienza con "squash! ..." (o "fixup! ..."), y hay un commit cuyo título comienza con el mismo ..., modifica automáticamente la lista de tareas pendientes de rebase -i para que el commit marcado para aplastar viene justo después del compromiso de ser modificado

Supongamos que tiene un historial que se ve así:

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

y tiene cambios que desea modificar a Commit2 y luego comprometer sus cambios usando

$ git commit -m "fixup! Commit2"

alternativamente puede usar el commit-sha en lugar del mensaje de confirmación, por lo que "fixup! e8adec4 o incluso solo un prefijo del mensaje de confirmación.

A continuación, inicie una rebase interactiva en la confirmación antes

$ git rebase e8adec4^ -i --autosquash

su editor se abrirá con los commits ya ordenados correctamente

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

todo lo que tienes que hacer es guardar y salir


57
2017-09-29 17:59



Correr:

$ git rebase --interactive commit_hash^

cada ^ indica la cantidad de confirmaciones que desea editar, si es solo una (el hash de confirmación que especificó), entonces simplemente agrega una ^.

Al usar Vim cambias las palabras pick a reword para las confirmaciones que desea cambiar, guardar y salir (:wq) Luego, git le preguntará con cada confirmación que marcó como nueva palabra para que pueda cambiar el mensaje de confirmación.

Cada mensaje de compromiso que debe guardar y salir (:wq) para ir al siguiente mensaje de confirmación

Si desea salir sin aplicar los cambios, presione :q!

EDITAR: navegar en vim tu usas j subir, k bajar, h ir a la izquierda, y l ir a la derecha (todo esto en NORMAL modo, presionar ESC ir a NORMAL modo ). Para editar un texto, presione i para que ingreses INSERT modo, donde insertas el texto. prensa ESC para volver a NORMAL modo :)

ACTUALIZAR: Aquí hay un excelente enlace de la lista de github Cómo deshacer (casi) cualquier cosa con git 


30
2017-07-02 19:11



Si por algún motivo no le gustan los editores interactivos, puede usar git rebase --onto.

Digamos que quiere modificar Commit1. Primero, rama de antes de  Commit1:

git checkout -b amending [commit before Commit1]

Segundo, agarrar Commit1 con cherry-pick:

git cherry-pick Commit1

Ahora, modifique sus cambios, creando Commit1':

git add ...
git commit --amend -m "new message for Commit1"

Y finalmente, después de haber ocultado cualquier otro cambio, transplante el resto de sus compromisos hasta master encima de tu nuevo compromiso:

git rebase --onto amending Commit1 master

Leído: "rebase, en la rama amending, todo se compromete entre Commit1 (no inclusivo) y master (inclusive) ". Es decir, Commit2 y Commit3, eliminando por completo el viejo Commit1. Podrías elegirlos, pero de esta manera es más fácil.

¡Recuerda limpiar tus ramas!

git branch -d amending

12
2017-10-22 12:19



Llegó a este enfoque (y es probablemente lo mismo que usar una base de datos interactiva), pero para mí es bastante sencillo.

Nota: Presento este enfoque con el fin de ilustrar lo que puede hacer en lugar de una alternativa cotidiana. Dado que tiene muchos pasos (y posiblemente algunas advertencias).

Digamos que quieres cambiar cometer 0 y usted está actualmente en feature-branch

some-commit---0---1---2---(feature-branch)HEAD

Finalice la compra de este compromiso y cree un quick-branch. También puede clonar su rama de características como un punto de recuperación (antes de comenzar).

?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch

Ahora tendrá algo como esto:

0(quick-branch)HEAD---1---2---(feature-branch)

Cambios de escenario, guardan todo lo demás.

git add ./example.txt
git stash

Confirmar cambios y pagar de nuevo a feature-branch

git commit --amend
git checkout feature-branch

Ahora tendrá algo como esto:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

Rebase feature-branch sobre quick-branch (resolver cualquier conflicto en el camino). Aplicar escondite y eliminar quick-branch.

git rebase quick-branch
git stash pop
git branch -D quick-branch

Y terminas con:

some-commit---0'---1'---2'---HEAD(feature-branch)

Git no duplicará (aunque no puedo decir en qué medida) el 0 se compromete al volver a basar.

Nota: todos los hashes de confirmación se cambian comenzando desde el compromiso que originalmente intentamos cambiar.


6
2018-06-01 11:57



Para obtener un comando no interactivo, coloque un script con este contenido en su RUTA:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

Úselo organizando sus cambios (con git add) y luego corre git fixup <commit-to-modify>. Por supuesto, seguirá siendo interactivo si tienes conflictos.


4
2018-01-16 15:27