Wie bearbeite ich den Git-Verlauf, um eine falsche E-Mail-Adresse / einen falschen Namen zu korrigieren?

76

Als ich anfing, Git zu benutzen, habe ich gerade ein gemacht git initund angefangen, addund zu rufen commit. Jetzt fange ich an, aufmerksam zu sein, und ich kann sehen, dass meine Commits als cowens@localmachineund nicht als die von mir gewünschte Adresse angezeigt werden. Es sieht so aus, als würde ich einstellen GIT_AUTHOR_EMAILund GIT_COMMITTER_EMAILtun, was ich will, aber ich habe immer noch die alten Commits mit der falschen E-Mail-Adresse / dem falschen Namen. Wie kann ich die alten Commits korrigieren?

Chas. Owens
quelle
4
Für unsere zukünftigen Leser: Fragen zur Verwendung gitfür ähnliche Zwecke werden bei Stack Overflow besser gestellt .
Michael Hampton
Hier ist die nächste Frage auf stackoverflow.com.
Naught101

Antworten:

82

Sie können alle Festschreibungen mit einem einzigen Aufruf von git filter-branch korrigieren. Dies hat den gleichen Effekt wie Rebase, aber Sie müssen nur einen Befehl ausführen, um Ihren gesamten Verlauf zu korrigieren, anstatt jedes Commit einzeln zu korrigieren.

Sie können alle falschen E-Mails mit diesem Befehl reparieren:

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

Weitere Informationen finden Sie in den Git-Dokumenten

Andy
quelle
11
Nun, Git-Filter-Zweig - Env-Filter 'Export GIT_AUTHOR_EMAIL = "[email protected]"; GIT_AUTHOR_NAME = "Foo"' ist viel einfacher, danke. Dies wäre die akzeptierte Antwort, wenn ich sie ändern könnte (es sieht so aus, als ob ein Fehler mit dem Serverfehler vorliegt).
Chas. Owens
7
Beachten Sie, dass die Exportzeilen auf beiden Seiten des Gleichheitszeichens KEINE Leerzeichen enthalten dürfen. Dh sie sollten so aussehen: export GIT_AUTHOR_EMAIL = "(richtige E-Mail)";
Andy Balaam
1
Wie würde ich das unter Windows machen?
Carsten Schmitz
2
@Deckard: Speichern Sie das Skript in einer Textdatei wie fixcommits.sh, führen Sie dann Git Bash aus und führen Sie das Skript aus. Ich habe die Skriptdatei im Stammverzeichnis meines Repos abgelegt, dann zu diesem Ordner in Git Bash navigiert und dann das Skript mit ./fixcommits.sh
Avalanchis am
2
Anhang 1 Dieses Befehlsformat hat bei mir nicht funktioniert, aber wenn / dann:if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; then GIT_AUTHOR_EMAIL="$newemail"; fi
Josh M.
28

Gits filter-branch Befehl ist mächtig, aber es ist schrecklich unhandlich, ihn für etwas Nicht-Triviales zu verwenden, wie zum Beispiel, wenn Sie mehr als einen Autor zur Korrektur haben.

Hier ist eine Alternative, die ich nützlich fand und die die .mailmap-Funktion verwendet, die in der git-shortlog-Manpage beschrieben ist. Dies bietet einen Autoren-Zuordnungsmechanismus, den wir mit der Formatierungsfunktion von git log verwenden können. Wir können es verwenden, um die Befehle zu generieren, um eine benannte Folge von Commits auszuwählen und zu ändern.

Angenommen, Sie möchten die Urheberschaft für einen Zweig $ BRANCH korrigieren, beginnend mit einem Commit $ START.

Sie müssen eine .mailmap-Datei im obersten Verzeichnis Ihres Repositorys erstellen, die die vorhandenen Verfassernamen den richtigen zuordnet. Sie können eine Liste der vorhandenen Autorennamen erhalten mit:

git shortlog -se

Sie müssen am Ende eine .mailmap-Datei wie diese haben (sagen wir):

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

Jetzt können Sie die Formatierungsfunktion von git log verwenden, um die Befehle zum Umschreiben von $ BRANCH in $ BRANCH2 zu generieren.

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

Der erste Befehl erstellt einen neuen leeren Zweig, der aus dem Commit $ START hervorgeht. Bei jedem Festschreiben zwischen $ START und dann dem Ende von $ BRANCH übernimmt der zweite Befehl cherry das ursprüngliche Festschreiben bis zum Ende des aktuellen Zweigs $ BRANCH2 und ändert es, um den Autor korrekt festzulegen.

Dies gilt auch allgemein - fügen Sie dies in Ihre ~ / .gitconfig ein:

[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" '

Wenn Sie also Autoren korrigieren müssen, müssen Sie jetzt nur noch eine .map-Datei generieren und Folgendes tun:

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

Die ursprüngliche Zweigreferenz kann der neuen zugewiesen und die neue gelöscht werden:

git checkout $BRANCH
git reset --hard $BRANCH2 # be careful with this command
git branch -d $BRANCH2
Wu-Lee
quelle
Das ist fantastisch. Ich würde dich belohnen, wenn ich mehr Repräsentanten hätte. Danke :)
Pistache
9

Kombinieren der Antwort von Wie behebe ich die Metainformation beim ersten Commit in 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
quelle
Ich war auf dem richtigen Weg, brauchte aber den Befehl von: stackoverflow.com/a/28536828/307 anstelle von --author usage
Brett Veenstra
5

Um jedbergs Antwort zu folgen: Sie können die rebase -ifraglichen Commits verwenden und bearbeiten. Wenn Sie git commit --amend --author <AUTHOR DETAILS>und verwenden git rebase continue, können Sie den Verlauf durchgehen und korrigieren.

Chealion
quelle