Comment modifier l'historique de git pour corriger une adresse email / un nom incorrect [fermé]

76

Quand j'ai commencé à utiliser git, je viens de faire un git initappel addet j'ai commencé à appeler commit. Maintenant, je commence à faire attention et je peux voir que mes commits apparaissent cowens@localmachineplutôt que l'adresse que je veux. Il semble que ce soit paramétrant GIT_AUTHOR_EMAILet GIT_COMMITTER_EMAILque je fasse ce que je veux, mais j'ai toujours ces anciens commits avec une adresse email / un nom incorrect. Comment puis-je corriger les anciens commits?

Chas. Owens
la source
4
Pour nos futurs lecteurs: gitIl est préférable de poser des questions sur l'utilisation à des fins similaires à Stack Overflow .
Michael Hampton
Voici la question la plus proche sur stackoverflow.com.
naught101

Réponses:

82

Vous pouvez revenir en arrière et corriger tous vos commits avec un seul appel à git filter-branch. Cela a le même effet que rebase, mais vous n'avez besoin que d'une seule commande pour corriger tout votre historique, au lieu de corriger chaque commit individuellement.

Vous pouvez corriger tous les mauvais emails avec cette commande:

git filter-branch --env-filter '
    oldname="(old name)"
    oldemail="(old email)"
    newname="(new name)"
    newemail="(new email)"
    [ "$GIT_AUTHOR_EMAIL"="$oldemail" ] && GIT_AUTHOR_EMAIL="$newemail"
    [ "$GIT_COMMITTER_EMAIL"="$oldemail" ] && GIT_COMMITTER_EMAIL="$newemail"
    [ "$GIT_AUTHOR_NAME"="$oldname" ] && GIT_AUTHOR_NAME="$newname"
    [ "$GIT_COMMITTER_NAME"="$oldname" ] && GIT_COMMITTER_NAME="$newname"
    ' HEAD

Plus d'informations sont disponibles dans la documentation de git

Andy
la source
11
Eh bien, exportation GIT_AUTHOR_EMAIL = "[email protected]" de git filter-branch '; GIT_AUTHOR_NAME = "Foo"' est beaucoup plus simple, merci. Ce serait la réponse acceptée si je pouvais le changer (il semble y avoir un bogue avec Server Fault).
Chas. Owens
7
Notez que les lignes d'exportation ne doivent PAS comporter d'espaces de part et d'autre du signe égal. C'est-à-dire qu'ils devraient ressembler à ceci: export GIT_AUTHOR_EMAIL = "(email correct)";
Andy Balaam
1
Maintenant, comment pourrais-je faire cela sous Windows?
Carsten Schmitz
2
@Deckard: enregistrez le script dans un fichier texte tel que fixcommits.sh, puis exécutez Git Bash et exécutez le script. J'ai mis le fichier de script à la racine de mon dépôt, puis j'ai navigué dans ce dossier dans Git Bash, puis j'ai exécuté le script avec ./fixcommits.sh
Avalanchis
2
Addendum 1 Ce format de commande ne fonctionnait pas pour moi, mais si / alors le faisait:if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; then GIT_AUTHOR_EMAIL="$newemail"; fi
Josh M.
28

La commande filter-branch de Git est puissante, mais elle est terriblement difficile à utiliser pour tout ce qui n'est pas trivial, comme par exemple si vous avez plus d'un auteur à corriger.

Voici une alternative que j'ai trouvée utile, qui utilise la fonctionnalité .mailmap décrite dans la page de manuel git-shortlog. Cela fournit un mécanisme de correspondance des auteurs que nous pouvons utiliser avec la fonction de formatage de git log. Nous pouvons l'utiliser pour générer les commandes permettant de sélectionner et de modifier une séquence nommée de commits.

Par exemple, supposons que vous souhaitiez corriger la paternité d'une branche $ BRANCH, à partir du commit $ START.

Vous devez créer un fichier .mailmap dans le répertoire supérieur de votre référentiel, qui mappe les noms d’auteurs existants sur les noms corrects. Vous pouvez obtenir une liste des noms d’auteurs existants avec:

git shortlog -se

Vous devez vous retrouver avec un fichier .mailmap comme ceci (par exemple):

You <[email protected]>   cowens@localmachine
You <[email protected]>   root@localmachine

Vous pouvez maintenant utiliser la fonctionnalité de formatage de git log pour générer les commandes permettant de réécrire $ BRANCH en tant que $ BRANCH2.

git checkout -b $BRANCH2 $START
git log --reverse --pretty=format:"cherry-pick %H; commit --amend --author='%aN <%aE>' -C %H" $START..$BRANCH | sh - 

La première commande crée une nouvelle branche vide issue du commit $ START. Pour chaque commit entre $ START et ensuite fin de $ BRANCH, la deuxième commande sélectionne le commit d'origine à la fin de la branche actuelle $ BRANCH2 et le modifie pour définir l'auteur correctement.

Ceci est aussi généralement applicable - mettez ceci dans votre ~ / .gitconfig:

[alias]
    # git reauthor $START..$END
    reauthor = !sh -c 'eval `git log --reverse --topo-order --pretty=format:\"git cherry-pick %H &&  git commit --amend -C %H --author=\\\"%aN <%aE>\\\" && \" $0 ` "echo success" '

Donc, lorsque vous avez besoin de corriger les auteurs, vous devez maintenant générer un fichier .map et faire:

git checkout -b $BRANCH2 $START
git reauthor $START..$BRANCH

La référence de branche d'origine peut être réaffectée à la nouvelle, et la nouvelle supprimée:

git checkout $BRANCH
git reset --hard $BRANCH2 # be careful with this command
git branch -d $BRANCH2
wu-lee
la source
C'est génial. Je vous remercierais si j'avais plus de représentant. Merci :)
pistache
9

Combinaison de la réponse de Comment résoudre la métainformation lors du premier commit dans git?

### Fix the first commit ###    
# create a temporary tag for the root-most commit so we can reference it
git tag root `git rev-list HEAD | tail -1`
# check it out on its own temporary branch
git checkout -b new-root root
# amend the commit
git commit --amend --author "Foo [email protected]"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# now you've changed the commit message, so checkout the original branch again
git checkout @{-1}
# and rebase it onto your new root commit
git rebase --onto new-root root
### Fix the rest of the commits ###
git rebase -i root
# edit the file to read "edit <commit number> for each entry
# amend the commit
git commit --amend --author "Foo [email protected]"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# move to the next commit
git rebase --continue    
# continue running the last two commands until you see
# Successfully rebased and updated refs/heads/master.
### Clean up ###
# nuke the temporary branch we created
git branch -d new-root
# nuke the temporary tag we created
git tag -d root
Chas. Owens
la source
M'a mis sur la bonne voie, mais avait besoin de la commande de: stackoverflow.com/a/28536828/307 au lieu de
Brett Veenstra
5

Pour suivre la réponse de jedberg: Vous pouvez utiliser rebase -iet choisir d’éditer les commits en question. Si vous utilisez git commit --amend --author <AUTHOR DETAILS>et puis git rebase continuevous pouvez parcourir et corriger l'historique.

Chealion
la source