سؤال

لدي بوابة المستودع الذي يحتوي على عدد من الدلائل.الآن لقد وجدت أن واحدة من الدلائل ليست لها علاقة إلى أخرى و يجب أن تكون منفصلة منفصلة مستودع.

كيف يمكن أن أفعل هذا مع الحفاظ على التاريخ من الملفات في دليل فرعي?

أعتقد أنني يمكن أن تجعل من استنساخ وإزالة الأجزاء غير المرغوب فيها من كل استنساخ, ولكن أعتقد أن هذا من شأنه أن يعطي لي شجرة كاملة عند التحقق من السن تنقيح الخ.هذا قد يكون مقبولا, ولكن أنا أفضل أن تكون قادرة على التظاهر أن اثنين من مستودعات ليس لديها تاريخ مشترك.

فقط أن تجعل من الواضح لدي الهيكل التالي:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

ولكن أود أن مثل هذا بدلا من ذلك:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/
هل كانت مفيدة؟

المحلول

التحديث:هذه العملية هي شائعة جدا ، أن بوابة فريق جعلت الأمر أسهل بكثير مع أداة جديدة ، git subtree.انظر هنا: فصل (نقل) فرعي في فصل Git


تريد استنساخ المستودع الخاص بك ومن ثم استخدام git filter-branch بمناسبة ولكن كل شيء فرعي في جديدة الريبو إلى أن القمامة التي تم جمعها.

  1. إلى استنساخ مستودع المحلية:

    git clone /XYZ /ABC
    

    (ملاحظة:مستودع سيتم استنساخ باستخدام بجد روابط, ولكن هذا ليس مشكلة منذ الصعب ربط الملفات لن يتم تعديل في أنفسهم - جديدة سيتم إنشاؤها.)

  2. الآن, دعونا نحفظ مثيرة للاهتمام الفروع التي نريد كتابة أيضا ، ومن ثم إزالة بلد المنشأ إلى تجنب دفع إلى هناك للتأكد من أن القديم يرتكب لن يتم الرجوع إليها بواسطة المنشأ:

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

    أو لجميع الفروع عن بعد:

    cd /ABC
    for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done
    git remote rm origin
    
  3. الآن قد ترغب أيضا إزالة العلامات التي لا علاقة مع فرعي;يمكنك أيضا القيام بذلك في وقت لاحق ، ولكن قد تحتاج إلى تقليم الريبو الخاص بك مرة أخرى.أنا لم تفعل ذلك و حصلت على WARNING: Ref 'refs/tags/v0.1' is unchanged جميع العلامات (منذ أنهم جميعا لا علاقة لها فرعي);بالإضافة إلى ذلك, بعد إزالة هذه العلامات أكثر سوف تكون المساحة المستصلحة.على ما يبدو git filter-branch يجب أن تكون قادرة على كتابة العلامات الأخرى, ولكن أنا لا يمكن التحقق من هذا.إذا كنت ترغب في إزالة جميع العلامات استخدام git tag -l | xargs git tag -d.

  4. ثم استخدام فلتر-فرع إعادة تعيين إلى استبعاد الملفات الأخرى, حتى أنها يمكن أن تكون مجردة.دعونا أيضا إضافة --tag-name-filter cat --prune-empty لإزالة فارغة يرتكب كتابة الكلمات (لاحظ أن هذا سوف تضطر إلى قطاع التوقيع):

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

    أو بدلا من ذلك, فقط كتابة رئيس فرع تجاهل العلامات الفروع الأخرى:

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
    
  5. ثم حذف النسخ الاحتياطي reflogs حتى الفضاء يمكن أن يكون حقا المستصلحة (على الرغم من الآن العملية المدمرة)

    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
    

    والآن لديك المحلية git من حروف sub-directory مع كل تاريخها الحفاظ عليها.

ملاحظة:بالنسبة لمعظم الاستخدامات ، git filter-branch ينبغي أن يكون في الواقع إضافة المعلمة -- --all.نعم هذا هو حقا --الفضاء-- all.هذا يحتاج إلى أن يكون آخر معلمات الأوامر.كما ماتلي اكتشف هذا يبقى المشروع فروع العلامات المدرجة في الريبو.

تحرير:اقتراحات مختلفة من التعليقات أدناه أدرجت للتأكد ، على سبيل المثال ، أن المخزون هو في الواقع تقلصت (الذي لم يكن الحال دائما من قبل).

نصائح أخرى

طريقة سهلة Tm

اتضح أن هذا هو ومفيدة ممارسة الأسياد من بوابة جعلت من السهل حقا ، ولكن يجب أن يكون لديك إصدار أحدث من بوابة (>= 1.7.11 أيار / مايو 2012).ترى التذييل كيفية تثبيت أحدث بوابة.أيضا هناك الأمثلة في العالم الحقيقي في تجول أدناه.

  1. إعداد القديمة الريبو

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

    ملاحظة: <name-of-folder> يجب أن لا يحتوي الرائدة أو أحرف زائدة.على سبيل المثال, المجلد المسمى subproject يجب أن يتم تمرير مثل subproject, لا ./subproject/

    ملاحظة لمستخدمي ويندوز: عندما الخاص بك مجلد عمق من 1 > ، <name-of-folder> يجب أن يكون *nix نمط فاصل المجلد (/).على سبيل المثال, المجلد المسمى path1\path2\subproject يجب أن يتم تمرير مثل path1/path2/subproject

  2. إنشاء جديد الريبو

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. الرابط الجديد الريبو إلى جيثب أو في أي مكان

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. تنظيف ، إذا رغبت في ذلك

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

    ملاحظة:هذا يترك كل المراجع التاريخية في مستودع.ترى التذييل أدناه إذا كنت فعلا تشعر بالقلق إزاء ارتكاب كلمة المرور أو تحتاج إلى تقليل حجم الملف الخاص بك .git المجلد.

...

تجول

هذه هي نفس الخطوات أعلاه, ولكن بعد الخطوات الدقيقة لبلدي مستودع بدلا من استخدام <meta-named-things>.

هنا هو مشروع يجب تنفيذ جافا سكريبت في المتصفح وحدات في عقدة:

tree ~/Code/node-browser-compat

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

أريد أن تقسيم مجلد واحد ، btoa, في فصل git

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

لدي الآن الفرع الجديد ، btoa-only, هذا فقط قد يرتكب من أجل btoa و أريد إنشاء المستودع الجديد.

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

أنا القادم إنشاء جديد الريبو على جيثب أو bitbucket ، أو أيا كان وإضافة هو origin (راجع للشغل, "الأصل" هو مجرد الاتفاقية ليست جزءا من القيادة - هل يمكن أن نسميها "عن بعد ملقم" أو ما تريد)

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

يوم سعيد!

ملاحظة: إذا قمت بإنشاء الريبو مع README.md, .gitignore و LICENSE, سوف تحتاج إلى سحب الأولى:

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

وأخيرا, سوف تحتاج إلى إزالة المجلد من أكبر الريبو

git rm -rf btoa

...

التذييل

أحدث بوابة على OS X

للحصول على أحدث إصدار من بوابة:

brew install git

للحصول على الشراب لمدة OS X:

http://brew.sh

أحدث بوابة على أوبونتو

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

إذا كان هذا لا يعمل (لديك نسخة قديمة جدا من أوبونتو) ، في محاولة

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

إذا كان هذا لا يزال لا يعمل, حاول

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

بفضل روي.اروجو من التعليقات.

مسح التاريخ

بشكل افتراضي إزالة الملفات من بوابة الواقع لا إزالتها من بوابة ، فقط يرتكب أنها لم تعد موجودة الآن.إذا كنت تريد فعلا إزالة المراجع التاريخية (أيلديك ارتكب كلمة المرور), كنت بحاجة للقيام بذلك:

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

بعد ذلك يمكنك التحقق من هذا الملف أو المجلد لم يعد يظهر في بوابة التاريخ على الإطلاق

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

ومع ذلك ، لا يمكن "دفع" حذف على جيثب وما شابه ذلك.إذا كنت تحاول سوف تحصل على خطأ وعليك أن git pull قبل أن تتمكن من git push - ثم عدت إلى وجود كل شيء في التاريخ.

حتى إذا كنت ترغب في حذف التاريخ من "الأصل" - معنى لحذفه من جيثب ، bitbucket ، وما إلى ذلك - سوف تحتاج إلى حذف إعادة الشراء وإعادة دفع مجردة نسخة من الريبو.ولكن مهلا - هناك المزيد!- إذا كنت قلقا حقا حول التخلص من كلمة سر أو شيء من هذا القبيل سوف تحتاج إلى تقليم النسخ الاحتياطي (انظر أدناه).

مما يجعل .git أصغر

المذكور حذف محفوظات الأوامر لا يزال يترك وراءه مجموعة من ملفات النسخ الاحتياطي - لأن بوابة جدا في مساعدتك على أن لا تدمر الريبو الخاص بك عن طريق الصدفة.فإنه في نهاية المطاف حذف ملفات الأيتام على مدى الأيام والشهور ، لكنه يترك لهم هناك لفترة من الوقت في حال كنت أدرك أن كنت قد حذفت بطريق الخطأ شيء كنت لا تريد.

حتى إذا كنت تريد حقا أن إفراغ سلة المهملات إلى تقليل حجم استنساخ من الريبو مباشرة عليك أن تفعل كل هذا غريب حقا الاشياء:

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

وقال أنصح عدم تنفيذ هذه الخطوات إلا إذا كنت تعرف أن كنت بحاجة إلى - فقط في حال كنت لم تقليم الخطأ فرعي, أتعلمين ؟ ملفات النسخ الاحتياطي لا ينبغي أن تحصل على المستنسخة عند الضغط على الريبو ، وأنها سوف تكون فقط في النسخة المحلية.

الائتمان

بولس الجواب يخلق مستودع جديد يحتوي على / ABC، ولكنه لا يزيل / ABC من داخل / XYZ. يقوم الأمر التالي إزالة / ABC من داخل / XYZ:

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

وبطبيعة الحال، اختبار في "استنساخ -ما لا-hardlinks" مستودع لأول مرة، ومتابعته مع إعادة تعيين، القيادة العامة وأوامر تقليم يعدد بولس.

لقد وجدت أنه صحيح من أجل حذف القديم التاريخ من جديد مستودع, عليك أن تفعل أكثر من ذلك بقليل العمل بعد filter-branch الخطوة.

  1. هل استنساخ و التصفية:

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. إزالة كل إشارة إلى التاريخ القديم."الأصل" كانت تتبع الخاص بك استنساخ ، و "الأصلي" هو المكان تصفية فرع يحفظ الاشياء القديمة:

    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. حتى إن التاريخ قد تكون عالقة في packfile أن fsck لن تعمل باللمس.تمزق إلى أشلاء ، وخلق جديد packfile وحذف غير المستخدمة:

    git repack -ad
    

هناك تفسير هذا في دليل تصفية فرع.

وأضاف النصي باش

:

تحرير.

والأجوبة الواردة هنا عملت فقط جزئيا بالنسبة لي. ظلت الكثير من الملفات الكبيرة في ذاكرة التخزين المؤقت. ما عملت أخيرا (بعد ساعات في #git على فرينود):

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

ومع الحلول السابقة، كان حجم المستودع نحو 100 MB. هذا واحد انها جلبت الى 1.7 MB. ربما يساعد شخص ما:)


والسيناريو باش التالية بأتمتة مهمة:

!/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

هنا هو تعديل صغير على CoolAJ86's "طريقة سهلة tm" الجواب من أجل تقسيم متعددة المجلدات الفرعية (دعنا نقول sub1و sub2) إلى git.

طريقة سهلة tm (متعددة المجلدات الفرعية)

  1. إعداد القديمة الريبو

    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
    

    ملاحظة: <name-of-folder> يجب أن لا يحتوي الرائدة أو أحرف زائدة.على سبيل المثال, المجلد المسمى subproject يجب أن يتم تمرير مثل subproject, لا ./subproject/

    ملاحظة لمستخدمي ويندوز: عندما الخاص بك مجلد عمق من 1 > ، <name-of-folder> يجب أن يكون *nix نمط فاصل المجلد (/).على سبيل المثال, المجلد المسمى path1\path2\subproject يجب أن يتم تمرير مثل path1/path2/subproject.وعلاوة على ذلك لا تستخدم mvالأمر ولكن move.

    ملاحظة أخيرة: فريدة من نوعها و فرق كبير مع قاعدة الجواب هو السطر الثاني من النص "git filter-branch..."

  2. إنشاء جديد الريبو

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. الرابط الجديد الريبو إلى جيثب أو في أي مكان

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. تنظيف ، إذا رغبت في ذلك

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

    ملاحظة:هذا يترك كل المراجع التاريخية في مستودع.ترى التذييل في إجابة الأصلي إذا كنت فعلا تشعر بالقلق إزاء ارتكاب كلمة المرور أو تحتاج إلى تقليل حجم الملف الخاص بك .git المجلد.

والسؤال الأصلي يريد XYZ / ABC / (* الملفات) لتصبح ABC / ABC / (* الملفات). بعد تنفيذ إجابة مقبولة لرمز بلدي، وأنا لاحظت أنه في الواقع تغيير (ملفات *) XYZ / ABC / في (ملفات *) ABC /. الصفحة رجل تصفية فرع حتى يقول:

<اقتباس فقرة>   

وسوف يتضمن نتيجة هذا الدليل (وهذا فقط) <م> كجذر مشروعها ".

وبعبارة أخرى، فإنه يعزز مجلد المستوى الأعلى "حتى" مستوى واحد. هذا تمييز مهم لأنه، على سبيل المثال، في تاريخ بلادي كنت قد سميت مجلد المستوى الأعلى. من خلال تشجيع المجلدات "حتى" مستوى واحد، بوابة يفقد استمرار في ارتكاب حيث فعلت إعادة تسمية.

وجوابي على السؤال ثم هو جعل 2 نسخ من مستودع واحذف مجلد (ق) التي تريد الاحتفاظ بها في كل منهما. الصفحة رجل تؤيد لي مع هذا:

<اقتباس فقرة>   

[...] تجنب استخدام [هذا الأمر] إذا كان واحد بسيط ارتكاب يكفي لإصلاح مشكلتك

لإضافة إلى بولس الجواب ، وجدت أن لاسترداد في نهاية المطاف الفضاء، لا بد لي من دفع الرأس إلى مستودع نظيفة وأن الديكورات أسفل حجم. بوابة / الأجسام / الدليل حزمة.

وأي بمعنى.

$ mkdir ...ABC.git
$ cd ...ABC.git
$ git init --bare

وبعد تقليم القيادة العامة، وأيضا القيام به:

$ git push ...ABC.git HEAD

وبعد ذلك يمكنك القيام به

$ git clone ...ABC.git

ويتم تقليل حجم ABC /. بوابة

في الواقع، بعض الوقت الخطوات المستهلكة (مثل بوابة القيادة العامة) ليست هناك حاجة للدفع لتنظيف مستودع، أي بمعنى:.

$ git clone --no-hardlinks /XYZ /ABC
$ git filter-branch --subdirectory-filter ABC HEAD
$ git reset --hard
$ git push ...ABC.git HEAD

الطريق الصحيح الآن هو التالي:

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

جيثب حتى الآن المقالة الصغيرة عن مثل هذه الحالات.

ولكن يجب التأكد من استنساخ الأصلي الريبو إلى دليل منفصل الأولى (كما حذف جميع الملفات و الدلائل الأخرى وأنت من المحتمل بحاجة إلى العمل معهم).

لذلك ينبغي أن تكون الخوارزمية:

  1. استنساخ جهاز التحكم عن بعد الريبو إلى دليل آخر
  2. باستخدام git filter-branch بقي فقط الملفات تحت بعض فرعي, دفع جديد عن بعد
  3. إنشاء ارتكاب لإزالة هذا الدليل من جهاز التحكم عن بعد الأصلي الريبو

ويبدو أن معظم ( ؟ ) الإجابات هنا تعتمد على بعض شكل من git filter-branch --subdirectory-filter وأمثاله.قد يعمل هذا "معظم الأحيان" ومع ذلك في بعض الحالات على سبيل المثال حالة من عند إعادة تسمية المجلد السابق:

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

ABC/
    /move_this_dir_renamed

إذا كنت لا عادي بوابة مرشح أسلوب لاستخراج "move_me_renamed" سوف تفقد ملف تغيير التاريخ التي حدثت من الخلف عندما كان في البداية move_this_dir (المرجع).

وبذلك يبدو أن الطريقة الوحيدة التي تبقى كل تغيير التاريخ (إذا كان لك مثل هذه الحالة) ، هي ، في جوهرها ، نسخ مستودع (إنشاء جديد الريبو التي يكون الأصل) ، ثم nuke كل شيء آخر ثم إعادة تسمية الدليل على الأصل مثل هذا:

  1. استنساخ متعددة وحدة المشروع محليا
  2. فروع - تحقق من ما هو هناك: git branch -a
  3. هل الخروج على كل فرع أن تكون مدرجة في تقسيم للحصول على نسخة محلية على محطة العمل الخاصة بك: git checkout --track origin/branchABC
  4. جعل نسخة في دليل جديد: cp -r oldmultimod simple
  5. تذهب إلى المشروع الجديد نسخ: cd simple
  6. التخلص من الوحدات الأخرى التي لا حاجة في هذا المشروع:
  7. git rm otherModule1 other2 other3
  8. الآن فقط subdir الهدف وحدة لا يزال
  9. التخلص من وحدة subdir حتى أن وحدة الجذر يصبح المشروع الجديد الجذر
  10. git mv moduleSubdir1/* .
  11. حذف بقايا subdir: rmdir moduleSubdir1
  12. التحقق من التغييرات في أي وقت: git status
  13. إنشاء بوابة جديدة الريبو " و " نسخ عنوان URL إلى نقطة هذا المشروع إلى:
  14. git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
  15. تحقق من هذا الخير: git remote -v
  16. دفع التغييرات تصل إلى البعيد الريبو: git push
  17. انتقل إلى جهاز التحكم عن بعد الشراء والتحقق من كل شيء هناك
  18. كرر ذلك أي فرع المطلوبة: git checkout branch2

هذا يلي جيثب دوك "تقسيم فرعي في المستودع الجديد" خطوات 6-11 دفع وحدة نمطية جديدة الريبو.

هذا لن توفر لك أي مساحة في حياتك .بوابة المجلد ولكن فإنه سيتم الحفاظ على كل ما تبذلونه من تغيير التاريخ لهذه الملفات حتى عبر إعادة تسمية.و هذا قد لا يكون يستحق كل هذا العناء إذا لم يكن هناك "الكثير" من التاريخ المفقود ، إلخ.ولكن على الأقل يضمن لك عدم فقدان السن يرتكب!

وكان لي بالضبط هذه المشكلة ولكن كانت كل الحلول القياسية على أساس بوابة تصفية فرع بطيئة للغاية. إذا كان لديك مستودع صغير ثم هذا قد لا يكون مشكلة، وكان بالنسبة لي. كتبت برنامج آخر تصفية بوابة استنادا libgit2 التي كخطوة أولى يخلق فروع لكل تصفية المستودع الرئيسي ومن ثم يدفع هذه لتنظيف مستودعات كخطوة تالية. على بلدي مستودع (500MB 100000 يرتكب) اتخذت بوابة أساليب تصفية فرع القياسية أيام. برنامجي يأخذ دقيقة للقيام بنفس الترشيح.

وله اسم رائع من git_filter ويعيش هنا:

https://github.com/slobobaby/git_filter

وعلى جيثب.

وآمل أن يكون مفيدا لشخص ما.

ما يستحق, هنا هو كيفية استخدام جيثب على جهاز ويندوز.دعونا نقول لديك المستنسخة الريبو في المقيمين في C:\dir1.بنية الدليل يبدو مثل هذا: C:\dir1\dir2\dir3.على dir3 الدليل هو واحد كنت تريد أن تكون جديدة منفصلة الريبو.

جيثب:

  1. إنشاء المستودع الجديد: MyTeam/mynewrepo

باش موجه:

  1. $ cd c:/Dir1
  2. $ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
    عاد: Ref 'refs/heads/master' was rewritten (لمعلوماتك:dir2/dir3 حساسة لحالة الأحرف.)

  3. $ git remote add some_name git@github.com:MyTeam/mynewrepo.git
    git remote add origin etc.لم تنجح ، عاد "remote origin already exists"

  4. $ git push --progress some_name master

كما المذكورة أعلاه, لقد كان لاستخدام عكس الحل (حذف كل ما لا يرتكب لمس بلدي dir/subdir/targetdir) التي يبدو أنها تعمل بشكل جيد جدا إزالة حوالي 95% من يرتكب (حسب الرغبة).ومع ذلك ، هناك اثنين من القضايا الصغيرة المتبقية.

أولا, filter-branch هل ضجة حتى وظيفة إزالة يرتكب أي إدخال أو تعديل التعليمات البرمجية ولكن على ما يبدو ، دمج يرتكب هي تحت محطة في Gitiverse.

هذه هي قضية التجميل التي ربما أستطيع العيش مع (...يقول في التراجع ببطء مع عيون تفاديها).

الثاني عدد قليل من يرتكب التي لا تزال إلى حد كبير كل تتكرر!يبدو أنني اكتسبت الثانية زائدة الزمني الذي يمتد فقط عن كامل تاريخ المشروع.الشيء المثير للاهتمام (الذي ترون من الصورة أدناه) ، هو أن بلدي ثلاثة فروع محلية ليست كلها على نفس الجدول الزمني (الذي هو بالتأكيد السبب في أنه موجود ليس فقط من القمامة التي تم جمعها).

الشيء الوحيد الذي أستطيع أن أتخيل أن أحد حذف يرتكب ربما كان واحد دمج ارتكاب ذلك filter-branch في الواقع لم تحذف, و التي خلقت بالتوازي الزمني لكل الآن-unmerged حبلا أخذ نسخته من يرتكب.(تتغاضى أين التارديس؟) أنا متأكد من أنني يمكن إصلاح هذه المشكلة, على الرغم من أنني كنت حقا أحب أن أفهم كيف حدث ذلك.

في حالة من الجنون mergefest-O-راما ، سوف المرجح أن يكون ترك ذلك وحدها منذ بقوة نفسه في ارتكاب التاريخ—الوعيد في وجهي كلما جئت القريبة ، فإنه لا يبدو أن يكون في الواقع تسبب أي غير المشاكل التجميلية و لأنها جميلة جدا في البرج.التطبيق.

استخدم هذا الأمر مرشح لإزالة دليل فرعي، مع الحفاظ على العلامات والفروع الخاصة بك:

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

أسهل طريقة

  1. تثبيت git splits.أنا خلقت أنها بوابة التمديد ، على أساس jkeating الحل.
  2. تقسيم الأدلة إلى الفرع المحلي #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. خلق فارغة الريبو في مكان ما.سوف نفترض قمنا بإنشاء فارغة الريبو يسمى xyz على جيثب له الطريق : git@github.com:simpliwp/xyz.git

  4. دفعة جديدة الريبو. #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. استنساخ حديثا عن بعد الريبو إلى الدليل المحلي
    #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

أوصي جيثب دليل تقسيم المجلدات الفرعية في المستودع الجديد.الخطوات مشابهة إجابة بولس, لكني وجدت تعليمات أسهل للفهم.

يجب تعديل التعليمات بحيث تنطبق على المخزون المحلي بدلا من استضافتها على جيثب.


تقسيم فرعي في المستودع الجديد

  1. فتح بوابة باش.

  2. تغيير دليل العمل الحالي إلى الموقع حيث تريد إنشاء الخاصة بك المستودع الجديد.

  3. استنساخ مستودع يحتوي على مجلد فرعي.

git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
  1. تغيير دليل العمل الحالي الخاص بك استنساخ مستودع.

cd REPOSITORY-NAME
  1. لتصفية فرعي من بقية الملفات في مستودع تشغيل git filter-branch, وتوريد هذه المعلومات:
    • FOLDER-NAME:المجلد داخل المشروع الخاص بك التي ترغب في إنشاء مستودع منفصل من.
      • Tip:مستخدمي ويندوز يجب استخدام / لتحديد المجلدات.
    • BRANCH-NAME:الافتراضي فرع المشروع الحالي الخاص بك ، على سبيل المثال ، master أو gh-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

وأنت قد تحتاج إلى شيء مثل "بوابة reflog تنتهي --expire = الآن --all" قبل جمع القمامة إلى الواقع تنظيف الملفات بها. بوابة تصفية فرع فقط يزيل المراجع في التاريخ، ولكن لا يؤدي إلى إزالة إدخالات reflog التي تحمل البيانات. وبطبيعة الحال، اختبار هذا أولا.

وبلدي استخدام القرص انخفض بشكل كبير في القيام بذلك، على الرغم من الظروف الأولية بلدي كانت مختلفة إلى حد ما. ربما --subdirectory مرشح ينفي هذه الحاجة، ولكني أشك في ذلك.

وراجع مشروع git_split على https://github.com/vangorra/git_split

والدلائل بدوره بوابة إلى المستودعات الخاصة جدا في مكان الخاصة بهم. لا الشجرة الأعمال مضحك. هذا السيناريو سوف تتخذ دليل موجود في بوابة مستودع ويتحول هذا الدليل إلى مستودع مستقل من تلقاء نفسها. على طول الطريق، وسوف نسخ على مدى التاريخ تغيير كامل للدليل الذي قدمته.

./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.

ووضع ذلك في 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'

وأنا متأكد من بوابة الشجرة هو كل الجميلة والرائعة، ولكن لي الدلائل من بوابة إدارة التعليمات البرمجية التي أردت الانتقال كان كل شيء في الكسوف. حتى إذا كنت تستخدم ايجت، فإنه من السهل بشكل مؤلم. أخذ المشروع الذي تريد نقل وteam-> قطع، ثم team-> تشاركه إلى الموقع الجديد. وسوف الافتراضي إلى محاولة استخدام موقع الريبو القديم، ولكن يمكنك إلغاء اختيار القائمة استخدام واختيار مكان جديد لنقلها. جميع البرد ايجت.

ولقد وجدت الحل على التوالي إلى الأمام تماما، والفكرة هي لنسخ مستودع وبعد ذلك فقط إزالة جزء لا داعي لها. هذه هي الطريقة التي يعمل:

1) استنساخ مستودع كنت ترغب في تقسيم

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

2) نقل إلى مجلد بوابة

cd test/

2) إزالة المجلدات غير الضرورية وارتكابها

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

و3) إزالة لا لزوم له مجلد (ق) شكل التاريخ مع BFG

cd ..
java -jar bfg.jar --delete-folders "{ABC}" test
cd test/
git reflog expire --expire=now --all && git gc --prune=now --aggressive
<اقتباس فقرة>   

والمجلدات مضاعفة يمكنك استخدام فاصلة

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

و4) تحقق لا يحتوي هذا التاريخ ملفات / مجلدات قمت بحذفها فقط

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

و5) والآن لديك مستودع نظيفة دون ABC، حتى مجرد دفعها إلى أصل جديد

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

وهذا كل شيء. يمكنك تكرار الخطوات للحصول على مستودع آخر،

ومجرد إزالة XY1، XY2 وإعادة تسمية XYZ -> ABC في الخطوة 3

يمكنك محاولة بسهولة https://help.github.com/enterprise/2.15/user/articles/splitting-a-subfolder-out-into-a-new-repository/

هذا عملت بالنسبة لي.القضايا التي تواجهها في الخطوات الواردة أعلاه ،

  1. في هذا الأمر git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME على BRANCH-NAME هو ماجستير

  2. إن الخطوة الأخيرة فشل عند ارتكاب بسبب حماية مسألة المتابعة https://docs.gitlab.com/ee/user/project/protected_branches.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top