متوفر أيضًا بلغات أخرى: English · Español · Português · Français
خطّافات git: القائمة الكاملة وأيها يستطيع إيقافك
المجموعة الكاملة التي يوثّقها git، والجواب المقيس عن السؤال الوحيد المهم: هل يستطيع هذا الخطّاف إيقاف ما تفعله؟
ما خطّاف git؟
خطّاف git ملف تنفيذي في مجلد الخطّافات داخل مستودعك، مسمّى باسم لحظة من حياة git. فإذا حلّت تلك اللحظة — وأنت على وشك الحفظ، أو أنهيت دمجًا، أو وصل دفعٌ إلى الخادم — شغّل git ذلك الملف. وهكذا يفرض مشروعٌ صيغةً لرسائل الحفظ، أو يمرّر مدقّق شيفرة قبل دخولها، أو يرفض دفعًا قسريًّا إلى الفرع الرئيسي.
يوثّق git ثمانية وعشرين خطّافًا. ولا يصادف أكثر الناس منها إلا ثلاثة أو أربعة، أما البقية فتغطي تطبيق الرقع عبر البريد، وإعادة الأساس، والطرف المستقبِل للدفع، وكنس المهملات، وجسرًا إلى Perforce، وعدد منها يعمل في مواضع لا يدلّ عليها اسمه أبدًا.
والسؤال الذي يأتي به كل أحد بسيط: إن فشل هذا الخطّاف، هل يوقفني؟ وكل مرجع وجدناه يجيب بنقل القائمة من دليل git. أما هذه الصفحة فتجيب بتشغيلها.
طريقة الاستخدام
- اكتب اسم خطّاف. تحصل على موضع تشغيله، وعلى ما يقوله توثيق git عن حالة خروجه، وعلى ما حدث حين رُكِّب فعلًا وأُمر بالفشل.
- أو ابحث في المجموعة كلها. يضم الجدول أدناه الثمانية والعشرين. والبحث بأمر من أوامر git — commit أو push أو git am — يعيد كل خطّاف ينطلق أثناءه.
- واقرأ العمودين أحدهما في مقابل الآخر. فهما من مصدرين مختلفين؛ حيث يتفقان يمكنك الوثوق بالجواب، وحيث لا تملك المواصفة كلمةً لما يجري، يقدّم القياس واحدة.
ماذا حدث حين شغّلناها
رُكِّب كل خطّاف على حدة، في مستودع مؤقّت إلى جانبه مستودع مجرّد محلي، ومتنه لا يفعل شيئًا سوى الفشل. ثم نُفِّذت العملية التي ينتمي إليها ذلك الخطّاف، وسُجِّل أمران: رمز الخروج الذي أعاده الأمر، وهل تحرّكت حالة المستودع فعلًا. وتسعة عشر من الثمانية والعشرين يمكن قيادتها هكذا، أما البقية فتحتاج مستودع Perforce أو ناقل بريد أو watchman أو بروتوكول الدفع الأحدث، فتُركت خالية بدل تخمينها.
وشُغِّلت كل حالة أيضًا بلا خطّاف إطلاقًا، وكان على هذا الضابط أن ينجح وأن يحرّك الحالة قبل أن يُعتدّ بالقياس. وليس هذا طقسًا شكليًّا: فقد أفادت النسخة الأولى من هذه التجربة بأن الخطّاف pre-rebase لا يستطيع إيقاف إعادة الأساس، وهو باطل، وسببه أن الفرع الذي بنته لم يكن فيه ما يُعاد تأسيسه، فلم تفعل العملية شيئًا بخطّاف أو بغيره. الضابط حوّل كذبةً معقولةً قابلةً للنشر إلى فشل صاخب.
ومن هذه التسعة عشر: أحد عشر أوقفت العملية، وسبعة لم تغيّر شيئًا البتة، وواحد فعل شيئًا لا كلمة شائعة له.
الخطّاف الذي يفشل دون أن يُفشل
لا يستطيع الخطّاف post-checkout إيقاف تبديل الفرع. ويقول توثيق git نفسه إنه لا يؤثر في النتيجة، إلا أن حالة خروجه تصير حالة خروج الأمر. وبالقياس، هذا بالضبط ما يقع: يتم التبديل، وتصير على الفرع الجديد، ويعيد git الرمز 1.
فالسكربت المكتوب على هيئة تبديل فرع يتبعه أمر مسلسل — وهكذا تُكتب معظم سكربتات النشر وخطوات التكامل المستمر — يتوقف تمامًا في مستودع يفشل فيه خطّاف post-checkout. التبديل نجح، والأمر فشل. حقيقتان مختلفتان، ولا يرى الصدَفُ إلا إحداهما.
ورمز خروج آخر يستحق المعرفة: حين يرفض الخطّاف reference-transaction في حالته prepared، لا يعيد git فشلًا عاديًّا بل يعيد 128، وهو رمزه للخطأ القاتل. فأي شيء يطابق رموز الخروج ينبغي أن يتوقع ذلك لا الرمز 1.
الاسم ليس هو القاعدة
يتعلّمها الجميع هكذا: الخطّافات التي تبدأ بـpre تستطيع المنع، والتي تبدأ بـpost لا تستطيع. ونصف هذا صحيح: فلم يوقف شيءٌ اسمه post شيئًا، وكل خطّاف لم يغيّر شيئًا البتة كان اسمه post-كذا.
أما النصف الآخر فيسقط. فستة فقط من الخطّافات الأحد عشر التي أوقفت عمليةً تُسمّى pre-كذا، والخمسة الأخرى هي applypatch-msg وcommit-msg وprepare-commit-msg وupdate وreference-transaction — أي أن قرابة نصف ما يستطيع إيقافك لا ينبّه إلى ذلك في اسمه. وprepare-commit-msg هو الفخ داخل الفخ: يبدأ بالحروف p-r-e، وليس خطّاف pre، ويمنع.
والقاعدة الحقيقية هي هل يستشير git حالة الخروج عند النقطة التي يعمل فيها الخطّاف، وهذه خاصية للعملية لا للاسم. ولهذا يوقف update عملية دفع، ويستطيع reference-transaction منع إنشاء فرع، ويستطيع post-checkout إفشال أمر دون أن يغيّر شيئًا.
ما لا تستطيع هذه الصفحة إخبارك به
هي إصدار واحد من git على منصة واحدة. أُخذ القياس بإصدار git المطبوع إلى جانب الأرقام، على ويندوز، ودلالات الخطّافات وإن كانت تتغيّر ببطء فهي تتغيّر. وحيث يتفق التوثيق والقياس — وهو كل ما يتقاطعان فيه — فالجواب أوثق ما يمكن دون قراءة الشيفرة المصدرية.
وتسعة خطّافات لم تُقَس، وتقول خاناتها ذلك بدل أن تُملأ. وقد جُرّب أحدها، pre-auto-gc، ثم تُرك: فكنس المهملات التلقائي لا يعمل إلا بعد أن يقرّر git أن في المستودع ما يكفي من الكائنات السائبة، وذلك القرار يأخذ عيّنة من مجلد بدل أن يعدّ، فلم يشغّله أي مستودع اختبار صغير بما يكفي. والخانة التي لا يمكن جعل ضابطها أمينًا تُترك خارجًا.
وأخيرًا، الحديث هنا عن قدرة الخطّاف على إيقاف عملية لا عن جدارته بذلك. فالخطّاف الذي يرفض عملًا لا ينفع إلا إذا عرف من أوقفه لماذا أُوقف، وgit لا يطبع شيئًا نيابةً عنك: ما يكتبه خطّافك في مخرج الخطأ هو الرسالة كلها التي سيراها أي أحد.
لماذا هي مجانية؟
القائمة كلها بضعة كيلوبايتات تُشحن مع الصفحة ويجري البحث فيها داخل متصفحك. لا يُرفع شيء مما تكتبه، ولا يُسجَّل شيء، ولا حساب عليك إنشاؤه.
بلا تسجيل، وبلا حدود، وبلا علامة مائية على أي شيء تنسخه.