Git, reescribe nombres de usuario y correos electrónicos de confirmación anteriores

170

He cometido un montón de confirmaciones para un proyecto en Github, sin embargo, me di cuenta de que no había configurado el correo electrónico y el nombre completo del confirmador en la computadora que estoy usando actualmente para hacer mis confirmaciones y, por lo tanto, el avatar y la dirección de correo electrónico de los usuarios no están allí.

¿Cómo puedo reescribir todos los correos electrónicos y nombres de usuario anteriores?

JP Silvashy
fuente
9
posible duplicado de ¿Cómo cambio el autor de un commit en git?
givanse
Experimenté esto después de cambiar la dirección de correo electrónico en mi cuenta de GitHub. Además de impulsar los cambios de código desde el repositorio git local utilizando la interfaz de línea de comando git (y no el escritorio de GitHub), también edité texto y administré archivos directamente desde el repositorio git remoto utilizando la interfaz web de GitHub. La nueva dirección de correo electrónico se propagó solo a las confirmaciones resultantes de las últimas acciones y no a las primeras.
Robert John

Respuestas:

243

Puedes agregar este alias:

git config alias.change-commits '!'"f() { VAR=\$1; OLD=\$2; NEW=\$3; shift 3; git filter-branch --env-filter \"if [[ \\\"\$\`echo \$VAR\`\\\" = '\$OLD' ]]; then export \$VAR='\$NEW'; fi\" \$@; }; f "

Para cambiar el nombre del autor:

git change-commits GIT_AUTHOR_NAME "old name" "new name"

o el correo electrónico de solo las últimas 10 confirmaciones:

git change-commits GIT_AUTHOR_EMAIL "[email protected]" "[email protected]" HEAD~10..HEAD

Alias:

change-commits="!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ \\\"$`echo $VAR`\\\" = '$OLD' ]]; then export $VAR='$NEW'; fi\" \$@; }; f "

Fuente: https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig

brauliobo
fuente
13
También git change-commits GIT_COMMITTER_EMAIL "[email protected]" "[email protected]"para cambiar el correo electrónico del confirmador.
Laurent
19
fijo para "eval: [[: no encontrado" en ubuntu y añadir una confirmanchange-commits = "!f() { VAR1=$1; VAR='$'$1; OLD=$2; NEW=$3; echo \"Are you sure for replace $VAR $OLD => $NEW ?(Y/N)\";read OK;if [ \"$OK\" = 'Y' ] ; then shift 3; git filter-branch --env-filter \"if [ \\\"${VAR}\\\" = '$OLD' ]; then export $VAR1='$NEW';echo 'to $NEW'; fi\" $@; fi;}; f "
qxo
9
git: 'change-commits' no es un comando git. Ver 'git --help'. Significa que no ha agregado el alias a su configuración de git. por ejemplo, git config -e
Wayne
2
Esto solo hizo duplicados de todas las confirmaciones con el correo electrónico que quería cambiar. No parece reescribir el historial. La solución de @Olivier Verdier funcionó para mí.
Jake Wilson el
66
Hacerlo dos veces seguidas con diferentes entradas conduce a:Cannot create a new backup. A previous backup already exists in refs/original/
theonlygusti
98

Mira aquí :

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD
Olivier Verdier
fuente
44
¿No cambiaría esto el nombre del autor para todos los commits (historial completo) de la rama?
hasen
2
Sí, eso cambiaría todas las confirmaciones a la información del nuevo autor.
ewall
9
Marque las preguntas como duplicados en lugar de copiar y pegar la respuesta.
givanse
2
¿Qué pasa si no especifiqué un nombre antiguo o un correo electrónico antiguo? git dice "identidad vacía <> no permitida"
Griffan
Ejecuté este comando y ahora mi repositorio no empujará ni extraerá del servidor git.
Jesús H
46

Si ya ha enviado algunas de sus confirmaciones al repositorio público, no desea hacer esto, o podría hacer una versión alternativa del historial del maestro que otros podrían haber utilizado. "No cruces las corrientes ... Sería malo ..."

Dicho esto, si son solo las confirmaciones que ha realizado en su repositorio local, entonces corrija esto antes de pasar al servidor. Puede usar el git filter-branchcomando con la --commit-filteropción, por lo que solo edita confirmaciones que coinciden con su información incorrecta, como esta:

git filter-branch --commit-filter '
      if [ "$GIT_AUTHOR_EMAIL" = "wrong_email@wrong_host.local" ];
      then
              GIT_AUTHOR_NAME="Your Name Here (In Lights)";
              GIT_AUTHOR_EMAIL="correct_email@correct_host.com";
              git commit-tree "$@";
      else
              git commit-tree "$@";
      fi' HEAD
ewall
fuente
55
Esto funciona perfecto, mientras que la respuesta marcada en verde no lo hizo
jmary 12/1218
Después, es posible que desee borrar la copia de seguridad con git update-ref -d refs/original/refs/heads/master, consulte < stackoverflow.com/a/7654880/333403 >.
cknoll
FYI: si tiene varios nombres / correos electrónicos incorrectos, es posible que deba ejecutar esto varias veces. Si eso sucede, se lamentará con este error: A previous backup already exists in refs/original/en ese caso, vuelva a ejecutarlo con el nuevo correo electrónico y agregue un -fantes del --commit-filter. Úselo a su propia discreción. Por -flo general, es algo peligroso hacer sin saber lo que está haciendo.
Chuck
19

Después de aplicar la respuesta de Olivier Verdier:

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD

... para impulsar el historial cambiado en el uso del repositorio original:

git push origin +yourbranch

El comando anterior (tenga en cuenta el signo más) obliga a reescribir el historial en el repositorio original también. Usar con precaución!

sarusso
fuente
Funcionó para mí, también reescribió correctamente la historia sobre el origen.
Xeverous
10
Esto reescribirá TODOS los commits, independientemente de quién sea el autor. Usar con precaución.
Bhavin Doshi
14

https://help.github.com/articles/changing-author-info/

#!/bin/sh

git filter-branch --env-filter '

OLD_EMAIL="[email protected]"
CORRECT_NAME="yourName"
CORRECT_EMAIL="yourEmail"

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

Esto funcionó totalmente para mí. Después de git push, asegúrese de ver la actualización en el portal web de git. Si el compromiso aún no estaba vinculado a mi cuenta, se mostraba una imagen en miniatura predeterminada al lado del compromiso y no se reflejaba en el gráfico de la línea de tiempo de mis contribuciones, vaya a la url de compromiso y agregue .patch al final de la url, y verifique el nombre y el correo electrónico son correctos.

Jacccck
fuente
Si bien esto puede responder teóricamente la pregunta, sería preferible incluir aquí las partes esenciales de la respuesta y proporcionar el enlace para referencia.
jhpratt
1
Este es el único que reescribe todas las ramas.
Bruno Zell
6

Para aquellos que solo quieren la versión fácil de copiar y pegar (además de actualizar los correos electrónicos y los nombres):

git config alias.change-commits '!'"f() { VAR=\$1; OLD=\$2; NEW=\$3; shift 3; git filter-branch --env-filter \"if [[ \\\"\$\`echo \$VAR\`\\\" = '\$OLD' ]]; then export \$VAR='\$NEW'; fi\" \$@; }; f "
git change-commits GIT_AUTHOR_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_AUTHOR_EMAIL <[email protected]> <[email protected]> -f
git change-commits GIT_COMMITTER_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_COMMITTER_EMAIL <[email protected]> <[email protected]> -f
Nick Kuznia
fuente
55
-bash:! f: evento no encontrado
Saiyine
Lo más probable es que haya un problema con una terminal que se escapa automáticamente
Andrei Savin el
3

Teniendo en cuenta el uso de nogit-filter-branch es deseable , hacer lo mismo en git-filter-repo (es posible que deba instalarlo primero con pip install git-filter-repo):

git-filter-repo --name-callback 'return name.replace(b"OldName", b"NewName")' --email-callback 'return email.replace(b"[email protected]", b"[email protected]")'

Si el repositorio es original, sin control remoto, deberá agregarlo --forcepara forzar la reescritura. (Es posible que desee crear una copia de seguridad de su repositorio antes de hacer esto).

Si no desea conservar las referencias (se mostrarán en el historial de ramas de la GUI de Git), deberá agregarlas --replace-refs delete-no-add.

Para obtener funciones más avanzadas, consulte "Filtrado de nombres y correos electrónicos" .

PS robado y mejorado de https://stackoverflow.com/a/59591928/714907 .

Pugsley
fuente