Comment modifier plusieurs commits dans Git pour changer d'auteur

180

J'ai fait une série de commits dans Git et je me rends compte maintenant que j'ai oublié de définir correctement mon nom d'utilisateur et mes propriétés de messagerie utilisateur (nouvelle machine). Je n'ai pas encore poussé ces commits dans mon référentiel, alors comment puis-je corriger ces commits avant de le faire (seulement les 3 derniers commits sur la branche master)?

J'ai regardé git resetet git commit -C <id> --reset-author, mais je ne pense pas que je suis sur la bonne voie.

Pauldoo
la source
1
Une autre raison pour laquelle vous voudrez peut-être modifier la propriété de messagerie est cette erreur github: remote: error: GH007: Your push would publish a private email address.... `! [distant rejeté] maître -> maître (push refusé en raison de restrictions de confidentialité des e-mails) `.
craq
Voir également stackoverflow.com/q/750172/1340631 .
scai

Réponses:

232

Rebase / modifier semble inefficace, lorsque vous avez la puissance de la branche de filtre à portée de main:

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

(divisé entre les lignes pour plus de clarté, mais pas nécessaire)

Assurez-vous d'inspecter le résultat lorsque vous avez terminé, pour vous assurer que vous n'avez rien changé à votre intention!

Cascabel
la source
l'esprit d'expliquer cela un peu plus? Je ne sais pas quelle branche de filtre est
max pleaner
1
@maxpleaner git filter-branch --helpest assez simple :)
alediaferia
3
voir aussi help.github.com/articles/changing-author-info , qui s'ajoute également --tag-name-filter catau filter-branchpour migrer les balises vers le nouvel historique. Il utilise également --branches --tagsau lieu de --all, qui ne réécrit que l'historique des branches et des balises et laisse les autres refsseuls (bien que cela ne fasse probablement pas beaucoup de différence à moins que vous ne l'utilisiez, par exemple git-notes)
Tobias Kienzler
12
pour effectuer cela uniquement sur les deux derniers commits, j'ai remplacé -- --allparHEAD~1..HEAD
nmz787
1
@ nmz787 Combien de journaux sont affichés si vous le faites git log HEAD~2..HEAD?
Jona
148

L'approche de rebase interactif est assez agréable lorsqu'elle est utilisée en conjonction avec exec. Vous pouvez exécuter n'importe quelle commande shell contre un commit spécifique ou tous les commits dans le rebase.

Définissez d'abord vos paramètres d'auteur git

git config --global user.name "John Doe"
git config --global user.email [email protected]

Ensuite, pour réinitialiser l'auteur pour tous les commits après le SHA donné

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

Cela fera apparaître votre éditeur pour confirmer les modifications. Tout ce que vous avez à faire ici est de sauvegarder et de quitter et il passera par chaque commit et exécutera la commande spécifiée dans l'indicateur -x.

Selon le commentaire de @ Dave ci-dessous, vous pouvez également changer l'auteur tout en conservant les horodatages d'origine avec:

git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <[email protected]>' -CHEAD"
Alex
la source
3
Merci de m'avoir présenté l'option -x. C'est assez génial! pour l'option -i, j'ai utilisé HEAD ~ 4 pour corriger mon adresse e-mail sur mes 4 derniers commits. a fonctionné comme un charme.
Brad Hein
2
C'est beaucoup plus simple que filter-branchsi vous voulez juste corriger vos derniers commits :). Notez cependant que cela modifie l'horodatage des validations.
luator
24
Pour changer l'auteur mais conserver les horodatages d'origine, utilisezgit rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <[email protected]>' -CHEAD"
Dave
2
@Connor a git logégalement montré l'ancienne paternité pour moi, mais le statut de git identifiait correctement les nouveaux commits et après une poussée forcée, ils étaient comme je l'avais prévu.
Dan M.
6
Pour rebaser tous les commits, y compris la racine, utilisez: git rebase -i --root …au lieu de passer un SHA.
gfullam
80

Pour changer l'auteur uniquement pour le dernier commit:

git commit --amend --author 'Author Name <[email protected]>' --no-edit

Supposons que vous souhaitiez uniquement modifier l'auteur des N derniers validations:

git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <[email protected]>' --no-edit"

REMARQUES

  • le --no-editdrapeau s'assure que le git commit --amendne demande pas de confirmation supplémentaire
  • lorsque vous utilisez git rebase -i, vous pouvez sélectionner manuellement les commits où changer l'auteur,

le fichier que vous éditez ressemblera à ceci:

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
la source
1
pour tous les commits depuis root. git rebase -i --root UPTO_COMMIT_SHA -x "git commit --amend --author 'NEW_CHANGE' --no-edit"
Ashish Negi
1
Je recommande d'ajouter --rebase-mergesune -roption (courte ), pour garder la topologie de votre branche intacte si elle contient des fusions.
donquixote le
4

Cette méthode a été documentée par github dans ce but précis. Les étapes sont:

  1. Ouvrez le terminal et créez un clone nu de votre dépôt
git clone --bare https://github.com/user/repo.git
cd repo
  1. Modifier le script suivant ( en remplacement OLD_EMAIL, CORRECT_EMAILet 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. Copiez / collez le script dans votre terminal et appuyez sur Entrée pour l'exécuter.
  2. Poussez vos changements avec git push --force --tags origin 'refs/heads/*'et vous avez terminé!
stevec
la source
J'ai suivi les mêmes instructions sur GitHub que vous avez référencées, et GitHub regarde maintenant. Cependant, je suis un newb Git et je ne sais pas comment synchroniser mon dépôt local après cela. Lorsque je tire, j'obtiens la même erreur "Refuser de fusionner des histoires non liées" mentionnée dans une autre réponse. Je pense que j'ai besoin de me rebasquer contre cette nouvelle histoire de commit, mais j'apprécierais beaucoup des étapes plus spécifiques.
énigment
@enigment si vous êtes satisfait du dépôt tel qu'il est sur github, vous pouvez supprimer (ou peut-être déplacer vers un autre emplacement) le dossier que vous avez localement et simplement cloner depuis github
stevec
Merci, je sais, mais cela ne semble pas être la manière idiomatique de GitHub / Git.
énigment
0

Si vous ne vous sentez pas en sécurité à propos de l'avilissement et de la modification, vous pouvez le faire de cette façon. En même temps, vous définiriez également la configuration globale que vous vouliez probablement faire de toute façon.

git reset HEAD~ (annuler le dernier commit)

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

git config --global user.email [email protected]

git commit -m "message"

Edison
la source