Cómo modificar varias confirmaciones en Git para cambiar de autor


180

He realizado una serie de confirmaciones en Git y ahora me doy cuenta de que olvidé establecer mi nombre de usuario y las propiedades de correo electrónico del usuario correctamente (máquina nueva). Todavía no he enviado estas confirmaciones a mi repositorio, entonces, ¿cómo puedo corregir estas confirmaciones antes de hacerlo (solo las 3 últimas confirmaciones en la rama maestra)?

He estado mirando git resety git commit -C <id> --reset-author, pero no creo que esté en el camino correcto.


1
Otra razón por la que es posible que desee cambiar la propiedad del correo electrónico es este error de github: remote: error: GH007: Your push would publish a private email address.... `! [remoto rechazado] maestro -> maestro (inserción rechazada debido a restricciones de privacidad del correo electrónico) `.
craq

Respuestas:


232

Rebase / enmienda parece ineficiente, cuando tiene el poder de la rama de filtro a su alcance:

git filter-branch --env-filter 'if [ "$GIT_AUTHOR_EMAIL" = "incorrect@email" ]; then
     GIT_AUTHOR_EMAIL=correct@email;
     GIT_AUTHOR_NAME="Correct Name";
     GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL;
     GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; fi' -- --all

(dividido en líneas para mayor claridad, pero no es necesario)

¡Asegúrate de inspeccionar el resultado cuando hayas terminado, para asegurarte de que no cambiaste nada que no quisiste!


¿Te importaría explicar esto un poco más? no estoy seguro de qué rama de filtro es
max pleaner

1
@maxpleaner git filter-branch --helpes bastante sencillo :)
alediaferia

3
consulte también help.github.com/articles/changing-author-info , que también se agrega --tag-name-filter cata filter-branchfin de migrar etiquetas al nuevo historial. También usa en --branches --tagslugar de --all, que solo reescribe el historial de ramas y etiquetas y deja refssolo a otros (aunque eso probablemente no haga mucha diferencia a menos que, por ejemplo, lo esté usando git-notes)
Tobias Kienzler

12
para realizar esto solo en los dos últimos commits, reemplacé -- --allconHEAD~1..HEAD
nmz787

1
@ nmz787 ¿Cuántos registros se muestran si lo hace git log HEAD~2..HEAD?
Jona

148

El enfoque de rebase interactivo es bastante bueno cuando se usa junto con exec. Puede ejecutar cualquier comando de shell contra una confirmación específica o todas las confirmaciones en el rebase.

Primero establezca la configuración de autor de git

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

Luego, para restablecer el autor para todos los commits después del SHA dado

git rebase -i YOUR_SHA -x "git commit --amend --reset-author -CHEAD"

Esto abrirá su editor para confirmar los cambios. Todo lo que necesita hacer aquí es guardar y salir y pasará por cada confirmación y ejecutará el comando especificado en el indicador -x.

Según el comentario de @ Dave a continuación, también puede cambiar el autor manteniendo las marcas de tiempo originales con:

git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"

3
Gracias por presentarme la opción -x. ¡Es increíble! para la opción -i utilicé HEAD ~ 4 para corregir mi dirección de correo electrónico en mis últimos 4 commits. trabajado como un encanto.
Brad Hein

2
Esto es mucho más simple que filter-branchsi solo quieres arreglar tus últimas confirmaciones :). Sin embargo, tenga en cuenta que esto cambia la marca de tiempo de las confirmaciones.
luator

24
Para cambiar el autor pero mantener las marcas de tiempo originales, usegit rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"
Dave

2
@Connor git logtambién mostró una antigua autoría para mí, pero el estado de git identificó correctamente los nuevos commits y después del empuje forzado fueron como yo pretendía.
Dan M.

66
Para cambiar la base de todas las confirmaciones, incluido el uso de la raíz: en git rebase -i --root …lugar de pasar un SHA.
gfullam

80

Para cambiar el autor solo para la última confirmación:

git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit

Supongamos que solo desea cambiar el autor de las últimas N confirmaciones:

git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit"

Notas

  • la --no-editbandera se asegura de git commit --amendque no pida una confirmación adicional
  • cuando lo use git rebase -i, puede seleccionar manualmente las confirmaciones donde cambiar el autor,

el archivo que edite se verá así:

pick 897fe9e simplify code a little
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick dc18f70 bugfix

1
para todos los commits desde root. git rebase -i --root UPTO_COMMIT_SHA -x "git commit --amend --author 'NEW_CHANGE' --no-edit"
Ashish Negi

1
Recomiendo agregar la opción --rebase-merges(corta -r) para mantener intacta la topología de su rama si contiene algunas fusiones.
donquixote

4

Este método fue documentado por github para este mismo propósito. Los pasos son:

  1. Abra el terminal y hacer un desnudo clon de tu repositorio
git clone --bare https://github.com/user/repo.git
cd repo
  1. Editar la siguiente secuencia de comandos (en sustitución OLD_EMAIL, CORRECT_EMAILy CORRECT_NAME)
#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
  1. Copie / pegue el script en su terminal y presione enter para ejecutarlo.
  2. ¡Empuja tus cambios git push --force --tags origin 'refs/heads/*'y listo!

Seguí las mismas instrucciones en GitHub a las que hizo referencia, y GitHub se ve ahora mismo. Sin embargo, soy un Git newb y no estoy seguro de cómo sincronizar mi repositorio local después de eso. Cuando tiro, recibo el mismo error de "negarse a fusionar historias no relacionadas" mencionado en otra respuesta. Creo que necesito refrenar contra ese nuevo historial de confirmaciones, pero agradecería mucho los pasos más específicos.
enigment

@enigment si está contento con el repositorio ya que está en github, puede eliminar (o quizás mudarse a otra ubicación) la carpeta que tiene localmente y simplemente clonar desde github
stevec

Gracias, lo sé, pero esa no parece la forma idiomática de GitHub / Git.
enigment


0

Si no se siente seguro acerca de la rebaja y la corrección, puede hacerlo de esta manera. Al mismo tiempo, también estarías configurando la configuración global, lo que probablemente querías hacer de todos modos.

git reset HEAD~ (deshacer la última confirmación)

git config --global user.name "Your Name"

git config --global user.email you@example.com

git commit -m "message"

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.