FreeToGenerate.com

اكتب الملف ثم شاهد ما يفعله git به فعلًا. مقيس لا منقول عن الدليل.

ملف ‎.gitattributes الخاص بك

افحص مسارًا في ضوئه

نسبةً إلى جذر المستودع، بشرطات مائلة أمامية. وهذا هو السؤال الذي لا يجيب عنه الملف بمجرد قراءته: أي سطر يفوز.

من يستنسخ مستودعك يملك أحد هذه الإعدادات الثلاثة، وأنت لا تتحكم فيه. وهذا موضوع اللوحة أدناه.

خصائص هذا المسار

الخاصيةالحالةمن
textauto*

ما سيفعله git فعلًا بنهايات الأسطر

المخزَّن في المستودع
LF
المكتوب في نسخة عمله
CRLF

غير مثبَّت. غيّر الإعداد أعلاه وراقب تحرك هذه اللوحة: فإعداد يخص كل شخص هو الذي يقرر مصير ملفاتك.

هذا مقيس لا منقول عن الدليل

الجدول أعلاه ناتج عن إيداع الملف نفسه بنهايات CRLF في واحد وعشرين مستودعًا مؤقتًا — كل تراكيب إعدادات core.autocrlf الثلاثة مع سبعة أسطر من الخصائص — ثم سؤال git عمّا انتهى فعلًا إلى مخزن الكائنات، وبعد حذف الملف واستعادته، عمّا انتهى إلى نسخة العمل.

والنتيجة الأبرز أنه بلا ملف ‎.gitattributes يتوقف ما يخزّنه مستودعك على من أودع. فالملف نفسه يدخل CRLF مع ‎core.autocrlf=false ويدخل LF مع true أو input، ولا شيء في نسختك أنت يخبرك أيّهما حدث. أضف أي خاصية text يختفِ ذلك التباين: فالإعدادات الثلاثة أنتجت بايتات متطابقة.

وما يخطئ فيه الناس هو ما لا يفعله ‎text=auto. فهو يثبّت المستودع ويترك نسخة العمل وشأنها: فعند سحب الملف من جديد يصل CRLF مع اثنين من الإعدادات الثلاثة وLF مع الثالث. ولا يثبّت الطرفين معًا إلا ‎eol=lf أو ‎eol=crlf. بل إن ‎eol=crlf يخزّن LF، لأنه تعليمة تخص السحب لا التخزين، فيبدو كأنه لا يفعل شيئًا حتى تنظر في الموضع الصحيح.

الأنماط أنماط gitignore، مع استثناء خطير

تعمل المطابقة كما تتوقع من ملف ‎.gitignore: فالنمط الذي فيه شرطة مائلة يُقاس من مجلد ملف ‎.gitattributes نفسه، والذي بلا شرطة يطابق اسمًا على أي عمق، و** تتجاوز المجلدات وتطابق أيضًا لا مجلد البتة. والأسبقية بالموضع — يفوز آخر سطر مطابق ولا يساوي التحديد شيئًا — بينما يفوز ملف ‎.gitattributes الأعمق في الشجرة على الأسطح منه، أيًا كان ترتيب قراءة git لهما.

والاستثناء هو علامة التعجب، وتستحق المعرفة لأنها تفشل صامتة. ففي ملف ‎.gitignore تنفي علامةُ التعجب في أول السطر النمطَ. أما في ‎.gitattributes فلا تفعل شيئًا البتة: فالسطر الذي يبدأ بها غير مدعوم أصلًا، ويمضي git بالقيمة السابقة. ولإزالة خاصية تضع شرطة قبل الخاصية لا قبل النمط، ولإعادتها إلى غير محدَّدة تضع علامة التعجب هناك.

السلوك مقيس في مقابل git نفسه، والمجسّات موجودة في المستودع. لا يُرفع شيء، فالمطابقة تجري داخل هذا التبويب.

متوفر أيضًا بلغات أخرى: English · Español · Português · Français

مولّد ملف ‎.gitattributes

ولّد ملف ‎.gitattributes وافحص أي مسار: أي سطر يفوز، وأي نهايات أسطر سيخزّنها git ويسلّمها لمن يستنسخ مستودعك.

ما ملف ‎.gitattributes؟

ملف ‎.gitattributes يخبر git كيف يعامل مسارات بعينها. يقيم في مستودعك، ويُودَع كأي شيء آخر، ويقرر أي الملفات يُعدّ نصًا وأيها ثنائي، وكيف تُقارَن وتُدمَج، والجزء الذي يأتي بأكثر الناس إلى هنا: ما يحدث لنهايات الأسطر ذهابًا وإيابًا.

والصيغة نمط يتبعه خصائص، قاعدة في كل سطر، وهي بالضبط هيئة ملف ‎.gitignore. وهذا الشبه هو أكثر أسباب الخطأ: فالأنماط هي أنماط gitignore فعلًا، لكن جزءًا من الصياغة يعني شيئًا مختلفًا تمامًا، والخاصية التي يقصدها الجميع تفعل أقل مما يوحي اسمها.

وتؤدي هذه الأداة النصفين. تحرّر الملف، ثم تعطيها مسارًا فتخبرك أي سطر يفوز، وفي أي حالة تستقر كل خاصية، وما الذي سيخزّنه git ويسحبه فعلًا — بما في ذلك إعدادُ جهاز شخص آخر الذي لا تتحكم فيه.

كيفية الاستخدام

  1. ابدأ من الملف المعروض. هو منطلق معقول: توحيد النص، وتثبيت سكربتات الصدفة على LF وملفات ‎.bat على CRLF، ووسم الملفات الثنائية المعتادة، ومنع git من مقارنة ملف قفل. حرّره مباشرة.
  2. اكتب مسارًا لفحصه. نسبةً إلى جذر المستودع. وتظهر كل خاصية مطابِقة ومعها النمط الذي قدّمها، فترى أي سطر فاز فعلًا لا أيها قصدت.
  3. غيّر إعداد 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 يواصل تخزينه حتى يعيد شيءٌ كتابة تلك الملفات. ولهذا وُجد خيار إعادة التوحيد، وهو ينتج بالضبط ذلك الفرق الهائل الذي تتوقعه، ولذلك يُستحسن فعله عن قصد لا اكتشافه لاحقًا.

لماذا هي مجانية؟

تعمل داخل متصفحك. ومطابقة مسار بنمط لا تكلّف شيئًا على جهازك أنت، فلا خادم يُدفع ثمنه ولا حساب يُنشأ.

لا يُرفع شيء مما تكتبه ولا يُخزَّن ولا يُسجَّل. فأسماء الملفات وبنية المجلدات تقول الكثير عن شفرة خاصة، والطريقة الموثوقة لإبقاء ذلك خاصًا ألا تُرسله إلى أي مكان.