Frage

Ich habe ein Git Repository, das eine Reihe von Unterverzeichnissen enthält.Jetzt habe ich festgestellt, dass eines der Unterverzeichnisse nichts mit dem anderen zu tun hat und in ein separates Repository getrennt werden sollte.

Wie kann ich dies tun und gleichzeitig den Verlauf der Dateien im Unterverzeichnis behalten?

Ich denke, ich könnte einen Klon erstellen und die unerwünschten Teile jedes Klons entfernen, aber ich nehme an, dass ich dadurch den vollständigen Baum erhalten würde, wenn ich eine ältere Revision usw. auschecke.Das mag akzeptabel sein, aber ich würde es vorziehen, so tun zu können, als hätten die beiden Repositories keinen gemeinsamen Verlauf.

Um es klarzustellen, ich habe die folgende Struktur:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

Aber ich hätte stattdessen gerne Folgendes:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/
War es hilfreich?

Lösung

Aktualisieren : Dieser Prozess ist so verbreitet, dass das git Team machte es viel einfacher mit einem neuen Werkzeug, git subtree. Siehe hier: Detach (move) Unterverzeichnis in separaten Git-Repository


Sie möchten Ihr Repository klonen und dann git filter-branch verwenden alles, aber das Unterverzeichnis Sie möchten in Ihrem neuen Repo markieren werden Garbage Collection.

  1. Ihr lokales Repository klonen:

    git clone /XYZ /ABC
    

    (Hinweis:. Das Repository wird mit Hard-Links geklont werden, aber das ist kein Problem, da die fest verbundenen Dateien werden nicht in sich selbst geändert werden - neue wird erstellt)

  2. Lassen Sie uns nun die interessanten Zweige bewahren, die wir auch neu schreiben möchten, und dann den Ursprung entfernen zu vermeiden, dort drängen und dafür zu sorgen, dass alte Commits nicht von der Herkunft verwiesen werden:

    cd /ABC
    for i in branch1 br2 br3; do git branch -t $i origin/$i; done
    git remote rm origin
    

    oder für alle entfernten Niederlassungen:

    cd /ABC
    for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done
    git remote rm origin
    
  3. Nun möchten Sie vielleicht auch Tags entfernen, die in keinem Zusammenhang mit dem Teilprojekt haben; Sie können auch das später tun, aber Sie könnten wieder Ihre Repo beschneiden müssen. Ich tat es nicht und bekam einen WARNING: Ref 'refs/tags/v0.1' is unchanged für alle Tags (da sie alle in keinem Zusammenhang mit dem Teilprojekt waren); zusätzlich nach einer solchen Tags mehr Platz entfernt wird zurückgewonnen werden. Offenbar sollte git filter-branch der Lage sein, andere Tags neu zu schreiben, aber ich konnte dies nicht bestätigen. Wenn Sie alle Tags entfernen möchten, verwenden Sie git tag -l | xargs git tag -d.

  4. Dann Filter-Zweig verwenden und die anderen Dateien ausschließen zurückgesetzt, so können sie beschnitten werden. Lassen Sie uns auch --tag-name-filter cat --prune-empty in den leeren Commits zu entfernen und Tags neu zu schreiben (beachten Sie, dass diese müssen ihre Unterschrift Streifen):

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
    

    oder alternativ nur den HEAD Zweig zu umschreiben und ignoriert Tags und andere Zweige:

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
    
  5. Dann die Sicherungs reflogs löschen, so kann der Raum wirklich zurückgewonnen werden (obwohl jetzt der Betrieb ist destruktiv)

    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --aggressive --prune=now
    

    und jetzt haben Sie eine lokale Git Repository des ABC-Unterverzeichnis mit all seiner Geschichte erhalten.

Hinweis: Für die meisten Anwendungen git filter-branch in der Tat die zusätzlichen Parameter -- --all haben sollte. Ja, das ist wirklich - - Raum - - all. Dies muss die letzten Parameter für den Befehl sein. Wie Matli entdeckte, hält dies das Projekt Branches und Tags in der neuen Repo enthalten.

Edit:. Verschiedene Vorschläge von Kommentaren unten eingebaut wurden, um sicherzustellen, zum Beispiel, dass das Repository tatsächlich geschrumpft ist (die vorher nicht immer der Fall war)

Andere Tipps

Der einfache Weg ™

Es stellt sich heraus, dass dies eine solche gemeinsame und nützliche Praxis, dass die Oberherren von git machte es wirklich einfach, aber Sie haben eine neuere Version von git haben (> = 1.7.11 Mai 2012). Sehen Sie die Anhang , wie Sie den neuesten git installieren. Außerdem gibt es ein reale Welt Beispiel in dem Durchlauf unten.

  1. Bereiten Sie die alte Repo

    pushd <big-repo>
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    Hinweis: <name-of-folder> darf NICHT führende oder nachfolgende Zeichen enthalten. Zum Beispiel, mit dem Namen der Ordner subproject MUSS als subproject übergeben werden, nicht ./subproject/

    Hinweis für Windows-Benutzer: , wenn Ihre Ordnertiefe> 1 ist, <name-of-folder> * nix-Stil Ordner Separator haben muss (/). Zum Beispiel, mit dem Namen der Ordner path1\path2\subproject MUSS als path1/path2/subproject geben werden

  2. Erstellen Sie die neue Repo

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. Verknüpfen Sie die neue Repo Github oder wo auch immer

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. Cleanup, , falls gewünscht

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    Hinweis : Das lässt alle historischen Referenzen in der repository.See die Anhang unten, wenn Sie tatsächlich besorgt sind über ein Passwort begangen zu haben, oder Sie müssen die abnehm Dateigröße Ihres .git Ordner.

...

Lösungsweg

Die gleichen Schritte wie oben , aber nach meinen genauen Schritten für mein Repository statt <meta-named-things> zu verwenden.

Hier ist ein Projekt, das ich für die Implementierung JavaScript-Browser-Module in Knoten haben:

tree ~/Code/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

Ich möchte einen einzelnen Ordner aufzuschlüsseln, btoa, in einem separaten git-Repository

pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd

Ich habe jetzt einen neuen Zweig, btoa-only, dass nur Commits für btoa hat, und ich möchte ein neues Repository erstellen.

mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only

Als nächstes habe ich eine neue Repo auf Github oder bitbucket erstellen, oder was auch immer, und fügen Sie die origin sind (btw, „Ursprung“ ist nur eine Konvention, die nicht Teil des Befehls - man könnte es als „Remote-Server“ oder was auch immer Sie mögen)

git remote add origin git@github.com:node-browser-compat/btoa.git
git push origin -u master

Happy day!

Hinweis: Wenn Sie ein Repo mit einem README.md, .gitignore und LICENSE erstellt, müssen Sie ziehen zuerst:

git pull origin -u master
git push origin -u master

Schließlich werde ich den Ordner, aus dem größeren Repo entfernen möge

git rm -rf btoa

...

Anhang

Aktuelle git auf OS X

Um die neueste Version von git zu erhalten:

brew install git

Um Gebräu für OS X zu erhalten:

http://brew.sh

Aktuelle git auf Ubuntu

sudo apt-get update
sudo apt-get install git
git --version

Wenn das nicht funktioniert (Sie haben eine sehr alte Version von Ubuntu), versuchen

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git

Wenn das immer noch nicht funktioniert, versuchen

sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree

Dank von den Kommentaren rui.araujo.

Löschen Ihrer Geschichte

Mit dem Standard-Dateien von git Entfernen von ihnen aus git eigentlich nicht entfernen, es verpflichtet nur, dass sie nicht mehr da sind. Wenn Sie möchten, um tatsächlich die historischen Referenzen entfernen (das heißt Sie haben ein Passwort begangen), müssen Sie dies tun:

git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

Danach können Sie überprüfen, ob Ihre Datei oder einen Ordner nicht mehr zeigt sich in der git Geschichte überhaupt

git log -- <name-of-folder> # should show nothing

Allerdings Sie nicht "Push" löscht auf Github und dergleichen. Wenn Sie versuchen, werden Sie eine Fehlermeldung erhalten, und Sie werden git pull müssen, bevor Sie git push können - und dann bist du wieder alles in Ihrer Geschichte mit

.

Wenn Sie also die Geschichte vom „Ursprung“ löschen wollen - was bedeutet, es von Github zu löschen, bitbucket, etc. - Sie werden die Repo löschen müssen und erneut drücken, um eine beschnittene Kopie des Repo. Aber warten Sie - gibt es mehr ! - Wenn Sie wirklich besorgt über immer wie ein Passwort oder etwas los, dass Sie need um die Sicherung zu beschneiden (siehe unten).

machen .git kleine

Die oben erwähnte Geschichte löschen Befehl lässt immer noch hinter einer Reihe von Backup-Dateien - weil git all zu freundlich ist Ihnen helfen, Ihre Repo durch Zufall nicht zu verderben. Es wird schließlich verwaiste Dateien in den Tagen gelöscht und Monate, aber es lässt sie dort für eine Weile, falls Sie feststellen, dass Sie versehentlich etwas gelöscht Sie nicht wollen.

Also, wenn Sie wirklich wollen, leeren Sie den Papierkorb reduzieren die Klongröße eines Repo sofort haben Sie alle diese wirklich seltsame Dinge zu tun:

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

Das heißt, würde ich empfehlen, diese Schritte nicht durchführen, es sei denn Sie wissen, dass Sie benötigen - nur für den Fall Sie den falschen Unterverzeichnis stutzen hat, weißte? Die Backup-Dateien sollten nicht geklont werden, wenn Sie die repo schieben, sie werden nur in Ihrer lokalen Kopie sein.

Kredit

Paul Antwort erstellt ein neues Repository enthält / ABC, aber nicht entfernen / ABC aus / XYZ. Der folgende Befehl entfernen / ABC aus / XYZ:

git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD

Natürlich testen Sie es in einem 'Klon --no-Hardlinks' Repository zuerst, und folgen Sie es mit dem Reset gc und Prune Befehle Paul auflistet.

Ich habe festgestellt, dass, um die alte Geschichte aus dem neuen Repository richtig zu löschen, haben Sie ein wenig mehr Arbeit nach dem filter-branch Schritt zu tun.

  1. Sie den Klon und die Filter:

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. jeden Verweis auf die alte Geschichte entfernen. „Ursprung“ wurde die Verfolgung Ihrer Klon und „Original“ ist, wo Filter-Zweig die alten Sachen speichert:

    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. Schon jetzt Ihre Geschichte könnte in einem Packfile geklebt werden, die nicht berühren fsck. Reißen Sie es in Fetzen, ein neues Packfile Erstellen und Löschen der nicht verwendeten Objekte:

    git repack -ad
    

Es gibt eine Erklärung dieses in dem Handbuch für filter-branch .

Edit: Bash-Skript hinzugefügt

.

Die hier gegebenen Antworten arbeiteten nur teilweise für mich; Viele große Dateien blieben im Cache. Was schließlich arbeitete (nach Stunden in #git auf freenode):

git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT  --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

Bei den bisherigen Lösungen waren die Repository Größe ca. 100 MB. Dieser brachte es auf 1,7 MB nach unten. Vielleicht hilft es jemand:)


Der folgende Bash-Skript automatisiert die Aufgabe:

!/bin/bash

if (( $# < 3 ))
then
    echo "Usage:   $0 </path/to/repo/> <directory/to/extract/> <newName>"
    echo
    echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
    exit 1
fi


clone=/tmp/${3}Clone
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

git filter-branch --subdirectory-filter $2  --prune-empty --tag-name-filter cat -- --all

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

Dies ist nicht mehr so ​​komplex, dass Sie einfach das verwenden können Git-Filterzweig Befehl auf einem Klon Ihres Repos, um die nicht gewünschten Unterverzeichnisse auszusortieren und sie dann auf die neue Fernbedienung zu übertragen.

git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .

Aktualisieren : Die git-Unterbaum-Modul war so nützlich, dass das git Team es in dem Kern gezogen und machte es git subtree. Siehe hier: Detach (move) Unterverzeichnis in separaten Git-Repository

git-Unterbaum kann dies nützlich sein

http://github.com/apenwarr/git -subtree / Blob / Master / git-subtree.txt (veraltet)

http: // psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/

Hier ist eine kleine Änderung an CoolAJ86 's " The Easy Way ™“ beantworten, um zu spalten mehr Unterordner (sie sub1and sub2 sagen) in ein neues Git Repository.

Der einfache Weg ™ (mehrere Unterordner)

  1. Bereiten Sie die alte Repo

    pushd <big-repo>
    git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    Hinweis: <name-of-folder> darf NICHT führende oder nachfolgende Zeichen enthalten. Zum Beispiel, mit dem Namen der Ordner subproject MUSS als subproject übergeben werden, nicht ./subproject/

    Hinweis für Windows-Benutzer: , wenn Ihre Ordnertiefe> 1 ist, <name-of-folder> * nix-Stil Ordner Separator haben muss (/). Zum Beispiel kann der Ordner mit dem Namen path1\path2\subproject MUSS als path1/path2/subproject geben werden. Darüber hinaus verwenden Sie nicht mvcommand aber move.

    Abschließender Hinweis: der einzigartige und großer Unterschied mit der Basis Antwort ist die zweite Zeile des Skripts "git filter-branch..."

  2. Erstellen Sie die neue Repo

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. Verknüpfen Sie die neue Repo Github oder wo auch immer

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. Cleanup, , falls gewünscht

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    Hinweis : Das lässt alle historischen Referenzen in der repository.See die Anhang in der ursprünglichen Antwort, wenn Sie tatsächlich besorgt sind über ein Passwort begangen zu haben, oder Sie brauchen um die Dateigröße Ihrer .git Ordner zu verringern.

Die ursprüngliche Frage will XYZ / ABC / (* Dateien) ABC / ABC / (* Dateien) werden. Nachdem die akzeptierte Antwort für meinen eigenen Code Implementierung, bemerkte ich, dass es tatsächlich ändert XYZ / ABC / (* Dateien) in ABC / (* Dateien). Der Filter-Zweig Manpage selbst sagt,

  

Das Ergebnis enthält das Verzeichnis (und nur das) als Projekt root .“

Mit anderen Worten, fördert es die Top-Level-Ordner „oben“ eine Ebene. Das ist eine wichtige Unterscheidung, weil zum Beispiel in meiner Geschichte ich einen Top-Level-Ordner umbenannt hatte. Mit dem Ordner „oben“ einer Ebene zu fördern, git verliert an der Kontinuität begehen, wo ich die Umbenennungs tat.

Ich verlor contiuity nach Filter-Zweig

Meine Antwort auf die Frage ist dann 2 Kopien des Repository zu machen und löschen Sie die Ordner (n), die Sie in jeder halten wollen. Der Mann Seite unterstützt mich mit dieser:

  

[...] vermeiden, mit [diesem Befehl], wenn eine einfache Einzel begehen würde genügen, Ihr Problem zu beheben

Die richtige Weg ist nun wie folgt vor:

git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]

GitHub haben jetzt sogar kleine Artikel über solche Fälle.

Aber sicher sein, Ihre ursprünglichen Repo separaten Verzeichnis zu klonen ersten (wie es alle Dateien löschen würde und andere Verzeichnisse und Sie wahrscheinlich Notwendigkeit, mit ihnen zu arbeiten).

So Ihr Algorithmus sollte sein:

  1. klonen Remote-Repo in ein anderes Verzeichnis
  2. mit git filter-branch links nur Dateien unter einem Unterverzeichnis, drücken Sie auf neue Remote
  3. create begehen dieses Unterverzeichnis von der Originalfernbedienung Repo entfernen

Es scheint, dass die meisten (alle?) Der hier Antworten stützen sich auf irgendeine Form von git filter-branch --subdirectory-filter und seinesgleichen. Dies kann „die meiste Zeit“ arbeiten aber in einigen Fällen, zum Beispiel den Fall, wenn Sie den Ordner umbenannt, ex:

 ABC/
    /move_this_dir # did some work here, then renamed it to

ABC/
    /move_this_dir_renamed

Wenn Sie einen normalen git Filter Stil zu extrahieren „move_me_renamed“ Sie Dateiänderungshistorie verlieren, die von hinten kamen, als es war zunächst move_this_dir ( ref ).

Es scheint also, dass der einzige Weg, wirklich zu halten alle Änderungsverlauf (wenn Sie einen Fall wie dieser ist), ist im Wesentlichen auf das Repository kopieren (erstellen Sie eine neue Repo, festgelegt, dass nuke der Ursprung), dann alles andere, und benennen Sie das Unterverzeichnis zu dem Elternteil zu sein wie folgt:

  1. Klonen Sie das Multi-Modul-Projekt lokal
  2. Branchen - prüfen, was da: git branch -a
  3. Sie an jedem Zweig eine Kasse im Split aufgenommen werden, um eine lokale Kopie auf Ihrer Workstation zu erhalten: git checkout --track origin/branchABC
  4. Erstellen Sie eine Kopie in einem neuen Verzeichnis: cp -r oldmultimod simple
  5. Gehen Sie in das neue Projekt kopieren: cd simple
  6. Sie sich von den anderen Modulen befreien, die noch nicht in diesem Projekt benötigt werden:
  7. git rm otherModule1 other2 other3
  8. Geben Sie nun nur die subdir des Zielmoduls bleibt
  9. Sie sich von dem Modul subdir befreien, so dass das Modul root das neue Projekt root
  10. wird
  11. git mv moduleSubdir1/* .
  12. Löschen Sie die Reliquie subdir: rmdir moduleSubdir1
  13. Überprüfen Sie Änderungen an einem beliebigen Punkt: git status
  14. Erstellen Sie die neue git Repo und kopieren Sie die URL dieses Projekt in sie Punkt:
  15. git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
  16. Stellen Sie sicher, das ist gut: git remote -v
  17. Drücken Sie die Änderungen bis zum Remote-Repo: git push
  18. Gehen Sie auf die Remote-Repo und überprüfen es ist alles da
  19. Wiederholen Sie es für einen anderen Zweig benötigt: git checkout branch2

Dies folgt die Github doc " Splitting einen Unterordner aus in ein neues Repository " 6-11 Schritte um das Modul zu einem neuen Repo zu drücken.

Dies wird Ihnen keinen Platz sparen in Ihrem .git Ordner, aber es wird für diese Dateien auch über Umbenennungen alle Änderungshistorie bewahren. Und das kann es nicht wert sein, wenn es nicht „eine Menge“ der Geschichte verloren, etc. Aber zumindest sind Sie garantiert nicht zu verlieren ältere verpflichtet!

Ich hatte genau dieses Problem aber alle Standardlösungen auf Basis von git filter-branch waren extrem langsam. Wenn Sie ein kleines Repository haben, dann kann dies kein Problem sein, es war für mich. Ich schrieb Programm eine andere git Filterung auf libgit2 basiert, die in einem ersten Schritt erzeugt Verzweigungen für jede Filterung des primären Repository- und schiebt dann diese Repositorys als nächsten Schritt zu reinigen. Auf meinem Repository (500Mb 100000 Commits) die Standard-git filter-branch Methoden dauerte Tage. Mein Programm dauert nur wenige Minuten die gleiche Filterung zu tun.

Es hat den fabelhaften Namen git_filter und lebt hier:

https://github.com/slobobaby/git_filter

auf GitHub.

Ich hoffe, dass es für jemanden nützlich ist.

Für das, was es wert ist, hier ist, wie GitHub unter Verwendung auf einem Windows-Rechner. Sagen wir, Sie in wohnhaft in C:\dir1 eine geklonte Repo haben. Die Verzeichnisstruktur sieht wie folgt aus: C:\dir1\dir2\dir3. Das dir3 Verzeichnis ist diejenige, die ich ein neuer separater Repo sein will.

Github:

  1. Erstellen Sie Ihr neues Repository: MyTeam/mynewrepo

Bash Prompt:

  1. $ cd c:/Dir1
  2. $ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
    Zurückgegeben: Ref 'refs/heads/master' was rewritten (FYI:. Dir2 / dir3 Groß- und Kleinschreibung)

  3. $ git remote add some_name git@github.com:MyTeam/mynewrepo.git
    git remote add origin etc. hat nicht funktioniert, kehrte "remote origin already exists"

  4. $ git push --progress some_name master

Wie ich oben erwähnt, hatte ich das umgekehrt verwenden Lösung (Löschen alle Commits meinen dir/subdir/targetdir nicht berühren) schien ziemlich gut zu funktionieren etwa 95% der Commits zu entfernen (wie gewünscht). Es gibt jedoch zwei kleine Probleme bleiben.

FIRST , filter-branch einen Knall tat Job Commits zu entfernen, den Code einzuführen oder ändern, aber es scheint, fusionieren Commits ist unter seiner Station im Gitiverse.

Dies ist ein kosmetisches Problem, das ich mit wohl leben kann (er sagt ... weicht langsam mit den Augen abgewendet) .

SECOND die wenigen Commits, die ziemlich viel bleiben, sind ALLE dupliziert! Ich scheine zu haben, ein zweites, redundantes Timeline erworben, die nur über die gesamte Geschichte des Projektes erstreckt. Das Interessante an (die Sie aus dem Bild unten sehen), ist, dass meine drei Ortsvereine sind nicht alle auf der gleichen Timeline (das ist sicherlich, warum es existiert und nicht nur Müll gesammelt).

Das einzige, was ich mir vorstellen kann ist, dass einer der gelöschten Commits war vielleicht der einzige merge commit, dass filter-branch hat löschen eigentlich , und das schuf die parallel Timeline wie jeder jetzt-unmerged Strang nahm seine eigene Kopie der Commits. ( Achselzucken Wo ist mein Tardis?) Ich bin mir ziemlich sicher, dass ich dieses Problem beheben kann, obwohl ich würde wirklich Liebe zu verstehen, wie es passiert ist.

Im Fall von verrücktem mergefest-O-RAMA, werde ich wahrscheinlich, dass man allein verlassen, da sie so selbst hat fest verwurzelt in meinem begehen mich Geschichte bedrohliche, wenn ich Near- kommen, scheint es nicht zu tatsächlich alle nicht-kosmetische Probleme verursachen und weil es ganz schön in Tower.app.

Mit diesem Filter Befehl ein Unterverzeichnis entfernen, während der Tags und Zweige zu bewahren:

git filter-branch --index-filter \
"git rm -r -f --cached --ignore-unmatch DIR" --prune-empty \
--tag-name-filter cat -- --all

Der einfachere Weg

  1. git splits . Ich habe es als git Erweiterung, basierend auf jkeating Lösung .
  2. Teilen Sie die Verzeichnisse in eine lokale Niederlassung #change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
    #split multiple directories into new branch XYZ git splits -b XYZ XY1 XY2

  3. Erstellen Sie eine leere Repo irgendwo. Wir nehmen an, wir haben eine leere Repo genannt xyz auf GitHub erstellt, der Weg hat: git@github.com:simpliwp/xyz.git

  4. Push auf den neuen Repo. #add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz git@github.com:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master

  5. Klonen Sie die neu erstellte Remote-Repo in ein neues lokales Verzeichnis
    #change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone git@github.com:simpliwp/xyz.git

Ich empfehle GitHub Leitfaden für die Spaltung Unterordner in ein neues Repository . Die Schritte sind ähnlich wie Paul Antwort , aber ich fand ihre Anweisungen leichter zu verstehen.

Ich habe die Anweisungen so modifiziert, dass sie für ein lokales Repository anwenden, anstatt eine auf GitHub.


  

Splitting einen Unterordner aus in ein neues Repository

     
      
  1. Öffnen Git Bash.

  2.   
  3. Ändern Sie den Strom an den Standort Arbeitsverzeichnis, in dem Sie Ihr neues Repository erstellen möchten.

  4.   
  5. das Repository-Klon, der den Unterordner enthält.

  6.   
     

git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
     
      
  1. ändern Sie das aktuelle Arbeitsverzeichnis zu Ihrem geklonten Repository.
  2.   
     

cd REPOSITORY-NAME
     
      
  1. Um die Unterordner aus dem Rest der Dateien im Repository, führen git filter-branch, liefert diese Informationen herausfiltern:      
        
    • FOLDER-NAME: Der Ordner in Ihrem Projekt, das Sie von einem separaten Repository erstellen möchten.      
          
      • . Tipp: Windows-Benutzer sollten / verwenden, um Ordner zu begrenzen
      •   
    •   
    • BRANCH-NAME. Der Standardzweig für Ihr aktuelles Projekt, zum Beispiel master oder gh-pages
    •   
  2.   
     

git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME  BRANCH-NAME 
# Filter the specified branch in your directory and remove empty commits
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89)
Ref 'refs/heads/BRANCH-NAME' was rewritten

Sie könnte so etwas wie brauchen „git reflog --expire = verfallen jetzt --all“ vor der Garbage Collection, um tatsächlich die Dateien zu säubern. git filter-branch entfernt nur Verweise in der Geschichte, aber nicht entfernen Sie die reflog Einträge, die die Daten enthalten. Natürlich testet diese zuerst.

Meine Plattennutzung sank dramatisch in dies zu tun, wenn meine Anfangsbedingungen etwas anders waren. Vielleicht --subdirectory-Filter negiert dieses Bedürfnis, aber ich bezweifle es.

Sehen Sie sich git_split Projekt unter https://github.com/vangorra/git_split

Schalten git Verzeichnisse in ihre ganz eigenen Repositories in ihrer eigenen Lage. Kein Teilbaum lustiges Geschäft. Dieses Skript wird ein vorhandenes Verzeichnis in Ihrem Git Repository übernehmen und das Verzeichnis in eine eigenständige Repository seines eigenen machen. Auf dem Weg dorthin wird es die gesamte Änderungshistorie für das Verzeichnis kopieren, über Sie zur Verfügung gestellt.

./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
        src_repo  - The source repo to pull from.
        src_branch - The branch of the source repo to pull from. (usually master)
        relative_dir_path   - Relative path of the directory in the source repo to split.
        dest_repo - The repo to push to.

Setzen Sie diese in Ihre gitconfig:

reduce-to-subfolder = !sh -c 'git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter cookbooks/unicorn HEAD && git reset --hard && git for-each-ref refs/original/ | cut -f 2 | xargs -n 1 git update-ref -d && git reflog expire --expire=now --all && git gc --aggressive --prune=now && git remote rm origin'

Ich bin sicher, dass git subtree alles schön und wunderbar, aber meine Unterverzeichnisse von git verwalteten Code, die ich war alles in Eclipse bewegen wollte. Also, wenn Sie egit verwenden, ist es schmerzlich einfach. Nehmen Sie das Projekt, das Sie verschieben möchten, und team-> trennen, und dann team-> teilen Sie es an die neue Position. Es wird versucht, die alte Repo-Position Standard zu verwenden, aber Sie können die Verwendung bestehende Auswahl deaktivieren und den neuen Ort wählen, um es zu bewegen. Alle Hagel egit.

Ich habe ziemlich straight forward Lösung gefunden, Die Idee ist, Repository zu kopieren und dann nur unnötigen Teil entfernen. Dies ist, wie es funktioniert:

1) ein Repository klonen Sie möchten aufzuspalten

git clone git@git.thehost.io:testrepo/test.git

2) verschieben zu git Ordner

cd test/

2) nicht mehr benötigte Ordner entfernen und sich verpflichten, es

rm -r ABC/
git add .
enter code here
git commit -m 'Remove ABC'

3) Entfernen Sie unnötige Ordner (n) Form Geschichte mit BFG

cd ..
java -jar bfg.jar --delete-folders "{ABC}" test
cd test/
git reflog expire --expire=now --all && git gc --prune=now --aggressive
  

für mehrfach Ordner können Sie Komma

java -jar bfg.jar --delete-folders "{ABC1,ABC2}" metric.git

4) Überprüfen Sie, dass die Geschichte enthält nicht die Dateien / Ordner, die Sie gerade gelöscht

git log --diff-filter=D --summary | grep delete

5) Jetzt haben Sie sauber Repository ohne ABC, so einfach in neue Herkunft schieben

remote add origin git@github.com:username/new_repo
git push -u origin master

Das ist es. Sie können diesen Schritt wiederholen, ein anderes Repository zu bekommen,

entfernen Sie einfach XY1, XY2 und umbenennen XYZ -> ABC auf Schritt 3

Sie können ganz einfach versuchen, die https://help.github.com/enterprise/2.15/user/articles/splitting-a-subfolder-out-into-a-new-repository/

Das funktionierte für mich. Die Fragen, die ich in den Schritten konfrontiert oben angegebenen Werte sind

  1. in diesem Befehl git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME Die BRANCH-NAME ist Master

  2. , wenn der letzte Schritt fehlschlägt, wenn aufgrund Schutz Ausgabe folgen zu begehen - https://docs.gitlab.com/ee/user/project/protected_branches.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top