Ich habe ein einfaches Skript auf dem Schulcomputer geschrieben und die Änderungen an Git vorgenommen (in einem Repo, das sich in meinem Pendrive befand und von meinem Computer zu Hause geklont wurde). Nach mehreren Commits wurde mir klar, dass ich als Root-Benutzer etwas festschrieb.
Gibt es eine Möglichkeit, den Autor dieser Commits in meinen Namen zu ändern?
git
version-control
git-filter-branch
git-rewrite-history
Flávio Amieiro
quelle
quelle
Antworten:
Das Ändern des Autors (oder Committers) würde ein erneutes Schreiben des gesamten Verlaufs erfordern. Wenn Sie damit einverstanden sind und denken, dass es sich lohnt, sollten Sie sich den Git-Filter-Zweig ansehen . Die Manpage enthält mehrere Beispiele, um Ihnen den Einstieg zu erleichtern. Beachten Sie auch, dass Sie Umgebungsvariablen verwenden können, um den Namen des Autors, des Committers, der Daten usw. zu ändern - siehe Abschnitt "Umgebungsvariablen" auf der Git-Manpage .
Insbesondere können Sie mit diesem Befehl alle falschen Autorennamen und E-Mails für alle Zweige und Tags korrigieren (Quelle: GitHub-Hilfe ):
quelle
git push --force --tags origin HEAD:master
HINWEIS: Diese Antwort ändert SHA1s. Achten Sie daher darauf, sie in einem Zweig zu verwenden, der bereits verschoben wurde. Wenn Sie nur die Schreibweise eines Namens korrigieren oder eine alte E-Mail aktualisieren möchten, können Sie dies mit git tun, ohne den Verlauf mit neu zu schreiben
.mailmap
. Siehe meine andere Antwort .Verwenden von Interactive Rebase
Du könntest es tun
Markieren Sie dann alle Ihre fehlerhaften Commits in der Rebase-Datei als "Bearbeiten". Wenn Sie auch Ihr erstes Commit ändern möchten, müssen Sie es manuell als erste Zeile in die Rebase-Datei einfügen (folgen Sie dem Format der anderen Zeilen). Wenn git Sie dann auffordert, jedes Commit zu ändern, tun Sie dies
Bearbeiten oder schließen Sie einfach den geöffneten Editor und tun Sie es dann
um die Rebase fortzusetzen.
Sie können das Öffnen des Editors hier ganz überspringen, indem Sie anhängen,
--no-edit
sodass der Befehl wie folgt lautet:Single Commit
Wie einige Kommentatoren bemerkt haben, ist der Befehl rebase nicht erforderlich, wenn Sie nur das letzte Commit ändern möchten. Mach einfach
Dadurch wird den Autor zu dem angegebenen Namen ändern, aber die Committer werden in Ihren konfigurierten Benutzer eingestellt werden
git config user.name
undgit config user.email
. Wenn Sie den Committer auf einen von Ihnen angegebenen Wert festlegen möchten, werden sowohl der Autor als auch der Committer festgelegt:Hinweis zu Merge Commits
In meiner ursprünglichen Antwort gab es einen kleinen Fehler. Wenn es Zusammenführungs-Commits zwischen dem aktuellen
HEAD
und Ihrem gibt<some HEAD before all your bad commits>
,git rebase
werden diese abgeflacht (und wenn Sie GitHub-Pull-Anforderungen verwenden, wird es übrigens eine Menge Zusammenführungs-Commits in Ihrem Verlauf geben). Dies kann sehr oft zu einem sehr unterschiedlichen Verlauf führen (da doppelte Änderungen möglicherweise "umbasiert" werden) und im schlimmsten Fall dazu führen,git rebase
dass Sie aufgefordert werden, schwierige Zusammenführungskonflikte zu lösen (die wahrscheinlich bereits in den Zusammenführungs-Commits gelöst wurden). Die Lösung besteht darin, das-p
Flag to zu verwendengit rebase
, um die Zusammenführungsstruktur Ihres Verlaufs beizubehalten. Die Manpage fürgit rebase
warnt davor, dass die Verwendung-p
und-i
zu Problemen führen kann, aber in derBUGS
In diesem Abschnitt heißt es: "Das Bearbeiten von Commits und das Umformulieren ihrer Commit-Nachrichten sollte einwandfrei funktionieren."Ich habe
-p
den obigen Befehl hinzugefügt . Für den Fall, dass Sie nur das letzte Commit ändern, ist dies kein Problem.quelle
git commit --amend --reset-author
funktioniert auch einmaluser.name
unduser.email
ist korrekt konfiguriert.<commit>
Verwendung vonuser.name
unduser.email
von neu~/.gitconfig
: Ausführengit rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit'
, Speichern, Beenden. Keine Notwendigkeit zu bearbeiten!Sie können auch tun:
Beachten Sie , wenn Sie diesen Befehl in der Windows - Eingabeaufforderung verwenden, dann müssen Sie verwenden
"
statt'
:quelle
"A previous backup already exists in refs/original/ Force overwriting the backup with -f"
Entschuldigung, aber wo wird die-f
-flag sein, wenn wir dieses Skript zweimal ausführen. Eigentlich ist das in Brians Antwort, entschuldigen Sie die Störung kurz nachdem der Filterzweig die Lösung ist.Ein Liner, aber seien Sie vorsichtig, wenn Sie ein Repository für mehrere Benutzer haben. Dadurch werden alle Commits so geändert , dass sie denselben (neuen) Autor und Committer haben.
Mit Zeilenumbrüchen in der Zeichenfolge (was in Bash möglich ist):
quelle
HEAD
am Ende des Befehls angeben ?git push --force --tags origin 'refs/heads/*'
nach dem empfohlenen Befehl$git push --force --tags origin 'refs/heads/master'
Dies passiert, wenn Sie kein $ HOME / .gitconfig initialisiert haben. Sie können dies wie folgt beheben:
getestet mit git version 1.7.5.4
quelle
--local
Werken zugit commit --amend --reset-author --no-edit
Befehl ist besonders nützlich, wenn Sie Commits mit den falschen Autoreninformationen erstellt und dann den richtigen Autor nachträglich über festgelegt habengit config
. Ich habe gerade mein Geld gespart, als ich meine E-Mail aktualisieren musste.Für ein einzelnes Commit:
(Auszug aus der Antwort von Asmeurer)
quelle
git help commit
,git commit --amend
ändert sich die an der „Spitze des Stromzweig“ commit (der Kopf). Dies ist normalerweise der letzte begehen, aber man kann es machen jede begehen wollen , indem zuerst Überprüfung heraus , die mit begehengit checkout <branch-name>
odergit checkout <commit-SHA>
.author
committer
In dem Fall, in dem nur die obersten Commits schlechte Autoren haben, können Sie dies alles innerhalb
git rebase -i
desexec
Befehls und des--amend
Commits wie folgt tun :Hier finden Sie die bearbeitbare Liste der Commits:
Fügen Sie dann
exec ... --author="..."
nach allen Zeilen mit schlechten Autoren Zeilen hinzu:Speichern und Beenden des Editors (zum Ausführen).
Diese Lösung ist möglicherweise länger zu tippen als einige andere, aber sie ist in hohem Maße kontrollierbar - ich weiß genau, welche Commits sie trifft.
Vielen Dank an @asmeurer für die Inspiration.
quelle
exec git commit --amend --reset-author -C HEAD
?Someone else's commit
statt anmy bad commit 1
? Ich habe gerade versuchtHEAD^^
, die letzten beiden Commits zu ändern, und es hat einwandfrei funktioniert.git rebase -i HEAD^^^^^^
Sie auch schreibengit rebase -i HEAD~6
Github hat eine nette Lösung , nämlich das folgende Shell-Skript:
quelle
git reset --hard HEAD^
ein paar Mal auf den anderen lokalen Repositories, um sie auf eine frühere Version zu bringen,git pull
-ed die geänderte Version, und hier bin ich ohne Zeilen, die enthaltenunknown <[email protected]>
(ich muss die Standardeinstellung von git lieben).git push -f
. Außerdem müssen lokale Repos danach neu geklont werden.Wie bereits erwähnt, ist das Umschreiben des Verlaufs gefährlich und führt dazu, dass die Repositories anderer Personen beschädigt werden.
Aber wenn Sie das wirklich wollen und sich in einer Bash-Umgebung befinden (kein Problem unter Linux, unter Windows können Sie Git Bash verwenden, das mit der Installation von Git geliefert wird), verwenden Sie Git Filter-Branch :
Um die Arbeit zu beschleunigen, können Sie eine Reihe von Revisionen angeben, die Sie neu schreiben möchten:
quelle
--tag-name-filter cat
ist die Option "Lass es funktionieren".--tag-name-filter cat
. Dies sollte wirklich das Standardverhalten gewesen sein.Wenn Sie ein nicht zusammengeführtes Commit von einem anderen Autor übernehmen, gibt es eine einfache Möglichkeit, damit umzugehen.
git commit --amend --reset-author
quelle
--no-edit
, um dies noch einfacher zu machen, da im Allgemeinen die meisten Leute nur die E-Mail-Adresse und nicht die Commit-Nachricht aktualisieren möchtenSie können dies als Alias verwenden, um Folgendes zu tun:
oder für die letzten 10 Commits:
Zu ~ / .gitconfig hinzufügen:
Quelle: https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Hoffe es ist nützlich.
quelle
Dies ist eine ausführlichere Version von @ Brians Version:
Um den Autor und den Committer zu ändern, können Sie dies tun (mit Zeilenumbrüchen in der Zeichenfolge, die in bash möglich sind):
Möglicherweise wird einer der folgenden Fehler angezeigt:
(dies bedeutet, dass zuvor ein anderer Filterzweig im Repository ausgeführt wurde und die ursprüngliche Originalverzweigungsreferenz bei refs / original gesichert wird ).
Wenn Sie den Lauf trotz dieser Fehler erzwingen möchten, fügen Sie das
--force
Flag hinzu:-- --all
Möglicherweise ist eine kleine Erläuterung der Option erforderlich: Dadurch funktioniert der Filterzweig bei allen Revisionen aller Refs (einschließlich aller Zweige). Dies bedeutet zum Beispiel, dass Tags ebenfalls neu geschrieben werden und in den neu geschriebenen Zweigen sichtbar sind.Ein häufiger "Fehler" ist die Verwendung,
HEAD
dh das Filtern aller Revisionen nur für den aktuellen Zweig . Und dann würden keine Tags (oder andere Verweise) in dem umgeschriebenen Zweig existieren.quelle
Ein einzelner Befehl zum Ändern des Autors für die letzten N Commits:
ANMERKUNGEN
--no-edit
Flagge stellt sicher,git commit --amend
dass keine zusätzliche Bestätigung angefordert wirdgit rebase -i
, können Sie manuell festlegen, wo der Autor geändert werden soll.Die von Ihnen bearbeitete Datei sieht folgendermaßen aus:
Sie können dann noch einige Zeilen ändern, um zu sehen, wo Sie den Autor ändern möchten. Dies gibt Ihnen einen guten Mittelweg zwischen Automatisierung und Steuerung: Sie sehen die Schritte, die ausgeführt werden, und sobald Sie alles gespeichert haben, wird alles auf einmal angewendet.
quelle
git rebase -i master -x ...
git rebase -i <sha1 or ref of starting point>
edit
(odere
)Führen Sie die folgenden zwei Befehle durch, bis Sie alle Commits verarbeitet haben:
git commit --amend --reuse-message=HEAD --author="New Author <[email protected]>"
;;git rebase --continue
Dadurch bleiben alle anderen Festschreibungsinformationen (einschließlich der Daten) erhalten. Die
--reuse-message=HEAD
Option verhindert, dass der Nachrichteneditor gestartet wird.quelle
Ich verwende Folgendes, um den Autor für ein gesamtes Repository einschließlich Tags und aller Zweige neu zu schreiben:
Entfernen Sie dann, wie auf der MAN-Seite von filter-branch beschrieben , alle ursprünglichen Refs, die von gesichert wurden
filter-branch
(dies ist destruktiv, sichern Sie zuerst):quelle
--tag-name-filter cat
. Andernfalls bleiben Ihre Tags in der ursprünglichen Commit-Kette. Die anderen Antworten erwähnen dies nicht.Ich habe diese Lösung angepasst, indem ich eine einfache Lösung einnehme
author-conv-file
(das Format ist das gleiche wie bei git-cvsimport ). Es funktioniert, indem alle Benutzer geändert werden, wie inauthor-conv-file
allen Zweigen definiert.Wir haben dies in Verbindung mit verwendet
cvs2git
, um unser Repository von cvs auf git zu migrieren.dh Probe
author-conv-file
Das Skript:
quelle
Ich sollte darauf hinweisen, dass wenn das einzige Problem darin besteht, dass der Autor / die E-Mail von Ihrem üblichen abweicht, dies kein Problem ist. Die richtige Lösung besteht darin, eine Datei zu erstellen, die
.mailmap
an der Basis des Verzeichnisses mit Zeilen wie aufgerufen wirdUnd von da an betrachten Befehle wie
git shortlog
diese beiden Namen als gleich (es sei denn, Sie weisen sie ausdrücklich an, dies nicht zu tun). Weitere Informationen finden Sie unter http://schacon.github.com/git/git-shortlog.html .Dies hat den Vorteil aller anderen Lösungen hier, dass Sie den Verlauf nicht neu schreiben müssen, was bei einem Upstream zu Problemen führen kann und immer eine gute Möglichkeit ist, versehentlich Daten zu verlieren.
Wenn Sie etwas als sich selbst begangen haben und es eigentlich jemand anderes sein sollte und es Ihnen nichts ausmacht, den Verlauf an dieser Stelle neu zu schreiben, ist es wahrscheinlich eine gute Idee, den Commit-Autor zu ändern, um ihn zuzuordnen (in diesem Fall leite ich Sie zu meinem andere Antwort hier).
quelle
Ich fand die vorgestellten Versionen viel zu aggressiv, besonders wenn Sie Patches von anderen Entwicklern festschreiben, wird dies im Wesentlichen deren Code stehlen.
Die folgende Version funktioniert in allen Zweigen und ändert den Autor und den Comitter separat, um dies zu verhindern.
Ein großes Lob an leif81 für die Option all.
quelle
Ändern Sie das Commit
author name & email
durchAmend
und ersetzen Sie dannold-commit with new-one
:Ein anderer Weg
Rebasing
:quelle
Der schnellste und einfachste Weg, dies zu tun, ist das Argument --exec von git rebase:
Dadurch wird eine Aufgabenliste erstellt, die folgendermaßen aussieht:
und dies funktioniert alles automatisch, was funktioniert, wenn Sie Hunderte von Commits haben.
quelle
Wenn Sie der einzige Benutzer dieses Repositorys sind, können Sie den Verlauf entweder mit
git filter-branch
(wie von svick geschrieben ) oder mit dem Filterskriptgit fast-export
/git fast-import
plus (wie in dem Artikel beschrieben, auf den in der Antwort von docgnome verwiesen wird ) oder mit interaktiver Basis neu schreiben . Beides würde jedoch die Revisionen ab dem ersten geänderten Commit ändern. Dies bedeutet Ärger für jeden, der seine Änderungen auf Ihrem Zweig vor dem Umschreiben basiert.WIEDERHERSTELLUNG
Wenn andere Entwickler ihre Arbeit nicht auf der Version vor dem Umschreiben basieren würden, wäre die einfachste Lösung das erneute Klonen (erneutes Klonen).
Alternativ können sie versuchen
git rebase --pull
, einen schnellen Vorlauf durchzuführen, wenn keine Änderungen in ihrem Repository vorgenommen wurden, oder ihren Zweig zusätzlich zu neu geschriebenen Commits neu zu gründen (wir möchten das Zusammenführen vermeiden, da dadurch vorab neu geschriebene Commits für immer erhalten bleiben). All dies unter der Annahme, dass sie keine Arbeit geleistet haben; Verwenden Siegit stash
diese Option, um Änderungen anderweitig aufzubewahren.Wenn andere Entwickler Feature-Zweige verwenden und / oder
git pull --rebase
nicht funktionieren, z. B. weil Upstream nicht eingerichtet ist, müssen sie ihre Arbeit zusätzlich zu den Commits nach dem Umschreiben neu aufbauen . Zum Beispiel muss unmittelbar nach dem Abrufen neuer Änderungen (git fetch
) für einenmaster
Zweig, der auf / forked from basiertorigin/master
, ausgeführt werdenHier
origin/master@{1}
ist der Zustand vor dem Umschreiben (vor dem Abrufen), siehe Gitrevisions .Eine alternative Lösung wäre die Verwendung von Refs / Replace / Mechanism, die in Git seit Version 1.6.5 verfügbar sind. In dieser Lösung ersetzen Sie Commits mit falschen E-Mails. dann würde jeder, der Refs zum Ersetzen abruft (so etwas wie
fetch = +refs/replace/*:refs/replace/*
Refspec an geeigneter Stelle in seinem.git/config
), transparent ersetzt werden, und diejenigen, die diese Refs nicht abrufen, würden alte Commits sehen.Das Verfahren sieht ungefähr so aus:
Finden Sie alle Commits mit falscher E-Mail, zum Beispiel mit
Erstellen Sie für jedes falsche Commit ein Ersatz-Commit und fügen Sie es der Objektdatenbank hinzu
Nachdem Sie das Commit in der Objektdatenbank korrigiert haben, müssen Sie git anweisen, das falsche Commit automatisch und transparent durch das korrigierte Commit mit dem folgenden
git replace
Befehl zu ersetzen :Listen Sie abschließend alle Ersetzungen auf, um zu überprüfen, ob dieser Vorgang erfolgreich war
und prüfen Sie, ob ein Austausch erfolgt
Sie können diesen Vorgang natürlich automatisieren ... nun, alle außer der Verwendung,
git replace
die (noch) keinen Batch-Modus hat. Sie müssten also dafür eine Shell-Schleife verwenden oder "von Hand" ersetzen.NICHT GETESTET! YMMV.
Beachten Sie, dass bei der Verwendung des
refs/replace/
Mechanismus möglicherweise einige Ecken und Kanten auftreten: Er ist neu und noch nicht sehr gut getestet .quelle
Wenn die Commits, die Sie korrigieren möchten, die neuesten sind und nur einige davon, können Sie eine Kombination aus
git reset
und verwendengit stash
, um sie erneut zu bestätigen, nachdem Sie den richtigen Namen und die richtige E-Mail-Adresse konfiguriert haben.Die Sequenz sieht ungefähr so aus (für 2 falsche Commits, keine ausstehenden Änderungen):
quelle
Wenn Sie Eclipse mit EGit verwenden, gibt es eine recht einfache Lösung.
Annahme: Sie haben Commits in einem lokalen Zweig 'local_master_user_x', die aufgrund des ungültigen Benutzers nicht an einen 'Zweig' der entfernten Zweigstelle übertragen werden können.
quelle
Mit der interaktiven Rebase können Sie nach jedem Commit, den Sie ändern möchten, einen Änderungsbefehl platzieren. Zum Beispiel:
quelle
;-)
.Beachten Sie, dass git zwei verschiedene E-Mail-Adressen speichert , eine für den Committer (die Person, die die Änderung übernommen hat) und eine für den Autor (die Person, die die Änderung geschrieben hat).
Die Committer-Informationen werden an den meisten Stellen nicht angezeigt, aber Sie können sie mit anzeigen
git log -1 --format=%cn,%ce
(oder verwenden,show
anstattlog
ein bestimmtes Commit anzugeben).Während das Ändern des Autors Ihres letzten Commits so einfach wie möglich ist
git commit --amend --author "Author Name <[email protected]>"
, gibt es keinen Einzeiler oder kein Argument, um dasselbe mit den Committer-Informationen zu tun.Die Lösung besteht darin, Ihre Benutzerinformationen (vorübergehend oder nicht) zu ändern und dann das Commit zu ändern, wodurch der Committer auf Ihre aktuellen Informationen aktualisiert wird:
quelle
path\to\repo\.git
. Ich bin mir noch nicht sicher, was Sie tun müssen, um es vollständig zu löschen. Änderungen scheinen leider (?) Nicht zu löschen.Wir haben heute ein Problem festgestellt, bei dem ein UTF8-Zeichen in einem Autorennamen Probleme auf dem Build-Server verursachte. Daher mussten wir den Verlauf neu schreiben, um dies zu korrigieren. Die unternommenen Schritte waren:
Schritt 1: Ändern Sie Ihren Benutzernamen in git für alle zukünftigen Commits gemäß den Anweisungen hier: https://help.github.com/articles/setting-your-username-in-git/
Schritt 2: Führen Sie das folgende Bash-Skript aus:
Kurzübersicht: Checken Sie Ihr Repository in eine temporäre Datei aus, checken Sie alle Remote-Zweige aus, führen Sie das Skript aus, mit dem der Verlauf neu geschrieben wird, erzwingen Sie einen Push des neuen Status und weisen Sie alle Kollegen an, einen Rebase-Pull durchzuführen, um die Änderungen zu erhalten.
Wir hatten Probleme damit, dies unter OS X auszuführen, da es die Zeilenenden in Festschreibungsnachrichten irgendwie durcheinander brachte, sodass wir es anschließend auf einem Linux-Computer erneut ausführen mussten.
quelle
Ihr Problem ist wirklich häufig. Siehe " Verwenden von Mailmap zum Korrigieren der Autorenliste in Git "
Der Einfachheit halber habe ich ein Skript erstellt, um den Prozess zu vereinfachen: git-changemail
Nachdem Sie dieses Skript in Ihren Pfad eingefügt haben, können Sie folgende Befehle ausführen:
Ändern Sie die Autorenübereinstimmungen im aktuellen Zweig
Ändern Sie die Autoren- und Committer-Übereinstimmungen auf <branch> und <branch2>. Übergeben Sie
-f
an Filter-Branch, um das Umschreiben von Backups zu ermöglichenVorhandene Benutzer auf Repo anzeigen
Übrigens, nachdem Sie Ihre Änderungen vorgenommen haben, bereinigen Sie das Backup aus dem Filterzweig mit: git-backup-clean
quelle
Probieren Sie es aus. Es wird das gleiche wie oben erwähnt tun, aber interaktiv.
Referenz: https://github.com/majdarbash/git-author-change-script
quelle
Ich möchte auch mein Beispiel hinzufügen. Ich möchte eine bash_function mit einem bestimmten Parameter erstellen .
Dies funktioniert in Mint-Linux-17.3
quelle
Wenn Sie der einzige Benutzer dieses Repos sind oder es Ihnen nicht wichtig ist, das Repo möglicherweise für andere Benutzer zu brechen, dann ja. Wenn Sie diese Commits gepusht haben und sie dort existieren, wo irgendwo anders auf sie zugegriffen werden kann, nein, es sei denn, Sie kümmern sich nicht darum, die Repos anderer Leute zu brechen. Das Problem besteht darin, dass durch Ändern dieser Commits neue SHAs generiert werden, die dazu führen, dass sie als unterschiedliche Commits behandelt werden. Wenn jemand anderes versucht, diese geänderten Commits einzuziehen, ist die Historie anders und kaboom.
Diese Seite http://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.html beschreibt, wie es geht. (Ich habe das nicht so YMMV versucht)
quelle
refs/replace/
Mechanismus ausprobieren .