Ich habe mit der Verwendung des Git-Teilbaums experimentiert und bin auf die folgende Situation gestoßen.
Ich habe den Teilbaum git verwendet, um meinem Repo ein externes Projekt hinzuzufügen. Ich habe absichtlich den gesamten Verlauf für das Upstream-Projekt beibehalten, da ich auf den Verlauf des Projekts verweisen und später auch einen Beitrag zum Upstream-Projekt leisten möchte.
Wie sich herausstellt, hat ein anderer Mitarbeiter des Upstream-Projekts versehentlich eine große Datei in den Hauptzweig verschoben. Um dies zu beheben, hat das vorgelagerte Projekt den Verlauf neu geschrieben und den Master erzwungen. Bei der Erstellung meines "Monorepo" habe ich dieses Commit eingefügt und möchte es auch entfernen.
Wie kann ich mein Repository aktualisieren, um den neuen Verlauf des Teilbaums widerzuspiegeln?
Mein erster Versuch war, Filter-Branch zu verwenden, um den Teilbaum und den gesamten Verlauf vollständig zu entfernen.
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch upstream-project-dir' --prune-empty HEAD
Sobald die alte Version des Teilbaums entfernt wurde, konnte ich den Teilbaum mit dem neuen Upstream-Master erneut hinzufügen. Dies hat jedoch nicht funktioniert, da der Festschreibungsverlauf aus irgendeinem Grund immer noch in der Git-Protokollausgabe angezeigt wird.
Aktualisieren
Ich habe die Schritte geschrieben, um ein minimal reproduzierbares Beispiel zu erstellen.
Erstellen Sie zuerst ein leeres Git-Repo.
git init test-monorepo cd ./test-monorepo
Erstellen Sie ein erstes Commit.
echo hello world > README git add README git commit -m 'initial commit'
Fügen Sie nun einen Teilbaum für ein externes Projekt hinzu.
git remote add thirdparty [email protected]:teivah/algodeck.git git fetch thirdparty git subtree add --prefix algodeck thirdparty master
Machen Sie einige Commits auf dem Monorepo
echo dont panic >> algodeck/README.md git commit -a -m 'test commit'
Versuchen Sie nun, den Teilbaum mit git filter-branch zu entfernen.
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
Untersuchen Sie die Git-Protokollausgabe. Ich erwarte nur mein erstes Commit.
git log
git gc --prune=now
nur Commits gelöscht, die nicht ingit log
angezeigt werden.git log
keine Argumente gemacht und ich sehe immer noch die alten Commits.Antworten:
Sie haben bereits das schlechte Commit in Ihrer Geschichte und müssen es loswerden, bevor Sie fortfahren können
Nehmen wir an, Sie haben das
master
letzte Commit umgeleitet und konnten nichts anderes tun (ich habe Ihre Filialen wirklich nicht in Sicht, also muss ich zunächst etwas annehmen).Sie können zum vorherigen Commit auschecken und Ihre Verzweigungsmarkierung 1 Schritt zurück (oder X Schritte zurück) drücken, was in jedem Fall harmlos wäre, und dann erneut ziehen
z.B
git checkout master~1
Um das übergeordnete Commit des Masters auszuchecken, warnt Git, dass wir nicht in den Filialen sindgit branch master -f
Um die aktuelle Prüfung zu zwingen, wieder Master zu werden, dh den Master-Zweig tatsächlich auf sein vorheriges Commit (oder X vorheriges Commit) zurückzuspulen, und von hier aus spielt es keine Rolle, ob der Upstream eine Force ausgeführt hat oder nicht, wir können normal oder sogar fortfahren Gehen Sie bei Bedarf zum obigen Schritt zurück. Wir können den Master nur wieder ziehen, ohne etwas vom Upstream zu verlieren (was für uns auch schreibgeschützt sein könnte, wir werden nichts dafür tun).git checkout master
Um in unserer "zurückgespulten" Hauptniederlassung zu sein, das gleiche Commit, auf das wir treten, aber jetzt stattdessen in der Niederlassunggit pull
Um den Master wieder zu ziehen (kann mit oder ohne sein--prune
), werden wir von hier aus wieder auf die Strecke zurückkehren, wenn nicht, werden wir das Gleiche bekommen, das wir hatten, wenn wir das Gleiche bekamen und nicht angenommen wurden, vielleicht wir Sie müssen zum ersten Schritt oben zurückkehren und weitere Commits zurückspulen, z. B.git checkout master~5
oder was auch immer (je nach Bedarf).quelle
git subtree
Bereinigen Sie in Ihrem Repo den Verlauf der Commits für diese Fernbedienung:
Wenn einer Ihrer eigenen Commits einen Commit enthält, der die große Datei enthält, schreiben Sie Ihren Verlauf neu, sodass auf diese große Datei nicht mehr verwiesen wird
Mit diesen beiden Schritten wird die große Datei von keinem Commit in Ihrem Repo mehr referenziert.
Es wird außerdem zu einem bestimmten Zeitpunkt zusätzlich von Ihrer Festplatte gelöscht, wenn git seinen Garbage Collector ausführt und die Ablaufverzögerungen für baumelnde Blobs erreicht sind.
Wenn Sie diese große Datei dringend so schnell wie möglich von Ihrer Festplatte löschen müssen:
Manuell ausführen
quelle