GIT Filter-Repo هي أداة متعددة الاستخدامات لإعادة كتابة التاريخ ، والتي تتضمن القدرات التي لم أجدها في أي مكان آخر. إنه يقع تقريبًا في نفس مساحة الأداة مثل فرع مرشح GIT ولكن بدون الأداء الضعيف الذي يسبب الاستسلام ، مع قدرات أكبر بكثير ، ومع تصميم يتجاوز قابلية الاستخدام إلى ما هو أبعد من حالات إعادة كتابة التافهة. يوصى الآن مشروع GIT Filter-Repo من قبل مشروع GIT بدلاً من فرع مرشح GIT.
على الرغم من أن معظم المستخدمين سيستخدمون فقط Filter-REPO كأداة سطر أوامر بسيطة (ومن المحتمل أن يستخدموا عددًا قليلاً من أعلامها) ، في مرشحها الأساسي يحتوي على مكتبة لإنشاء أدوات إعادة كتابة التاريخ. على هذا النحو ، يمكن للمستخدمين ذوي الاحتياجات المتخصصة الاستفادة منه لإنشاء أدوات إعادة كتابة التاريخ الجديدة بسرعة.
يتطلب المرشح ريبو:
git-filter-repo
هو نص Python واحد ملف ، والذي تم القيام به لجعل التثبيت للاستخدام الأساسي على العديد من الأنظمة Trivial: فقط ضع هذا الملف في مسار $ الخاص بك.
انظر install.md للحصول على أشياء تتجاوز الاستخدام الأساسي أو الحالات الخاصة. كلما كانت الإرشادات الأكثر إشراكًا مطلوبة فقط إذا تم تطبيق أحد ما يلي:
للتوثيق الشامل:
إذا كنت تفضل التعلم من الأمثلة:
تمت تغطية هذا بمزيد من التفاصيل في مقال Git Rev News حول Filter-Repo ، ولكن بعض النقاط البارزة للمنافسين الرئيسيين:
إن الفلتر الفرع هو بطيء للغاية (أوامر متعددة من الحجم أبطأ مما ينبغي) للمستودعات غير التافهة.
إن فرع التصفية مليء بـ Gotchas التي يمكن أن تفسد إعادة الكتابة بصمت أو على الأقل إحباط جهود "التنظيف" الخاصة بك من خلال إعطائك شيئًا أكثر إشكالية وفوضى مما بدأت به.
فرع المرشح أمر شاق للغاية لاستخدامه في أي إعادة كتابة غير تافهة قليلاً.
صرح مشروع GIT بأن المشكلات المذكورة أعلاه مع فرع المرشح لا يمكن أن تكون ثابتة بشكل متوافق ؛ يوصيون بالتوقف عن استخدام فرع التصفية
قد يهتم عشاق Filter-Branch بالمرشح (المعروف أيضًا باسم Filter-Branch-ish) ، وهو إعادة تفسير من فرع المرشح على أساس الفلتر-ريبو أكثر أداء (على الرغم من أنه ليس سريعًا أو آمنًا تقريبًا مثل المرشح- ريبو).
تتوفر ورقة الغش توضح كيفية تحويل أوامر المثال من دليل فرع المرشح إلى أوامر مرشح REPO.
أداة رائعة لوقته ، ولكن على الرغم من أنها تجعل بعض الأشياء بسيطة ، إلا أنها تقتصر على أنواع قليلة من إعادة الكتابة.
بنيةها ليست قابلة للتعامل مع المزيد من أنواع إعادة الكتابة.
تعرض بنيةها بعض أوجه القصور والأخطاء حتى بالنسبة للاستعارة المقصودة.
قد يكون عشاق BFG مهتمين بـ BFG-ish ، وهو إعادة تنفيذ BFG استنادًا إلى Filter-Repo والتي تتضمن العديد من الميزات الجديدة وإثارات الأخطاء بالنسبة إلى BFG.
تتوفر ورقة الغش التي توضح كيفية تحويل أوامر المثال من دليل منظف BFG REPO إلى أوامر Filter-REPO.
دعنا نقول أننا نريد استخراج قطعة من مستودع ، مع النية على دمج هذه القطعة فقط في بعض الريبو الأكبر الأخرى. للاستخراج ، نريد:
القيام بذلك مع Filter-Repo بسيط مثل الأمر التالي:
git filter-repo --path src/ --to-subdirectory-filter my-module --tag-rename ' ' : ' my-module- '
(عروض الأسعار الفردية غير ضرورية ، ولكنها تجعله أكثر وضوحًا بالنسبة للإنسان أننا نستبدل السلسلة الفارغة كبادئة مع my-module-
)
BFG Repo Cleaner غير قادر على هذا النوع من إعادة الكتابة ؛ في الواقع ، جميع أنواع التغييرات الثلاثة المطلوبة خارج قدراتها.
يأتي فرع التصفية مع كومة من المحاذير (المزيد عن ذلك أدناه) حتى بمجرد معرفة الاحتجاج (S) اللازم:
git filter-branch
--tree-filter ' mkdir -p my-module &&
git ls-files
| grep -v ^src/
| xargs git rm -f -q &&
ls -d *
| grep -v my-module
| xargs -I files mv files my-module/ '
--tag-name-filter ' echo "my-module-$(cat)" '
--prune-empty -- --all
git clone file:// $( pwd ) newcopy
cd newcopy
git for-each-ref --format= " delete %(refname) " refs/tags/
| grep -v refs/tags/my-module-
| git update-ref --stdin
git gc --prune=now
قد يلاحظ البعض أن دعوة فرع التصفية أعلاه سيكون بطيئًا حقًا بسبب استخدام المرشح-Tree-Filter ؛ يمكنك بدلاً من ذلك استخدام خيار-مرشح الفهرس لـ Filter-Branch ، وتغيير الأوامر المذكورة أعلاه إلى:
git filter-branch
--index-filter ' git ls-files
| grep -v ^src/
| xargs git rm -q --cached;
git ls-files -s
| sed "s%$(printf \t)%&my-module/%"
| git update-index --index-info;
git ls-files
| grep -v ^my-module/
| xargs git rm -q --cached '
--tag-name-filter ' echo "my-module-$(cat)" '
--prune-empty -- --all
git clone file:// $( pwd ) newcopy
cd newcopy
git for-each-ref --format= " delete %(refname) " refs/tags/
| grep -v refs/tags/my-module-
| git update-ref --stdin
git gc --prune=now
ومع ذلك ، بالنسبة إلى قيادة الفلتر ، هناك كومة من التحذيرات. أولاً ، قد يتساءل البعض عن سبب إدراج خمسة أوامر هنا للمرشح. على الرغم من استخدام مرشح-كل اسم ، ومرشح ، ومرشح الفرع ، مدعيا أن الاستنساخ يكفي للتخلص من الأشياء القديمة ، والخطوات الإضافية لحذف العلامات الأخرى والقيام GC آخر لا يزال مطلوبًا لذلك قم بتنظيف الأشياء القديمة وتجنب خلط التاريخ الجديد والقديم قبل الدفع إلى مكان ما. تحذيرات أخرى:
يمكن للمرء أن يخترق هذا إلى جانب شيء مثل:
git fast-export --no-data --reencode=yes --mark-tags --fake-missing-tagger
--signed-tags=strip --tag-of-filtered-object=rewrite --all
| grep -vP ' ^M [0-9]+ [0-9a-f]+ (?!src/) '
| grep -vP ' ^D (?!src/) '
| perl -pe ' s%^(M [0-9]+ [0-9a-f]+ )(.*)$%1my-module/2% '
| perl -pe ' s%^(D )(.*)$%1my-module/2% '
| perl -pe s%refs/tags/%refs/tags/my-module-%
| git -c core.ignorecase=false fast-import --date-format=raw-permissive
--force --quiet
git for-each-ref --format= " delete %(refname) " refs/tags/
| grep -v refs/tags/my-module-
| git update-ref --stdin
git reset --hard
git reflog expire --expire=now --all
git gc --prune=now
لكن هذا يأتي مع بعض التحذيرات والقيود السيئة:
لم تفعل أي من أدوات تصفية المستودع الحالية ما أردت ؛ لقد جاءوا جميعًا لتلبية احتياجاتي. لم تقدم أي أداة أي من السمات الثمانية الأولى أدناه التي أردت ، ولم تقدم أي أداة أكثر من اثنين من الصفات الأربع الأخيرة أيضًا:
[تقرير البدء] تزويد المستخدم بتحليل لإثباته لمساعدتهم على البدء في ما يجب تقليمه أو إعادة تسميته ، بدلاً من توقع تخمين أو العثور على أدوات أخرى لمعرفة ذلك. (تم تشغيله ، على سبيل المثال من خلال تشغيل أول مرة بعلم خاص ، مثل -تحليل.)
[Keep مقابل إزالة] بدلاً من مجرد توفير طريقة للمستخدمين لإزالة المسارات المحددة بسهولة ، وتوفير أعلام للمستخدمين فقط للحفاظ على مسارات معينة فقط. من المؤكد أن المستخدمين يمكن أن يحلوا عن ذلك من خلال تحديد جميع المسارات بخلاف المسارات التي يريدون الاحتفاظ بها ، ولكن الحاجة إلى تحديد جميع المسارات الموجودة في أي إصدار من المستودع قد تكون في بعض الأحيان مؤلمة للغاية. للفلتر الفرع ، باستخدام خطوط الأنابيب مثل git ls-files | grep -v ... | xargs -r git rm
قد يكون git ls-files | grep -v ... | xargs -r git rm
بمثابة حلول معقول ولكن يمكن أن يكون غير عملي وليس واضحًا للمستخدمين ؛ بالإضافة إلى أن هذه الأوامر غالباً ما تكون نظام التشغيل الخاص (هل يمكنك اكتشاف gnuism في المقتطف الذي قدمته؟).
[إعادة تسمية] يجب أن يكون من السهل إعادة تسمية المسارات. على سبيل المثال ، بالإضافة إلى السماح لأحدهم بمعالجة بعض الدليل الفرعي كجذر للمستودع ، فإنه يوفر أيضًا خيارات للمستخدمين لجعل جذر المستودع مجرد دليل فرعي. وبشكل أعم تسمح للملفات والأدلة بإعادة تسمية بسهولة. توفير فحص العقل إذا كان إعادة تسمية تسبب في وجود ملفات متعددة في نفس المسار. (وأضف معالجة خاصة بحيث إذا تم نسخ التزام فقط OldName-> newName دون تعديل ، فإن تصفية oldname-> NewName لا يؤدي إلى فحص العقل والموت على هذا الالتزام).
[سلامة أكثر ذكاءً] كتابة نسخ من الحكام الأصلية إلى مساحة اسم خاصة داخل الريبو لا توفر آلية استرداد سهلة الاستخدام. كثيرون سوف يكافحون من أجل التعافي باستخدام ذلك. إن كل شخص رأيته تقريبًا يقوم بإجراء عملية تصفية مستودع قد قام بذلك باستخدام استنساخ جديد ، لأن مسح الاستنساخ في حالة وجود خطأ هو آلية استرداد أسهل إلى حد كبير. شجع بشدة سير العمل من خلال اكتشاف وكفالة إذا لم نكن في استنساخ جديد ، ما لم يتغلب المستخدم على القوة.
[Auto Drenk] تلقائيًا قم بإزالة Cruft Old وأعيد تعبئة المستودع للمستخدم بعد التصفية (ما لم يتم تجاوزه) ؛ هذا يبسط الأشياء للمستخدم ، ويساعد على تجنب خلط التاريخ القديم والجديد معًا ، ويتجنب المشكلات التي لا تعمل فيها العملية متعددة الخطوات لتقليص الريبو الموثقة في Manpage بالفعل في بعض الحالات. (أنا أنظر إليك ، تصفية الفرع.)
[فصل نظيف] تجنب إرباك المستخدمين (ومنع إعادة صياغة الأشياء القديمة) بسبب خلط الريبو القديم وإعادة كتابة الريبو معًا. (هذه مشكلة خاصة في فرع المرشح عند استخدام خيار مرشح اسم الأسماء ، وأحيانًا أيضًا مشكلة عند تصفية مجموعة فرعية من الفروع فقط.)
[prositiality] تزويد المستخدم بالقدرة على توسيع الأداة أو حتى كتابة أدوات جديدة تستفيد من القدرات الحالية ، وتوفير هذه القابلية للتوسع بطريقة (أ) تجنب الحاجة إلى شوكة عمليات منفصلة (والتي من شأنها تدمير الأداء) ، (ب) يتجنب جعل المستخدم يحدد أوامر shell المعتمدة على نظام التشغيل (والتي من شأنها أن تمنع المستخدمين من مشاركة الأوامر مع بعضهم البعض) ، (ج) يستفيد من هياكل البيانات الغنية (لأن التجزئة ، والقوائم ، والصفائف صعبة بشكل محظور في الصدفة) و ( د) يوفر إمكانات معالجة معالجة سلسلة معقولة (والتي تفتقر بشدة إلى shell).
[مراجع الالتزام القديمة] توفر طريقة للمستخدمين لاستخدام معرفات الالتزام القديمة مع المستودع الجديد (على وجه الخصوص عن طريق التعيين من التجزئة القديمة إلى المراجع/ الاستبدال/ المراجع).
[ارتكاب اتساق الرسائل] إذا كانت رسائل الالتزام ، فاربعة إلى الالتزامات الأخرى حسب المعرف (على سبيل المثال "هذا يعود إلى الالتزام 01234567890ABCDEF" ، "في الالتزام 0013DeadBeef9a ...") يجب إعادة كتابة هذه الرسائل الالتزام للإشارة إلى معرفات الالتزام الجديدة.
[أن تصبح مخففة التقليم] تلتزم والتي تصبح فارغة بسبب الترشيح يجب تقليمها. إذا تم تقليم والد الالتزام ، فيجب أن يصبح الجد الأول غير المشترك الوالد الجديد. إذا لم يكن هناك سلف غير محدد ولم يكن الالتزام دمجًا ، فسيصبح التزامًا جديدًا للجذر. إذا لم يكن هناك أي سلف غير مشترك وكان الالتزام بمثابة دمج ، فسيكون للاندماج أحد الوالدين أقل (وبالتالي يجعل من المحتمل أن يصبح التزامًا غير حارق يتم تقليمه إذا لم يكن لديه أي تغييرات في ملفه) . شيء خاص واحد يجب ملاحظته هنا هو أننا نخوض الالتزامات التي تصبح فارغة ، وليس الالتزام والتي تبدأ فارغة. تقوم بعض المشاريع بإنشاء ارتباطات فارغة عن عمد لأسباب الإصدار أو النشر ، ويجب عدم إزالةها. (كحالة خاصة ، فإن الالتزامات التي بدأت فارغة ولكن سيتم اعتبار الوالد الذي تم تقليمه بعيدًا "أصبح فارغًا".).
[أن تصبح تقليمًا غير معتدل] تشذيب الالتزامات التي تصبح فارغة يمكن أن تتسبب في تغييرات طوبولوجيا ، وهناك الكثير من الحالات الخاصة. عادة ، لا تتم إزالة الالتزامات الدموية نظرًا لأنها ضرورية للحفاظ على طوبولوجيا الرسم البياني ، ولكن يمكن أن يؤدي تقليم الآباء والأجداد الآخرين في النهاية إلى فقدان واحد أو أكثر من الوالدين. وقد لوحظ بالفعل حالة بسيطة أعلاه: إذا فقدت الالتزام بما يكفي من الوالدين ليصبحوا التزامًا غير حارق وليس له تغييرات في الملف ، فيمكن تقليمه أيضًا. يمكن أن يكون لدى Commits Commits أيضًا طوبولوجيا تصبح متدهورة: يمكن أن ينتهي الأمر بخدمة Merge_Base كأبوين (إذا تم تقليم كل الوالدين (إذا تم تقليم كل ما يتدخل من الريبو الأصلي) ، أو قد ينتهي به الأمر مع أحد الوالدين وهو سلف لآخره الوالد. في مثل هذه الحالات ، إذا لم يكن لدى الدمج أي تغييرات في الملف ، فيمكن أيضًا تشذيب الالتزام بالدمج. ومع ذلك ، بقدر ما نفعل مع التقليم الفارغ ، فإننا لا نقوم بدمج الالتزامات التي بدأت تتدهور (مما يشير إلى أنه قد يكون مقصودًا ، كما هو الحال مع-لا تندمج) ولكن دمج الاندماج فقط التي تصبح متدهورة ولا توجد تغييرات في ملفات خاصة بهم.
[السرعة] يجب أن يكون التصفية سريعًا بشكل معقول
انظر الإرشادات المساهمة.
من المتوقع أن يلتزم المشاركون في مجتمع Filter-Repo بنفس المعايير بالنسبة لمشروع GIT ، وبالتالي ينطبق مدونة قواعد السلوك GIT.
لقد دفع العمل على Filter-Repo وسلفه أيضًا العديد من التحسينات على التصدير السريع والاستيراد السريع (وأحيانًا أوامر أخرى) في GIT الأساسية ، بناءً على الأشياء التي يحتاج المرشح إلى القيام بعملها: