Aufteilung eines Unterverzeichnisses mit Submodule in ein separates Git -Repository
-
25-09-2019 - |
Frage
Als Teilmenge der Frage Abschlüsse Bereits zuvor gemacht und unter Berücksichtigung der Tatsache, dass ich, obwohl viele Fragen zur Aufteilung und Verschmelzung von Git -Repositorys gestellt wurden, nicht finden konnte, das das Thema der Aufteilung berührt, wenn Submodule vorhanden sind.
Also im folgenden Szenario:
.git/
.gitmodules
folder/
data/
content/
other_data/
submoduleA/
submoduleB/
Ich möchte zwei Repositorys mit der folgenden Struktur bekommen:
.git/
data/
und
.git/
.gitmodules
content/
other_data/
submoduleA/
submoduleB/
Der erste Fall ist kein Problem und kann mit der in beschriebenen Methode leicht gelöst werden Abschlüsse.
Die zweite nicht so sehr. Die Existenz von Submodules und die Tatsache, dass .Gitmodules den vollen Weg für folder/content/submoduleA
und folder/content/submoduleB
bewirkt, dass ein Teil der Geschichte inkonsistent ist, da sich .gitmodules auf eine nicht vorhandene Verzeichnisstruktur bezieht (sobald die Filterbranch verwendet wird).
Ich würde gerne wissen, ob es eine Möglichkeit gibt, dies zu tun, ohne eine inkonsistente Geschichte zu verursachen.
Lösung
Ich vermute (nicht getestet), dass eine Sekunde git filter-branch
hätte die Möglichkeit, die zu ändern .gitmodules
Inhalt für jeden Commit des neuen Repo.
Aber eigentlich ein git submodule split
Das Kommando war Anfang 2009 in Diskussion.
Vorgeschlagene Verwendung:
git submodule split [--url submodule_repo_url] submodule_dir \
[alternate_dir...]
Ersetzen
submodule_dir
mit einem neu geschaffenen Submodul, die die gesamte Geschichte von behaltensubmodule_dir
.
Dieser Befehl schreibt auch jeden Commit im aktuellen Repository -Verlauf um, um die korrekte Überarbeitung von zu enthaltensumodule_dir
und die angemessen.gitmodules
Einträge.
Ich sehe es jedoch nicht in der LETZT, was kocht.
Das Skript im vorgeschlagenen Patch kann Ihnen eine Vorstellung von der Art des Umschreibens für die Aktualisierung des Baumes geben .gitmodules
Datei jedoch.
Andere Tipps
Ich hatte genau das gleiche Problem wie Unode und gelang es, es mit der folgenden Prozedur zu lösen:
git clone git@github.com:kdeldycke/kev-code.git
cd kev-code
git filter-branch --tree-filter "test -f ./.gitmodules && mv ./.gitmodules ./cool-cavemen/gitmodules || echo 'No .gitmodules file found'" -- --all
git filter-branch --force --prune-empty --subdirectory-filter cool-cavemen --tag-name-filter cat -- --all init..HEAD
git filter-branch --force --tree-filter "test -f ./gitmodules && mv ./gitmodules ./.gitmodules || echo 'No gitmodules file found'" -- --all
git filter-branch --force --tree-filter "test -f ./.gitmodules && sed -i 's/cool-cavemen\///g' ./.gitmodules || echo 'No .gitmodules file found'" -- --all
git remote rm origin
rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune
git remote add origin git@github.com:kdeldycke/cool-cavemen.git
git push -u origin master --force --tags
Wie Sie sehen, besteht der Trick darin, die vorübergehend umzubenennen .gitmodules
Datei und Verwendung sed
Um seinen Inhalt neu zu schreiben. Sie können alle Details und die erhalten Kontext dieses Prozesses in meinem Blog.
Um Kevins Antwort zu erläutern: Angenommen, es gab keine Submodules jemals draußen cool/cavemen
- Der Ordner, der abgelöst wird (ansonsten aufwändigere Bearbeitung von .gitmodules wird benötigt, um diese zusätzlichen Abschnitte zu entfernen), kann dies erreicht werden viel schneller und in einem Schritt mit einem index-filter
:
$ git filter-branch --subdirectory-filter cool/cavemen --index-filter $'
hash=$(git rev-parse --verify $GIT_COMMIT:.gitmodules 2>/dev/null) &&
git update-index --add --cacheinfo 100644 $(git cat-file -p $hash |
sed \'s/cool\\/cavemen\\///g\' | git hash-object -w --stdin) .gitmodules ||
true' --tag-name-filter cat --prune-empty -- --all
Als zusätzlicher Vorteil, wenn cool/cavemen
existierte nicht in jeder Revision oder Niederlass cool/cavemen
wird betrachtet.
Wenn dies der Fall ist, möchten Sie möglicherweise Folgendes ausführen, um unveränderte Referenzen zu entfernen:
$ git for-each-ref --format='%(refname)' |
grep -vF "$(git for-each-ref --format='%(refname)' refs/original |
sed 's/refs\/original\///g')" | xargs -n 1 git update-ref -d