So ändern Sie mehrere Commits in Git, um den Autor zu ändern

179

Ich habe eine Reihe von Commits in Git vorgenommen und stelle jetzt fest, dass ich vergessen habe, meinen Benutzernamen und die E-Mail-Eigenschaften des Benutzers korrekt festzulegen (neuer Computer). Ich habe diese Commits noch nicht in mein Repository verschoben. Wie kann ich diese Commits korrigieren, bevor ich dies tue (nur die 3 letzten Commits im Hauptzweig)?

Ich habe nachgeschaut git resetund git commit -C <id> --reset-author, aber ich glaube nicht, dass ich auf dem richtigen Weg bin.

pauldoo
quelle
1
Ein weiterer Grund, warum Sie möglicherweise die E-Mail-Eigenschaft ändern möchten, ist dieser Github-Fehler: remote: error: GH007: Your push would publish a private email address.... `! [remote abgelehnt] master -> master (Push aufgrund von E-Mail-Datenschutzbeschränkungen abgelehnt) `.
Craq

Antworten:

230

Rebase / Amendment scheint ineffizient zu sein, wenn Sie die Kraft des Filterzweigs zur Hand haben:

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

(aus Gründen der Übersichtlichkeit über Linien aufgeteilt, aber nicht erforderlich)

Überprüfen Sie das Ergebnis, wenn Sie fertig sind, um sicherzustellen, dass Sie nichts geändert haben, was Sie nicht wollten!

Cascabel
quelle
Hast du etwas dagegen, das ein bisschen mehr zu erklären?
Ich bin
1
@ Maxpleaner git filter-branch --helpist ziemlich einfach :)
Alediaferia
2
siehe auch help.github.com/articles/changing-author-info , die auch hinzufügt , --tag-name-filter catum die filter-branchum Migrate Tags in die neue Geschichte. Es wird auch --branches --tagsanstelle von verwendet --all, wodurch nur der Zweig- und Tag-Verlauf neu geschrieben wird und andere in refsRuhe gelassen werden (obwohl dies wahrscheinlich keinen großen Unterschied macht, es sei denn, Sie verwenden z. B. git-notes)
Tobias Kienzler,
12
dies auf ausführen nur die letzten beiden Commits, ich ersetzt -- --allmitHEAD~1..HEAD
nmz787
1
@ nmz787 Wie viele Protokolle werden angezeigt, wenn Sie dies tun git log HEAD~2..HEAD?
Jona
146

Der interaktive Rebase-Ansatz ist in Verbindung mit exec sehr hilfreich. Sie können einen beliebigen Shell-Befehl für ein bestimmtes Commit oder alle Commits in der Rebase ausführen.

Stellen Sie zuerst Ihre Git-Autoreneinstellungen ein

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

Dann, um den Autor für alle Commits nach dem angegebenen SHA zurückzusetzen

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

Daraufhin wird Ihr Editor geöffnet, um die Änderungen zu bestätigen. Alles, was Sie hier tun müssen, ist Speichern und Beenden. Es wird jedes Commit durchlaufen und den im Flag -x angegebenen Befehl ausführen.

Per @ Daves Kommentar unten können Sie auch den Autor ändern, während Sie die ursprünglichen Zeitstempel beibehalten mit:

git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <[email protected]>' -CHEAD"
Alex
quelle
3
Vielen Dank, dass Sie mir die Option -x vorgestellt haben. Es ist ziemlich genial! Für die Option -i habe ich HEAD ~ 4 verwendet, um meine E-Mail-Adresse bei meinen letzten 4 Commits festzulegen. Lief wie am Schnürchen.
Brad Hein
2
Dies ist viel einfacher, als filter-branchwenn Sie nur Ihre letzten Commits korrigieren möchten :). Beachten Sie jedoch, dass dies den Zeitstempel der Commits ändert.
Luator
24
Um den Autor zu ändern, aber die ursprünglichen Zeitstempel beizubehalten, verwenden Siegit rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <[email protected]>' -CHEAD"
Dave
2
@Connor git logzeigte auch alte Autorenschaft für mich, aber der Git-Status identifizierte neue Commits korrekt und nach Force Push waren sie so, wie ich es beabsichtigt hatte.
Dan M.
6
So setzen Sie alle Commits einschließlich der Root-Verwendung neu fest: git rebase -i --root …anstatt eine SHA zu übergeben.
Gfullam
80

So ändern Sie den Autor nur für das letzte Commit:

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

Angenommen, Sie möchten den Autor nur für die letzten N Commits ändern:

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

ANMERKUNGEN

  • Die --no-editFlagge sorgt dafür, dass diegit commit --amend dass keine zusätzliche Bestätigung angefordert wird
  • Wenn Sie verwenden git rebase -i, können Sie manuell festlegen, wo der Autor geändert werden soll.

Die von Ihnen bearbeitete Datei sieht folgendermaßen aus:

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
quelle
1
für alle Commits von root. git rebase -i --root UPTO_COMMIT_SHA -x "git commit --amend --author 'NEW_CHANGE' --no-edit"
Ashish Negi
1
Ich empfehle, eine --rebase-merges(kurze -r) Option hinzuzufügen , um die Topologie Ihres Zweigs intakt zu halten, wenn er einige Zusammenführungen enthält.
Donquixote
3

Diese Methode wurde von github zu diesem Zweck dokumentiert. Die Schritte sind:

  1. Öffnen Sie das Terminal und machen Sie einen nackten Klon Ihres Repos
git clone --bare https://github.com/user/repo.git
cd repo
  1. Bearbeiten Sie das folgende Skript (ersetzt OLD_EMAIL, CORRECT_EMAILund 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. Kopieren Sie das Skript, fügen Sie es in Ihr Terminal ein und drücken Sie die Eingabetaste, um es auszuführen.
  2. Schieben Sie Ihre Änderungen mit git push --force --tags origin 'refs/heads/*'und Sie sind fertig!
stevec
quelle
Ich habe die gleichen Anweisungen auf GitHub befolgt, auf die Sie verwiesen haben, und GitHub sieht jetzt so aus. Ich bin jedoch ein Git-Neuling und nicht sicher, wie ich mein lokales Repo danach wieder synchronisieren soll. Wenn ich ziehe, erhalte ich den gleichen Fehler "Weigert sich, nicht verwandte Historien zusammenzuführen", der in einer anderen Antwort erwähnt wird. Ich denke, ich muss mich gegen diese neue Commit-Historie wehren, aber ich würde spezifischere Schritte sehr schätzen.
Enigment
@enigment Wenn Sie mit dem Repo auf Github zufrieden sind, können Sie den lokal vorhandenen Ordner löschen (oder möglicherweise an einen anderen Speicherort verschieben) und einfach von Github klonen
stevec
Danke, ich weiß, aber das scheint nicht der idiomatische GitHub / Git-Weg zu sein.
Enigment
0

Wenn Sie sich beim Abwerten und Ändern unsicher fühlen, können Sie dies auf diese Weise tun. Gleichzeitig würden Sie auch die globale Konfiguration festlegen, die Sie wahrscheinlich sowieso vorhatten.

git reset HEAD~ (letztes Commit rückgängig machen)

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

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

git commit -m "message"

Edison
quelle