Wie entferne ich den alten Verlauf aus einem Git-Repository?

Ich fürchte, ich konnte nichts Genaues finden.

Ich habe ein Git-Repository mit viel Geschichte: 500+ Filialen, 500+ Tags, geht zurück bis Mitte 2007. Es enthält ~ 19.500 Commits. Wir möchten den gesamten Verlauf vor dem 1. Januar 2010 entfernen, um ihn kleiner und leichter zu handhaben zu machen (wir würden eine vollständige Kopie des Verlaufs in einem Archiv-Repository aufbewahren).

Ich kenne das Commit, das ich zum Stamm des neuen Repositorys gemacht haben möchte. Ich kann jedoch nicht das richtige git mojo finden, um den Repo abzukürzen, um mit diesem Commit zu beginnen. Ich vermute eine Variante von

git filter-branch 

Einbeziehen von Transplantaten wäre notwendig; Es könnte auch notwendig sein, jeden der über 200 Zweige, die wir getrennt halten wollen, zu behandeln und dann den Repo wieder zusammenzufügen (etwas, was ich zu tun weiß).

Hat jemand jemals so etwas getan? Ich habe git 1.7.2.3 wenn das wichtig ist.

Erstellen Sie einfach ein Graft des Parents Ihres neuen Root-Commits an kein Parent (oder an ein leeres Commit, z. B. das echte Root-Commit Ihres Repositorys). ZB echo "" > .git/info/grafts

Nach dem Erstellen des Transplantats wird es sofort wirksam. Du solltest in der Lage sein, git log und zu sehen, dass die unerwünschten alten Commits weg sind:

 $ echo 4a46bc886318679d8b15e05aea40b83ff6c3bd47 > .git/info/grafts $ git log --decorate | tail --lines=11 commit cb3da2d4d8c3378919844b29e815bfd5fdc0210c Author: Your Name  Date: Fri May 24 14:04:10 2013 +0200 Another message commit 4a46bc886318679d8b15e05aea40b83ff6c3bd47 (grafted) Author: Your Name  Date: Thu May 23 22:27:48 2013 +0200 Some message 

Wenn alles wie git filter-branch -- --all aussieht, kannst du einfach einen einfachen git filter-branch -- --all machen, um es dauerhaft zu machen.

ACHTUNG: Nachdem der Filter-Zweig ausgeführt wurde , werden sich alle Commit-IDs geändert haben, so dass jeder, der den alten Repo benutzt, niemals mit irgendjemandem merge darf, der den neuen Repo benutzt.

Vielleicht ist es zu spät, um eine Antwort zu posten, aber da diese Seite das erste Google-Ergebnis ist, kann es dennoch hilfreich sein.

Wenn Sie in Ihrem git-Repository etwas Speicherplatz freigeben möchten, aber nicht alle Ihre Commits (Rebase oder Graft) neu erstellen und trotzdem Push / Pull / Merge von Personen mit dem vollen Repo durchführen möchten, können Sie das Git verwenden Klon seicht klonen ( –depth Parameter).

 ; Clone the original repo into limitedRepo git clone file:///path_to/originalRepo limitedRepo --depth=10 ; Remove the original repo, to free up some space rm -rf originalRepo cd limitedRepo git remote rm origin 

Sie können möglicherweise Ihr vorhandenes Repo fluten, indem Sie die folgenden Schritte ausführen:

 ; Shallow to last 5 commits git rev-parse HEAD~5 > .git/shallow ; Manually remove all other branches, tags and remotes that refers to old commits ; Prune unreachable objects git fsck --unreachable ; Will show you the list of what will be deleted git gc --prune=now ; Will actually delete your data 

Ps: Ältere Versionen von git unterstützten clone / push / pull von / zu seichten Repos nicht.

Diese Methode ist einfach zu verstehen und funktioniert gut. Das Argument für das Skript ( $1 ) ist eine Referenz (Tag, Hash, …) für das Commit, ab dem Sie Ihren Verlauf beibehalten möchten.

 #!/bin/bash git checkout --orphan temp $1 # create a new branch without parent history git commit -m "Truncated history" # create a first commit on this branch git rebase --onto temp $1 master # now rebase the part of master branch that we want to keep onto this branch git branch -D temp # delete the temp branch # The following 2 commands are optional - they keep your git repo in good shape. git prune --progress # delete all the objects w/o references git gc --aggressive # aggressively collect garbage; may take a lot of time on large repos 

Beachten Sie, dass alte Tags weiterhin vorhanden sind. Daher müssen Sie sie möglicherweise manuell entfernen

Bemerkung: Ich weiß, dass dies fast das gleiche wie @ yoyodin ist, aber es gibt einige wichtige zusätzliche Befehle und Informationen hier. Ich habe versucht, die Antwort zu bearbeiten, aber da es eine substanzielle Änderung an @ yoyodins Antwort ist, wurde meine Bearbeitung abgelehnt, also hier ist die Information!

Versuchen Sie diese Methode So kürzen Sie Git History :

 #!/bin/bash git checkout --orphan temp $1 git commit -m "Truncated history" git rebase --onto temp $1 master git branch -D temp 

Hier ist $1 SHA-1 des Commits, das Sie behalten möchten, und das Skript erstellt einen neuen Zweig, der alle Commits zwischen $1 und master und der gesamte ältere Verlauf wird gelöscht. Beachten Sie, dass dieses einfache Skript davon ausgeht, dass Sie keine bestehende Verzweigung namens temp . Beachten Sie auch, dass dieses Skript die Git-Daten für den alten Verlauf nicht löscht. Führen Sie git gc --prune=all && git repack -a -f -F -d nachdem Sie git gc --prune=all && git repack -a -f -F -d haben, dass Sie wirklich den gesamten Verlauf verlieren möchten. Sie können auch rebase --preserve-merges aber seien Sie gewarnt, dass die Git-Implementierung dieses Features nicht perfekt ist. Überprüfen Sie die Ergebnisse manuell, wenn Sie diese verwenden.

Als Alternative zum Neuschreiben des Verlaufs sollten Sie in Erwägung ziehen, git replace wie in diesem Artikel aus dem Pro Git- Buch zu verwenden . Das besprochene Beispiel beinhaltet das Ersetzen eines Eltern-Commits, um den Beginn eines Baumes zu simulieren, während der vollständige Verlauf als separater Zweig zur Verwahrung beibehalten wird.

Wenn Sie das Upstream- Repository mit dem vollständigen Verlauf , aber mit kleineren lokalen git clone --depth=1 [repo] behalten möchten, führen Sie einen flachen Klon mit git clone --depth=1 [repo] .

Nachdem Sie ein Commit durchgeführt haben, können Sie es tun

  1. git fetch --depth=1 um die alten Commits zu git fetch --depth=1 . Dies macht die alten Commits und ihre Objekte unerreichbar.
  2. git reflog expire --expire-unreachable=now --all . Alle alten Commits und ihre Objekte ablaufen lassen
  3. git gc --aggressive --prune=all , um die alten Objekte zu entfernen

Siehe auch Wie entferne ich den lokalen Git-Verlauf nach einem Commit? .

Beachten Sie, dass Sie dieses “flache” Repository nicht an einen anderen Ort verschieben können: “seichtes Update nicht erlaubt”. Weitere Informationen finden Sie unter Remote-Zurückweisung (oberflächliche Aktualisierung nicht zulässig), nachdem Git Remote-URL geändert wurde . Wenn Sie das wollen, müssen Sie bei der Pfropfung bleiben.

Ich musste mehrere Antworten und einige andere Informationen lesen, um zu verstehen, was ich tat.

1. Ignoriere alles, was älter ist als ein bestimmtes Commit

Die Datei .git/info/grafts kann falsche Eltern für ein Commit definieren. Eine Zeile mit nur einer Commit-ID besagt, dass das Commit kein Parent hat. Wenn wir sagen wollten, dass uns nur die letzten 2000 Commits wichtig sind, können wir tippen:

 git rev-parse HEAD~2000 > .git/info/grafts 

git rev-parse gibt uns die Commit-ID des 2000. Parents des aktuellen Commits. Der obige Befehl überschreibt die Graftsdatei, falls vorhanden. Überprüfen Sie, ob es zuerst da ist.

2. Schreiben Sie den Git-Verlauf neu (optional)

Wenn du dieses verfälschte Elternteil zu einem echten machen willst, dann führe:

 git filter-branch -- --all 

Es wird alle Commit-IDs ändern. Jede Kopie dieses Repositorys muss dringend aktualisiert werden.

3. Bereinigen Sie Speicherplatz

Ich habe Schritt 3 nicht gemacht. Ich wollte, dass meine Kopie mit dem Upstream kompatibel bleibt. Ich wollte nur etwas Speicherplatz sparen. Um all die alten Commits zu vergessen:

 git prune git gc 

Alternative: flache Kopien

Wenn Sie eine flache Kopie eines anderen Repositorys haben und nur etwas Speicherplatz sparen möchten, können Sie .git/shallow aktualisieren. Aber seien Sie vorsichtig, dass nichts auf einen Commit von vorher zeigt. Du könntest also so etwas ausführen:

 git fetch --prune git rev-parse HEAD~2000 > .git/shallow git prune git gc 

Der Eintritt in die Tiefe funktioniert wie ein Transplantat. Aber seien Sie vorsichtig, keine Transplantate und gleichzeitig seicht zu verwenden. Zumindest haben Sie nicht die gleichen Einträge dort, es wird fehlschlagen.

Wenn Sie noch einige alte Referenzen (Tags, Zweige, Remote-Heads) haben, die auf ältere Commits verweisen, werden diese nicht bereinigt und Sie sparen nicht mehr Speicherplatz.

Beim Rebase oder Push to Head / Master kann dieser Fehler auftreten

 remote: GitLab: You are not allowed to access some of the refs! To git@giturl:main/xyz.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'git@giturl:main/xyz.git' 

Um dieses Problem in Git Dashboard zu beheben, sollte Master-Zweig von “Protected Branches” entfernen

Bildbeschreibung hier eingeben

dann können Sie diesen Befehl ausführen

 git push -f origin master 

oder

 git rebase --onto temp $1 master 

Sie können das Verzeichnis, die Dateien und auch den gesamten Verlauf des Verzeichnisses oder der Datei löschen, indem Sie das unten genannte jar [download it] und die Befehle verwenden

bfg.jar-Datei: https://rtyley.github.io/bfg-repo-cleaner/

Git-Klon –are Repo-URL-CD Repo-Verzeichnis java -jar bfg.jar –Delete-Ordner Ordnername git Reflog Ablauf –expire = jetzt –all && git gc –prune = jetzt –aggressive Git-Push – Spiegel Repo_url

  1. entferne git data, rm .git
  2. git init
  3. Fügen Sie eine Git-Fernbedienung hinzu
  4. Kraft drücken