Was Sie tun möchten, ist äußerst störend, wenn Sie den Verlauf für andere Entwickler veröffentlicht haben. Siehe „Wiederherstellen von Upstream Rebase“ in der git rebase
Dokumentation für die notwendigen Schritte nach der Geschichte zu reparieren.
Sie haben mindestens zwei Optionen: git filter-branch
und eine interaktive Rebase, die beide unten erläutert werden.
Verwenden von git filter-branch
Ich hatte ein ähnliches Problem mit umfangreichen binären Testdaten aus einem Subversion-Import und schrieb über das Entfernen von Daten aus einem Git-Repository .
Sagen Sie, Ihre Git-Geschichte ist:
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Beachten Sie, dass dies git lola
ein nicht standardmäßiger, aber äußerst nützlicher Alias ist. Mit dem --name-status
Schalter können wir Baumänderungen sehen, die mit jedem Commit verbunden sind.
Beim Commit "Careless" (dessen SHA1-Objektname ce36c98 lautet) ist die Datei oops.iso
der DVD-Rip, der versehentlich hinzugefügt und beim nächsten Commit, cb14efd, entfernt wurde. Unter Verwendung der im oben genannten Blog-Beitrag beschriebenen Technik lautet der auszuführende Befehl:
git filter-branch --prune-empty -d /dev/shm/scratch \
--index-filter "git rm --cached -f --ignore-unmatch oops.iso" \
--tag-name-filter cat -- --all
Optionen:
--prune-empty
Entfernt Commits, die aufgrund der Filteroperation leer werden ( dh den Baum nicht ändern). Im typischen Fall erzeugt diese Option einen saubereren Verlauf.
-d
Benennt ein temporäres Verzeichnis, das noch nicht zum Erstellen des gefilterten Verlaufs verwendet werden kann. Wenn Sie auf einer modernen Linux-Distribution arbeiten, führt die Angabe eines Baums in /dev/shm
zu einer schnelleren Ausführung .
--index-filter
ist das Hauptereignis und wird bei jedem Schritt im Verlauf gegen den Index ausgeführt. Sie möchten entfernen, oops.iso
wo immer es gefunden wird, aber es ist nicht in allen Commits vorhanden. Der Befehl git rm --cached -f --ignore-unmatch oops.iso
löscht den DVD-Rip, wenn er vorhanden ist, und schlägt ansonsten nicht fehl.
--tag-name-filter
beschreibt, wie Tag-Namen umgeschrieben werden. Ein Filter von cat
ist die Identitätsoperation. Ihr Repository hat wie das obige Beispiel möglicherweise keine Tags, aber ich habe diese Option aus Gründen der allgemeinen Allgemeinheit eingefügt.
--
Gibt das Ende der Optionen an git filter-branch
--all
Das Folgende --
ist eine Abkürzung für alle Refs. Ihr Repository hat wie das obige Beispiel möglicherweise nur eine Referenz (Master), aber ich habe diese Option aus Gründen der allgemeinen Allgemeinheit aufgenommen.
Nach einigem Hin und Her ist die Geschichte nun:
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
|
| * f772d66 (refs/original/refs/heads/master) Login page
| | A login.html
| * cb14efd Remove DVD-rip
| | D oops.iso
| * ce36c98 Careless
|/ A oops.iso
| A other.html
|
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Beachten Sie, dass das neue Commit "Unvorsichtig" nur other.html
hinzugefügt wird und dass sich das Commit "DVD-Rip entfernen" nicht mehr im Hauptzweig befindet. Der gekennzeichnete Zweig refs/original/refs/heads/master
enthält Ihre ursprünglichen Commits, falls Sie einen Fehler gemacht haben. Befolgen Sie zum Entfernen die Schritte unter „Checkliste zum Verkleinern eines Repositorys“.
$ git update-ref -d refs/original/refs/heads/master
$ git reflog expire --expire=now --all
$ git gc --prune=now
Für eine einfachere Alternative klonen Sie das Repository, um die unerwünschten Bits zu verwerfen.
$ cd ~/src
$ mv repo repo.old
$ git clone file:///home/user/src/repo.old repo
Durch die Verwendung einer file:///...
Klon-URL werden Objekte kopiert, anstatt nur Hardlinks zu erstellen.
Jetzt ist Ihre Geschichte:
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Die SHA1-Objektnamen für die ersten beiden Commits ("Index" und "Admin-Seite") blieben unverändert, da die Filteroperation diese Commits nicht geändert hat. „Careless“ verloren oops.iso
und „Login - Seite“ haben ein neu Eltern, so dass ihre SHA1s tat ändern.
Interaktive Rebase
Mit einer Geschichte von:
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Sie möchten oops.iso
aus "Unvorsichtig" entfernen, als hätten Sie es nie hinzugefügt, und dann ist "DVD-Rip entfernen" für Sie nutzlos. Daher ist unser Plan für eine interaktive Rebase, die "Admin-Seite" beizubehalten, "Nachlässig" zu bearbeiten und "DVD-Rip entfernen" zu verwerfen.
Durch Ausführen wird $ git rebase -i 5af4522
ein Editor mit den folgenden Inhalten gestartet.
pick ce36c98 Careless
pick cb14efd Remove DVD-rip
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Wir führen unseren Plan aus und ändern ihn in
edit ce36c98 Careless
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
# ...
Das heißt, wir löschen die Zeile mit "DVD-Rip entfernen" und ändern den Vorgang auf "Unvorsichtig" so, dass er edit
nicht pick
.
Wenn Sie das Speichern des Editors beenden, wird uns an einer Eingabeaufforderung die folgende Meldung angezeigt.
Stopped at ce36c98... Careless
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
Wie aus der Nachricht hervorgeht, befinden wir uns im Commit "Unvorsichtig", das wir bearbeiten möchten, und führen daher zwei Befehle aus.
$ git rm --cached oops.iso
$ git commit --amend -C HEAD
$ git rebase --continue
Der erste entfernt die fehlerhafte Datei aus dem Index. Der zweite ändert oder ändert "Careless" als aktualisierten Index und -C HEAD
weist git an, die alte Festschreibungsnachricht wiederzuverwenden. Schließlich wird git rebase --continue
mit dem Rest der Rebase-Operation fortgefahren.
Dies gibt eine Geschichte von:
$ git lola --name-status
* 93174be (HEAD, master) Login page
| A login.html
* a570198 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Welches ist, was Sie wollen.