Trennen (verschieben) Sie das Unterverzeichnis in ein separates Git-Repository
-
21-08-2019 - |
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/
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.
-
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)
-
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
-
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 solltegit 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 Siegit tag -l | xargs git tag -d
. -
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
-
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.
-
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 Ordnersubproject
MUSS alssubproject
ü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 Ordnerpath1\path2\subproject
MUSS alspath1/path2/subproject
geben werden -
Erstellen Sie die neue Repo
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
-
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
-
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:
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.
-
Sie den Klon und die Filter:
git clone --no-hardlinks foo bar; cd bar git filter-branch --subdirectory-filter subdir/you/want
-
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
-
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 sub1
and sub2
sagen) in ein neues Git Repository.
Der einfache Weg ™ (mehrere Unterordner)
-
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 Ordnersubproject
MUSS alssubproject
ü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 Namenpath1\path2\subproject
MUSS alspath1/path2/subproject
geben werden. Darüber hinaus verwenden Sie nichtmv
command abermove
.Abschließender Hinweis: der einzigartige und großer Unterschied mit der Basis Antwort ist die zweite Zeile des Skripts "
git filter-branch...
" -
Erstellen Sie die neue Repo
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
-
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
-
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.
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
So fügen Sie Paul Antwort , ich fand schließlich Raum zu erholen, muss ich HEAD zu einem sauberen Repository schieben und dass trimmt, um die Größe des .git / Objekte / Pack-Verzeichnis.
d.
$ mkdir ...ABC.git $ cd ...ABC.git $ git init --bare
Nach der gc Pflaume, auch tun:
$ git push ...ABC.git HEAD
Dann können Sie tun
$ git clone ...ABC.git
und die Größe des ABC / .git reduziert
Eigentlich einige der Zeitschritte aufwendig (z git gc) nicht mit dem Push benötigt Repository zu reinigen, das heißt:.
$ git clone --no-hardlinks /XYZ /ABC $ git filter-branch --subdirectory-filter ABC HEAD $ git reset --hard $ git push ...ABC.git HEAD
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:
- klonen Remote-Repo in ein anderes Verzeichnis
- mit
git filter-branch
links nur Dateien unter einem Unterverzeichnis, drücken Sie auf neue Remote - 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:
- Klonen Sie das Multi-Modul-Projekt lokal
- Branchen - prüfen, was da:
git branch -a
- Sie an jedem Zweig eine Kasse im Split aufgenommen werden, um eine lokale Kopie auf Ihrer Workstation zu erhalten:
git checkout --track origin/branchABC
- Erstellen Sie eine Kopie in einem neuen Verzeichnis:
cp -r oldmultimod simple
- Gehen Sie in das neue Projekt kopieren:
cd simple
- Sie sich von den anderen Modulen befreien, die noch nicht in diesem Projekt benötigt werden:
-
git rm otherModule1 other2 other3
- Geben Sie nun nur die subdir des Zielmoduls bleibt
- Sie sich von dem Modul subdir befreien, so dass das Modul root das neue Projekt root wird
-
git mv moduleSubdir1/* .
- Löschen Sie die Reliquie subdir:
rmdir moduleSubdir1
- Überprüfen Sie Änderungen an einem beliebigen Punkt:
git status
- Erstellen Sie die neue git Repo und kopieren Sie die URL dieses Projekt in sie Punkt:
-
git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
- Stellen Sie sicher, das ist gut:
git remote -v
- Drücken Sie die Änderungen bis zum Remote-Repo:
git push
- Gehen Sie auf die Remote-Repo und überprüfen es ist alles da
- 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:
- Erstellen Sie Ihr neues Repository:
MyTeam/mynewrepo
Bash Prompt:
-
$ cd c:/Dir1
-
$ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
Zurückgegeben:Ref 'refs/heads/master' was rewritten
(FYI:. Dir2 / dir3 Groß- und Kleinschreibung) -
$ git remote add some_name git@github.com:MyTeam/mynewrepo.git
git remote add origin etc
. hat nicht funktioniert, kehrte "remote origin already exists
" -
$ 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
-
git splits
. Ich habe es als git Erweiterung, basierend auf jkeating Lösung . -
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 -
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
-
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
-
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
Öffnen Git Bash.
Ändern Sie den Strom an den Standort Arbeitsverzeichnis, in dem Sie Ihr neues Repository erstellen möchten.
das Repository-Klon, der den Unterordner enthält.
git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
- ändern Sie das aktuelle Arbeitsverzeichnis zu Ihrem geklonten Repository.
cd REPOSITORY-NAME
- 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 begrenzenBRANCH-NAME
. Der Standardzweig für Ihr aktuelles Projekt, zum Beispielmaster
odergh-pages
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
-
in diesem Befehl
git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME
DieBRANCH-NAME
ist Master -
, wenn der letzte Schritt fehlschlägt, wenn aufgrund Schutz Ausgabe folgen zu begehen - https://docs.gitlab.com/ee/user/project/protected_branches.html