Wie kann ich ein einzelnes Verzeichnis von einem Git-Repository in ein neues Repository verschieben, während der Verlauf beibehalten wird?

110

Ich habe ein Git-Repository geerbt, das mehrere Projekte in separaten Verzeichnissen enthält. Ich möchte das Repository in neue einzelne Repositorys aufteilen, eines für jedes Projekt, und dann das Master-Repository die Projekte als Submodule enthalten lassen. Ich möchte dies alles tun und dabei den Revisionsverlauf der einzelnen Projekte nach Möglichkeit beibehalten.

Ich könnte das Repository für jedes Projekt klonen und jedes Mal alle anderen Projekte entfernen, aber gibt es eine bessere Möglichkeit, den geklonten Verlauf in jedem neuen Projekt-Repository zu vermeiden?

Apfelwein
quelle
2
Git-Submodule-Tag hinzugefügt, da dies sehr nützlich ist, um einen Teil eines Repos in ein Submodul umzuwandeln.
idbrii
Mögliches Duplikat des Export-Teilbaums in Git mit Verlauf
Benutzer

Antworten:

99

Mit können Sie git filter-branchden Verlauf eines Projekts neu schreiben. Aus der Dokumentation:

So schreiben Sie das Repository so um, dass es so aussieht, als ob foodir / seine Projektwurzel gewesen wäre, und verwerfen alle anderen Verlaufsdaten:

git filter-branch --subdirectory-filter foodir -- --all

Erstellen Sie mehrere Kopien Ihres Repos, tun Sie dies für jedes Unterverzeichnis, das Sie aufteilen möchten, und Sie sollten das finden, wonach Sie suchen.

Brian Campbell
quelle
1
Was wäre, wenn ich foodir ausschließen und all seine Geschichte entfernen wollte ?
Saeedgnu
1
Hinweis: Wenn Sie mehrere Verzeichnisse möchten, müssen Sie diese mehrmals angeben --subdirectory-filter. EG git filter-branch --subdirectory-filter foodir --subdirectory-filter bardirusw. --subdirectorynimmt nicht mehrere Verzeichnisse an, kann jedoch mehrfach angegeben werden.
EnabrenTane
3
@Adam Wenn Sie den Verlauf von foodirim ursprünglichen Projekt beibehalten und den Verlauf nicht neu schreiben möchten , git rm -r foodirsollte dies nur ausreichen (dies löscht auch die Kopie in Ihrem Arbeitsbaum; wenn Sie dies nicht möchten, verwenden Sie --cached). Wenn Sie es vollständig aus dem Verlauf entfernen möchten (auch die Frage von @ ilius beantworten), möchten Sie etwas wiegit filter-branch --index-filter 'git rm -r --cached --ignore-unmatched foodir' -- --all
Brian Campbell
2
@ilius Entschuldigung, ich habe Ihre Frage früher verpasst. In meiner Antwort oben finden Sie eine Antwort zum Entfernen eines Verzeichnisses und seines Verlaufs.
Brian Campbell
2
@ilius Ja, das funktioniert auch. Bei einem großen Projekt ist die --index-filterLösung schneller als die --tree-filter, da sie die Dateien nicht auschecken muss, sondern nur den Index direkt bearbeiten kann. Die Verwendung --tree-filterkann jedoch etwas einfacher sein, da Sie normale Dateisystemoperationen verwenden können, anstatt mit Indexmanipulationsoperationen arbeiten zu müssen.
Brian Campbell
4

Um einen Ordner als neues Repository zu exportieren, benötigen Sie:

  1. So klonen Sie das Repository, in das sich der zu exportierende Ordner befindet.
  2. So erstellen Sie ein leeres Repository auf Ihrem Hosting-Anbieter als GitHub, um den exportierten Ordner zu speichern.
  3. Öffnen Sie den geklonten Repository-Ordner und führen Sie den folgenden Befehl aus:

    git subtree push --prefix=YourFolderNameToExport https://github.com/YourUserName/YourNewCleanRepoName master
    
Benutzer
quelle
1
git subtreeist nicht als Cygwin-Paket verfügbar. Wenn Sie es brauchen: stackoverflow.com/a/27116828/2484903
Jack Miller
2

Der Punkt von Git ist, dass der Verlauf in jedem Commit durch Hashing des übergeordneten Commits verkörpert wird. Sie können die Commits (so funktioniert der svn-Importer im Wesentlichen) in einem neuen Repository "wiedergeben" und nur jedes Unterprojekt behalten. Dies würde jedoch die Bedeutung der Commit-Hashes zerstören. Wenn Sie damit kein Problem haben, dann sei es so.

In der Vergangenheit habe ich es einfach geklont und bin weitergegangen. Dies macht die Dinge größer, aber der Speicherplatz ist billig; Meine Zeit ist teuer.

Ich kenne auch keine Tools zum Ausspleißen eines Verzeichnisses. Ich nehme an, Sie könnten sich im Verzeichnis anmelden, um alle Commits zu finden, und dann die Commits mit etwas wie git-fast-export wiedergeben.

Colin Burnett
quelle
Ich habe mich dafür ausgesprochen, weil dies nicht negativ verdient hat - ich würde diesem Ansatz sicherlich nicht folgen, kann aber sehen, dass er es versucht hat
Alvin