تقسيم الدليل الفرعي مع العارض الفرعي إلى مستودع GIT منفصل
-
25-09-2019 - |
سؤال
كمجموعة فرعية من السؤال detach-subdirectory تم تقديمه بالفعل من قبل وبالنظر إلى حقيقة أنه على الرغم من أن الكثير من الأسئلة قد تم طرحها حول عملية تقسيم ودمج مستودعات GIT ، إلا أنني لم أتمكن من العثور على موضوع يمس موضوع الانقسام عند وجود علامات فرعية.
لذلك في السيناريو التالي:
.git/
.gitmodules
folder/
data/
content/
other_data/
submoduleA/
submoduleB/
أود الحصول على مستودعين مع الهيكل التالي:
.git/
data/
و
.git/
.gitmodules
content/
other_data/
submoduleA/
submoduleB/
الحالة الأولى ليست مشكلة ويمكن حلها بسهولة مع الطريقة الموضحة في detach-subdirectory.
الثاني ليس كثيرا. وجود عروض فرعية وحقيقة أن .gitmodules يحتوي على المسار الكامل ل folder/content/submoduleA
و folder/content/submoduleB
يسبب جزء من التاريخ غير متناسق لأن .gitmodules يشير إلى بنية دليل غير موجودة (بمجرد استخدام فرع المرشح).
لذلك أود أن أعرف ما إذا كانت هناك طريقة للقيام بذلك دون التسبب في تاريخ غير متناسق.
المحلول
أظن (لم يختبر) أن ثانية git filter-branch
سيكون لديك الفرصة لتعديل .gitmodules
محتوى لكل ارتباط من الريبو الجديد.
ولكن في الواقع أ git submodule split
كان الأمر في المناقشة في أوائل عام 2009.
الاستخدام المقترح:
git submodule split [--url submodule_repo_url] submodule_dir \
[alternate_dir...]
يحل محل
submodule_dir
مع وحدة فرعية تم إنشاؤها حديثًا ، مع الحفاظ على كل تاريخsubmodule_dir
.
يعيد هذا الأمر أيضًا كتابة كل التزام في تاريخ المستودع الحالي لتضمين المراجعة الصحيحة لـsumodule_dir
والمناسبة.gitmodules
إدخالات.
ومع ذلك ، لا أراه في أحدث ما يطبخ.
يمكن أن يمنحك البرنامج النصي في التصحيح المقترح فكرة عن نوع إعادة كتابة الأشجار اللازمة لتحديث .gitmodules
ملف رغم ذلك.
نصائح أخرى
لقد واجهت نفس المشكلة بالضبط التي تمكنت من حلها وتمكنت من حلها مع الإجراء التالي:
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
كما ترى ، فإن الحيلة هي إعادة تسمية مؤقتًا .gitmodules
الملف والاستخدام sed
لإعادة كتابة محتواها. يمكنك الحصول على كل التفاصيل و سياق هذا الإجراء على مدونتي.
لتوضيح إجابة كيفن: على افتراض أنه لم تكن هناك أي منها فرعي في الخارج cool/cavemen
- المجلد الذي يتم فصله (وإلا سيكون هناك حاجة إلى تحرير أكثر تفصيلاً لـ .gitmodules لإزالة تلك الأقسام الإضافية) ، ويمكن تحقيق ذلك كثير أسرع وفي خطوة واحدة باستخدام 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
كميزة إضافية ، إذا cool/cavemen
لم تكن موجودة في كل مراجعة أو فرع فقط تلك المراجعات أو الفروع التي تحتوي cool/cavemen
سيتم النظر إليه.
إذا كان هذا هو الحال ، فقد ترغب في تشغيل ما يلي لإزالة المراجع التي لم تتغير:
$ 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