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 rebaseDokumentation für die notwendigen Schritte nach der Geschichte zu reparieren.
Sie haben mindestens zwei Optionen: git filter-branchund 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 lolaein nicht standardmäßiger, aber äußerst nützlicher Alias ist. Mit dem --name-statusSchalter können wir Baumänderungen sehen, die mit jedem Commit verbunden sind.
Beim Commit "Careless" (dessen SHA1-Objektname ce36c98 lautet) ist die Datei oops.isoder 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-emptyEntfernt Commits, die aufgrund der Filteroperation leer werden ( dh den Baum nicht ändern). Im typischen Fall erzeugt diese Option einen saubereren Verlauf.
-dBenennt 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/shmzu einer schnelleren Ausführung .
--index-filterist das Hauptereignis und wird bei jedem Schritt im Verlauf gegen den Index ausgeführt. Sie möchten entfernen, oops.isowo immer es gefunden wird, aber es ist nicht in allen Commits vorhanden. Der Befehl git rm --cached -f --ignore-unmatch oops.isolöscht den DVD-Rip, wenn er vorhanden ist, und schlägt ansonsten nicht fehl.
--tag-name-filterbeschreibt, wie Tag-Namen umgeschrieben werden. Ein Filter von catist 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
--allDas 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.htmlhinzugefügt wird und dass sich das Commit "DVD-Rip entfernen" nicht mehr im Hauptzweig befindet. Der gekennzeichnete Zweig refs/original/refs/heads/masterenthä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.isound „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.isoaus "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 5af4522ein 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 editnicht 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 HEADweist git an, die alte Festschreibungsnachricht wiederzuverwenden. Schließlich wird git rebase --continuemit 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.