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.

pauldoo
fuente
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
Consulte también stackoverflow.com/q/750172/1340631 .
Scai

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!

Cascabel
fuente
¿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 [email protected]

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 <[email protected]>' -CHEAD"
Alex
fuente
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 <[email protected]>' -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 <[email protected]>' --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 <[email protected]>' --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 <[email protected]>' --no-edit
pick dc18f70 bugfix
Chris Maes
fuente
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="[email protected]"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="[email protected]"
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!
stevec
fuente
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 [email protected]

git commit -m "message"

Edison
fuente