متوفر أيضًا بلغات أخرى: English · Español · Português · Français
مولّد ملف .gitattributes
ولّد ملف .gitattributes وافحص أي مسار: أي سطر يفوز، وأي نهايات أسطر سيخزّنها git ويسلّمها لمن يستنسخ مستودعك.
ما ملف .gitattributes؟
ملف .gitattributes يخبر git كيف يعامل مسارات بعينها. يقيم في مستودعك، ويُودَع كأي شيء آخر، ويقرر أي الملفات يُعدّ نصًا وأيها ثنائي، وكيف تُقارَن وتُدمَج، والجزء الذي يأتي بأكثر الناس إلى هنا: ما يحدث لنهايات الأسطر ذهابًا وإيابًا.
والصيغة نمط يتبعه خصائص، قاعدة في كل سطر، وهي بالضبط هيئة ملف .gitignore. وهذا الشبه هو أكثر أسباب الخطأ: فالأنماط هي أنماط gitignore فعلًا، لكن جزءًا من الصياغة يعني شيئًا مختلفًا تمامًا، والخاصية التي يقصدها الجميع تفعل أقل مما يوحي اسمها.
وتؤدي هذه الأداة النصفين. تحرّر الملف، ثم تعطيها مسارًا فتخبرك أي سطر يفوز، وفي أي حالة تستقر كل خاصية، وما الذي سيخزّنه git ويسحبه فعلًا — بما في ذلك إعدادُ جهاز شخص آخر الذي لا تتحكم فيه.
كيفية الاستخدام
- ابدأ من الملف المعروض. هو منطلق معقول: توحيد النص، وتثبيت سكربتات الصدفة على LF وملفات .bat على CRLF، ووسم الملفات الثنائية المعتادة، ومنع git من مقارنة ملف قفل. حرّره مباشرة.
- اكتب مسارًا لفحصه. نسبةً إلى جذر المستودع. وتظهر كل خاصية مطابِقة ومعها النمط الذي قدّمها، فترى أي سطر فاز فعلًا لا أيها قصدت.
- غيّر إعداد core.autocrlf عنده. تمثّل هذه الأزرار الثلاثة الإعدادَ على جهاز من يستنسخ مستودعك. راقب لوحة نهايات الأسطر وأنت تضغطها: فإن تحركت، فملفاتك متوقفة على إعداد لا تراه.
ما تفعله نهايات الأسطر فعلًا، مقيسًا
هذا الجزء مقيس لا مقروء. فقد أُودع الملف نفسه بنهايات CRLF في واحد وعشرين مستودعًا مؤقتًا — كل تراكيب إعدادات core.autocrlf الثلاثة مع سبعة أسطر مختلفة من الخصائص — ثم سُئل git عمّا في مخزن الكائنات، وبعد حذف الملف واستعادته، عمّا في نسخة العمل.
بلا ملف .gitattributes يتوقف ما يخزّنه مستودعك على من أودع. فالملف نفسه يدخل CRLF مع core.autocrlf=false ويدخل LF مع true أو input. ولا شيء في نسختك أنت يخبرك أيّهما حدث، ولهذا يظهر الأمر طلبَ دمج مليئًا بملفات كاملة متغيرة بدل أن يظهر خطأً. أضف أي خاصية text يختفِ ذلك التباين: فالإعدادات الثلاثة أنتجت بايتات متطابقة.
والمفاجأة هي ما لا يفعله text=auto. فهو يثبّت المستودع ويترك نسخة العمل وشأنها: فعند سحب الملف من جديد يصل CRLF مع اثنين من الإعدادات الثلاثة وLF مع الثالث. ومن ثم فالفريق الذي يضيف سطرًا واحدًا من text=auto جعل تاريخه متسقًا ولم يجعل نسخ عمله متفقة. ولا يثبّت الطرفين إلا eol=lf أو eol=crlf.
وeol=crlf يخزّن LF. فهو تعليمة تخص السحب لا التخزين، فإن فحصت الكائن وجدت LF وخلصت إلى أن السطر لم يفعل شيئًا. بل فعل، لكنه فعله في الطرف الآخر.
الأنماط أنماط gitignore، مع استثناء يفشل صامتًا
تسلك المطابقة كما توحي تلك الهيئة المألوفة. فالنمط الذي فيه شرطة مائلة يُقاس من مجلد ملف .gitattributes نفسه، والذي بلا شرطة يطابق اسمًا على أي عمق تحته. والنجمة المزدوجة تتجاوز المجلدات، و— وهذا مقيس لأن افتراض العكس سهل — تطابق أيضًا لا مجلد البتة، فـ sub/**/*.txt يشمل sub/a.txt كما يشمل sub/deep/a.txt. وفئات المحارف تعمل.
والأسبقية بالموضع لا بالتحديد: يفوز آخر سطر مطابق، ولا يساوي كون النمط أدقّ شيئًا. وهي القاعدة نفسها في EditorConfig، ونفس ما يفهمه الناس معكوسًا في كليهما. وبين الملفات يفوز ملف .gitattributes الأعمق في الشجرة على الأسطح منه، أيًا كان ترتيب قراءة git لهما.
والاستثناء هو علامة التعجب. ففي ملف .gitignore تنفي علامةُ التعجب في أول السطر النمطَ. أما في .gitattributes فغير مدعومة إطلاقًا: فالسطر الذي يبدأ بها لا يفعل شيئًا، وتبقى القيمة السابقة سارية. ولا خطأ ولا تحذير. ولإزالة خاصية تضع شرطة قبل الخاصية لا قبل النمط، ولإعادتها إلى غير محدَّدة تضع علامة التعجب هناك.
وأمر أخير يجدر معرفته لأنه أكثر الأسطر شيوعًا في أي ملف حقيقي: binary ليست خاصية بل ماكرو. تتوسّع إلى إلغاء text وdiff وmerge معًا، ولهذا فوسم مسار بـ binary يتجاوز text=auto سابقًا تجاوزًا صحيحًا بدل أن يتعايش معه.
حدود معلنة
هذا يُنمذِج القواعد لا مستودعك. فقد تحوي المشاريع الحقيقية عدة ملفات .gitattributes على أعماق مختلفة، ويقرأ git كذلك .git/info/attributes وملفًا عامًا خارج المستودع بالكلية، وكلاهما غير مودَع ولا يملكه أحد غيرك. وما يُنمذَج هنا الملفُ المودَع والقواعد داخله، وهناك يسكن الجزء المربك في الغالب الأعم.
ولوحة نهايات الأسطر تتنبأ بما يفعله git بملف نصي نهاياته اليوم CRLF، لأن هذه هي الحالة التي يأتي بها الناس. أما الملف الذي صار LF بالكامل، أو الذي نهاياته مختلطة، فيسلك سلوكًا لا تحاول اللوحة رسمه.
وتغيير ملف .gitattributes لا يغيّر ملفات أُودعت من قبل. فـ git يطبّق القواعد الجديدة في المرة التالية التي يمر بها ملف، فالمستودع الذي ظل يخزّن CRLF يواصل تخزينه حتى يعيد شيءٌ كتابة تلك الملفات. ولهذا وُجد خيار إعادة التوحيد، وهو ينتج بالضبط ذلك الفرق الهائل الذي تتوقعه، ولذلك يُستحسن فعله عن قصد لا اكتشافه لاحقًا.
لماذا هي مجانية؟
تعمل داخل متصفحك. ومطابقة مسار بنمط لا تكلّف شيئًا على جهازك أنت، فلا خادم يُدفع ثمنه ولا حساب يُنشأ.
لا يُرفع شيء مما تكتبه ولا يُخزَّن ولا يُسجَّل. فأسماء الملفات وبنية المجلدات تقول الكثير عن شفرة خاصة، والطريقة الموثوقة لإبقاء ذلك خاصًا ألا تُرسله إلى أي مكان.