Diese Frage basiert auf dem Unterverzeichnis Detach in ein separates Git-Repository
Anstatt ein einzelnes Unterverzeichnis zu trennen, möchte ich ein Paar trennen. Zum Beispiel sieht mein aktueller Verzeichnisbaum folgendermaßen aus:
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ
Und ich möchte stattdessen Folgendes:
/apps
/AAA
/libs
/XXX
Das --subdirectory-filter
Argument, git filter-branch
nicht zu funktionieren, weil es beim ersten Ausführen alles außer dem angegebenen Verzeichnis entfernt. Ich dachte, die Verwendung des --index-filter
Arguments für alle unerwünschten Dateien würde funktionieren (wenn auch mühsam), aber wenn ich versuche, es mehrmals auszuführen, wird die folgende Meldung angezeigt:
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
Irgendwelche Ideen? TIA
quelle
--tag-name-filter cat
zu Ihren Parametern hinzufügenManuelle Schritte mit einfachen Git-Befehlen
Es ist geplant, einzelne Verzeichnisse in eigene Repos aufzuteilen und diese dann zusammenzuführen. In den folgenden manuellen Schritten wurden keine Geek-to-Use-Skripte verwendet, sondern leicht verständliche Befehle. Sie können dazu beitragen, zusätzliche N Unterordner in einem anderen Repository zusammenzuführen.
Teilen
Nehmen wir an, Ihr ursprüngliches Repo lautet: original_repo
1 - Geteilte Apps:
2 - Geteilte Bibliotheken
Fahren Sie fort, wenn Sie mehr als 2 Ordner haben. Jetzt haben Sie zwei neue und temporäre Git-Repository.
Erobern Sie, indem Sie Apps und Bibliotheken zusammenführen
3 - Bereiten Sie das brandneue Repo vor:
Und Sie müssen mindestens ein Commit durchführen. Wenn die folgenden drei Zeilen übersprungen werden sollen, wird Ihr erstes Repo unmittelbar unter dem Stammverzeichnis Ihres Repos angezeigt:
Wenn die temporäre Datei festgeschrieben ist, wird der
merge
Befehl im späteren Abschnitt wie erwartet gestoppt.Unter von Benutzer-Feedback, stattdessen eine zufällige Datei hinzuzufügen , wie
a_file_and_make_a_commit
können Sie wählen , eine hinzuzufügen.gitignore
, oderREADME.md
usw.4 - Apps zuerst zusammenführen repo:
Jetzt sollte das Apps- Verzeichnis in Ihrem neuen Repository angezeigt werden.
git log
sollte alle relevanten historischen Commit-Nachrichten anzeigen.Hinweis: wie Chris unten in den Kommentaren erwähnt, für neuere Version (> = 2.9) von git, müssen Sie angeben ,
--allow-unrelated-histories
mitgit merge
5 - Merge libs repo als nächstes auf die gleiche Weise zusammenführen:
Fahren Sie fort, wenn Sie mehr als 2 Repos zusammenführen möchten.
Referenz: Führen Sie ein Unterverzeichnis eines anderen Repositorys mit git zusammen
quelle
.gitignore
undREADME.md
Dateien hinzufügt .git merge .. git read-tree
Schritt hinzugefügten Dateien zu unterbrechen, da er sie als neu hinzugefügte Dateien aufzeichnet und alle meine Git-Guis keine Verbindung zu ihren früheren Commits herstellen.Warum sollten Sie
filter-branch
mehr als einmal laufen wollen ? Sie können alles in einem Durchgang ausführen, sodass Sie es nicht erzwingen müssen (beachten Sie, dass Sieextglob
es in Ihrer Shell aktivieren müssen, damit dies funktioniert):Dies sollte alle Änderungen in den unerwünschten Unterverzeichnissen beseitigen und alle Ihre Zweige und Commits beibehalten (es sei denn, sie wirken sich nur auf Dateien in den beschnittenen Unterverzeichnissen aus
--prune-empty
) - kein Problem mit doppelten Commits usw.Nach diesem Vorgang werden die unerwünschten Verzeichnisse als nicht verfolgt von aufgelistet
git status
.Das
$(ls ...)
ist notwendigextglob
, wenn es von Ihrer Shell anstelle dessh
Indexfilters ausgewertet wird, der das eingebaute verwendeteval
(woextglob
nicht verfügbar). Siehe Wie aktiviere ich Shell-Optionen in Git? für weitere Details dazu.quelle
git
Befehle stützt , und ist daher nicht so anfällig für Unterschiede in derls
Interpretation der Betriebssysteme, wie @Bae herausgefunden hat.Beantwortung meiner eigenen Frage hier ... nach viel Versuch und Irrtum.
Ich habe es geschafft, dies mit einer Kombination aus
git subtree
und zu tungit-stitch-repo
. Diese Anweisungen basieren auf:Zuerst zog ich die Verzeichnisse heraus, die ich in ihrem eigenen separaten Repository aufbewahren wollte:
Ich habe dann ein neues leeres Repository erstellt und die letzten beiden importiert / zusammengefügt:
Dies schafft zwei Zweige,
master-A
undmaster-B
, die jeweils den Inhalt eines des genähten repos halten. Um sie zu kombinieren und aufzuräumen:Jetzt bin ich mir nicht ganz sicher, wie / wann dies geschieht, aber nach dem ersten
checkout
und dempull
geht der Code auf magische Weise in den Hauptzweig über (jeder Einblick in das, was hier vor sich geht, ist willkommen!).Alles scheint wie erwartet gearbeitet zu haben, mit der Ausnahme , dass , wenn ich den Blick durch die
newRepo
Geschichte begehen, es Duplikate sind , wenn die changeset beide betroffenapps/AAA
undlibs/XXX
. Wenn es eine Möglichkeit gibt, Duplikate zu entfernen, ist dies perfekt.quelle
export PERL5LIB="$PERL5LIB:/usr/local/git/lib/perl5/site_perl/"
meine Bash-Konfiguration hinzufügen musste , damit es Git.pm finden konnte. Dann habe ich es mit cpan installiert.git subtree add
, diese Aufgabe auszuführen. Siehe stackoverflow.com/a/58253979/1894803Ich habe einen Git-Filter geschrieben, um genau dieses Problem zu lösen. Es hat den fantastischen Namen git_filter und befindet sich hier bei github:
https://github.com/slobobaby/git_filter
Es basiert auf dem exzellenten libgit2.
Ich musste ein großes Repository mit vielen Commits (~ 100000) aufteilen, und die Ausführung der auf git filter-branch basierenden Lösungen dauerte mehrere Tage. git_filter benötigt eine Minute, um dasselbe zu tun.
quelle
Verwenden Sie die Git-Erweiterung "Git Splits"
git splits
ist ein Bash-Skript, das ein Wrapper istgit branch-filter
, den ich als Git-Erweiterung erstellt habe, basierend auf der Lösung von jkeating .Es wurde genau für diese Situation gemacht. Verwenden Sie für Ihren Fehler die
git splits -f
Option, um das Entfernen der Sicherung zu erzwingen. Dagit splits
in einem neuen Zweig gearbeitet wird, wird Ihr aktueller Zweig nicht neu geschrieben, sodass die Sicherung irrelevant ist. Weitere Informationen finden Sie in der Readme-Datei. Verwenden Sie sie auf einer Kopie / einem Klon Ihres Repos (nur für den Fall!) .git splits
.Teilen Sie die Verzeichnisse in einen lokalen Zweig auf
#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 apps/AAA libs/ZZZ
Erstellen Sie irgendwo ein leeres Repo. Wir gehen davon aus, dass wir
xyz
auf GitHub ein leeres Repo mit dem folgenden Pfad erstellt haben:[email protected]:simpliwp/xyz.git
Zum neuen Repo drücken.
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz [email protected]:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master
Klonen Sie das 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 [email protected]:simpliwp/xyz.git
quelle
quelle
for
Schleife ist eine Bestätigung wert, da andere ähnliche Antworten sie nicht enthalten. Wenn Sie nicht über eine lokale Kopie jedes Zweigs in Ihrem Klon verfügen,filter-branch
werden diese beim Umschreiben nicht berücksichtigt. Dies kann möglicherweise Dateien ausschließen, die in anderen Zweigen eingeführt, aber noch nicht mit Ihrem aktuellen Zweig zusammengeführt wurden. (Obwohl es sich auch lohnt, einegit fetch
Filiale zu machen, die Sie zuvor ausgecheckt haben, um sicherzustellen, dass sie aktuell bleibt.)Eine einfache Lösung: Git-Filter-Repo
Ich hatte ein ähnliches Problem und nachdem ich die verschiedenen hier aufgeführten Ansätze überprüft hatte, entdeckte ich Git-Filter-Repo . Es wird als Alternative zum Git-Filter-Zweig in der offiziellen Git-Dokumentation hier empfohlen .
Verwenden Sie den folgenden Befehl, um ein neues Repository aus einer Teilmenge von Verzeichnissen in einem vorhandenen Repository zu erstellen:
Filtern Sie mehrere Dateien / Ordner, indem Sie sie verketten:
Um die ursprüngliche Frage zu beantworten , benötigen Sie mit git-filter-repo nur den folgenden Befehl:
quelle
Ja. Erzwingen Sie das Überschreiben der Sicherung, indem Sie bei
-f
nachfolgenden Aufrufen das Flag verwendenfilter-branch
, um diese Warnung zu überschreiben. :) Ansonsten denke ich, dass Sie die Lösung haben (dh ein unerwünschtes Verzeichnis gleichzeitig mit löschenfilter-branch
).quelle
Löschen Sie die Sicherung im Verzeichnis .git in refs / original, wie in der Nachricht vorgeschlagen. Das Verzeichnis ist ausgeblendet.
quelle