Wenn Sie der einzige Benutzer dieses Repositorys sind, können Sie die Geschichte umschreiben entweder durch git filter-branch
(als svick schrieb ), oder git fast-export
/ git fast-import
plus Filterskript (wie im Artikel beschrieben, auf den in docgnome Antwort ), oder interaktiv neu gründen . Aber beide würden die Revisionen ab dem ersten geänderten Commit ändern; das bedeutet Ärger für jeden, der seine Änderungen auf Ihrem Zweig vor dem Rewrite basiert.
RECOVERY
Wenn andere Entwickler ihre Arbeit nicht auf die Vorabversion stützen, wäre die einfachste Lösung, erneut zu klonen (erneut zu klonen).
Alternativ dazu können sie versuchen git rebase --pull
die vorspulen würden, wenn es keine Änderungen in ihrem Repository gäbe, oder ihren Zweig auf neu geschriebene Commits zurücksetzen würden (wir wollen Merge vermeiden, da es Pre-Rewrite-Commits für immer behalten würde). All dies unter der Annahme, dass sie noch keine Arbeit übertragen haben; verwenden Sie git stash
um Änderungen anderweitig zu verstauen.
Wenn andere Entwickler Feature-Zweige verwenden, und/oder git pull --rebase
nicht funktioniert, z. B. weil der Upstream nicht eingerichtet ist, müssen sie neu gründen ihre Arbeit zusätzlich zu den Post-Rewrite-Commits. Zum Beispiel direkt nach dem Holen neuer Änderungen ( git fetch
), für eine master
Zweig basiert auf / gegabelt von origin/master
muss man ausführen
$ git rebase --onto origin/master origin/master@{1} master
Hier 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/ Mechanismus, der in Git seit Version 1.6.5 verfügbar ist. Bei dieser Lösung stellen Sie Ersetzungen für Commits bereit, die eine falsche E-Mail haben; dann kann jeder, der die "replace"-Referenzen abruft (etwas wie fetch = +refs/replace/*:refs/replace/*
refspec an geeigneter Stelle in ihre .git/config
) würden auf transparente Weise Ersetzungen erhalten, und diejenigen, die diese Referenzen nicht abrufen, würden alte Übertragungen sehen.
Das Verfahren läuft in etwa so ab:
-
Alle Commits mit falscher E-Mail finden, zum Beispiel mit
$ git log --author=user@wrong.email --all
-
Erstellen Sie für jede falsche Übertragung eine Ersatzübertragung und fügen Sie sie der Objektdatenbank hinzu
$ git cat-file -p <ID of wrong commit> |
sed -e 's/user@wrong\.email/user@example.com/g' > tmp.txt
$ git hash-object -t commit -w tmp.txt
<ID of corrected commit>
-
Nun, da Sie den korrigierten Commit in der Objektdatenbank haben, müssen Sie Git anweisen, automatisch und transparent den falschen Commit durch den korrigierten zu ersetzen, indem Sie git replace
Befehl:
$ git replace <ID of wrong commit> <ID of corrected commit>
-
Listen Sie abschließend alle Ersetzungen auf, um zu überprüfen, ob dieses Verfahren erfolgreich war
$ git replace -l
und prüfen, ob Ersetzungen stattfinden
$ git log --author=user@wrong.email --all
Sie können diese Prozedur natürlich automatisieren... nun, alles außer der Verwendung von git replace
die (noch) nicht über einen Batch-Modus verfügt, so dass Sie dafür eine Shell-Schleife verwenden oder "von Hand" ersetzen müssen.
NICHT GEPRÜFT! YMMV.
Beachten Sie, dass Sie bei der Verwendung der folgenden Funktionen auf einige raue Ecken stoßen könnten refs/replace/
Mechanismus: er ist neu und noch nicht sehr gut getestet .
17 Stimmen
Frage: Bleiben bei der Verwendung von git filter-branch die SHA1-Werte für frühere Tags, Versionen und Objekte erhalten? Oder werden durch die Änderung des Autorennamens auch die zugehörigen SHA1-Sätze geändert?
0 Stimmen
Oder Sie können versuchen, mit
refs/replace/
Mechanismus.1 Stimmen
Nach der Neufassung, wenn sie ihre Arbeit nicht auf die Geschichte vor der Neufassung gestützt haben, nur
git reset --hard origin/master
oder einfachgit pull origin
(der vorspulen sollte). Wenn sie ihre Änderung als Grundlage nehmen, müssen sie eine neue Basis mitgit rebase origin/master
oder einfachgit pull --rebase origin
(die Befehle sind nur Beispiele).49 Stimmen
Hashes werden sich ändern ja
3 Stimmen
Ich habe ein kleines Skript erstellt, das die Ursache für meine Probleme beseitigt hat. gist.github.com/tripleee/16767aa4137706fd896c
0 Stimmen
@tripleee Ich finde deinen Link/deine Antwort wirklich gut, aber diese Frage ist jetzt etwa 5 Jahre alt. Dies könnte ein großartiger Q&A-Beitrag für andere Nutzer werden (beantworten Sie Ihre eigene Frage). Das wäre nützlicher, anschaulicher und sichtbarer als ein einfacher Kommentar hier.
2 Stimmen
@impinball Das Alter der Frage ist kaum relevant. Eine neue, doppelte Frage zu erstellen, kommt nicht in Frage. Ich nehme an, ich könnte eine Frage erstellen, die um diese spezielle Antwort bittet, aber ich bin nicht ganz davon überzeugt, dass sie so viel Aufmerksamkeit erhalten würde. Es ist ja nicht so, dass es hier einen Mangel an Git-Fragen gäbe... Ich freue mich jedenfalls, dass ich helfen konnte.
0 Stimmen
Diese Antwort ist viel einfacher @Flávio Amieiro stackoverflow.com/a/11768870/670229
3 Stimmen
Das github-Skript, das @TimurBernikovich erwähnt hat, ist großartig und funktioniert bei mir. Aber die github url hat sich geändert: docs.github.com/de/enterprise/2.17/user/github/using-git/
0 Stimmen
Die Antworten könnten zu viel des Guten sein. Prüfen Sie zunächst, ob dies Ihren Anwendungsfall erfüllt - stackoverflow.com/a/67363253/8293309