Git, réécrire les noms d'utilisateur et e-mails de commit précédents

170

J'ai engagé un tas de commits dans un projet sur Github, mais j'ai réalisé que je n'avais pas configuré le bon email et le nom complet du commetteur sur l'ordinateur que j'utilise actuellement pour faire mes commits et donc l'avatar et l'adresse e-mail des utilisateurs ne sont pas là.

Comment puis-je réécrire tous les e-mails et noms d'utilisateur de commit passés?

JP Silvashy
la source
9
duplicata possible de Comment changer l'auteur d'un commit dans git?
givanse le
J'ai vécu cela après avoir changé l'adresse e-mail de mon compte GitHub. En plus de pousser les modifications de code à partir du dépôt git local à l'aide de l'interface de ligne de commande git (et non du bureau GitHub), j'ai également modifié du texte et géré des fichiers directement à partir du dépôt git distant à l'aide de l'interface Web GitHub. La nouvelle adresse e-mail s'est propagée uniquement aux commits résultant des dernières actions et non de la première.
Robert John

Réponses:

244

Vous pouvez ajouter cet 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 "

Pour changer le nom de l'auteur:

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

ou l'email des 10 derniers commits seulement:

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 "

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

brauliobo
la source
13
Également git change-commits GIT_COMMITTER_EMAIL "[email protected]" "[email protected]"pour changer l'email du committer.
laurent
20
corrigé pour "eval: [[: not found" sur ubuntu et ajout d'une confirmationchange-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' n'est pas une commande git. Voir 'git --help'. Cela signifie que vous n'avez pas ajouté l'alias à votre configuration git. eg git config -e
Wayne
3
Cela a juste fait des doublons de tous les commits avec l'e-mail que je voulais changer. Ne semble pas réécrire l'histoire. La solution de @Olivier Verdier a fonctionné pour moi.
Jake Wilson
7
Le faire deux fois de suite avec des entrées différentes conduit à:Cannot create a new backup. A previous backup already exists in refs/original/
theonlygusti
98

Voir ici :

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
la source
4
cela ne changerait-il pas le nom de l'auteur de tous les commits (historique entier) de la branche?
hasen
2
Ouais, cela changerait tous les commits avec les informations sur le nouvel auteur.
ewall
9
Veuillez marquer les questions comme des doublons au lieu de copier-coller la réponse.
givanse le
2
Et si je n'ai pas spécifié un ancien nom ou un ancien e-mail? git dit "ident vide <> non autorisé"
Griffan
J'ai exécuté cette commande et maintenant mon dépôt ne sera plus poussé ou extrait du serveur git.
Jesus H
46

Si vous avez déjà poussé certains de vos commits au dépôt public, vous ne pas vouloir faire cela, ou il serait une autre version de l'histoire du maître que d' autres ont peut - être utilisé. "Ne traversez pas les ruisseaux ... Ce serait mauvais ..."

Cela dit, s'il ne s'agit que des validations que vous avez effectuées sur votre référentiel local, corrigez-le avant de pousser vers le serveur. Vous pouvez utiliser la git filter-branchcommande avec l' --commit-filteroption, donc elle ne modifie que les commits qui correspondent à vos informations incorrectes, comme ceci:

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
la source
5
Cela fonctionne parfaitement alors que la réponse marquée en vert ne l'a pas fait
jmary
Ensuite, vous voudrez peut-être effacer la sauvegarde avec git update-ref -d refs/original/refs/heads/master, voir < stackoverflow.com/a/7654880/333403 >.
cknoll
FYI: Si vous avez plusieurs noms / e-mails incorrects, vous devrez peut-être l'exécuter plusieurs fois. Si cela se produit, il gémira avec cette erreur: A previous backup already exists in refs/original/dans ce cas, réexécutez-le, avec le nouvel e-mail, et ajoutez un -favant le --commit-filter. Utilisez à votre propre discrétion. C'est généralement -fune chose dangereuse à faire sans savoir ce que cela fait.
Chuck le
19

Après avoir appliqué la réponse d'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

... pour pousser l'historique modifié sur le référentiel d'origine, utilisez:

git push origin +yourbranch

La commande ci-dessus (notez le plus) oblige également à réécrire l'historique sur le dépôt d'origine. Utiliser avec précaution!

Sarusso
la source
A travaillé pour moi, a également réécrit correctement l'histoire sur l'origine.
Xeverous
10
Cela va réécrire TOUS les commits - quel que soit l'auteur. Utiliser avec précaution.
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

cela a totalement fonctionné pour moi. Après git push, assurez-vous de voir la mise à jour sur le portail Web de git. Si le commit n'était toujours pas lié à mon compte, afficher l'image miniature par défaut à côté du commit et qu'il n'était pas reflété sur le graphique chronologique de mes contributions, accédez à l'url de commit et ajoutez .patch à la fin de l'url, et vérifiez le nom et l'email sont corrects.

Jacccck
la source
Bien que cela puisse théoriquement répondre à la question, il serait préférable d'inclure ici les parties essentielles de la réponse et de fournir le lien pour référence.
jhpratt
1
C'est le seul à réécrire toutes les branches.
Bruno Zell le
6

Pour ceux qui veulent juste la version facile à copier-coller (à part la mise à jour des e-mails et des noms):

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
la source
5
-bash:! f: événement non trouvé
Saiyine
Très probablement un problème avec un terminal qui s'échappe automatiquement des choses
Andrei Savin
3

Considérant que l'utilisation de git-filter-branchn'est pas souhaitée , faire la même chose dans git-filter-repo (vous devrez peut-être l'installer d'abord avec 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 le référentiel est original, sans télécommande, vous devrez ajouter --forcepour forcer la réécriture. (Vous pouvez créer une sauvegarde de votre dépôt avant de faire cela.)

Si vous ne souhaitez pas conserver les références (elles seront affichées dans l'historique des branches de Git GUI), vous devrez ajouter --replace-refs delete-no-add.

Pour des fonctionnalités plus avancées, voir "Filtrage des noms et des e-mails" .

PS volé et amélioré de https://stackoverflow.com/a/59591928/714907 .

Pugsley
la source