الوحدة 4 · عادات احترافية
الـ Stash وملف .gitignore
15 دقراءة 4 داكتشف الخطأ
الدرس في لمحة
اركن العمل غير المكتمل جانبًا بـ git stash وأعده لاحقًا، واكتب ملف .gitignore يُبقي الاعتماديات وناتج البناء والأسرار وفوضى نظام التشغيل خارج الـ repository.
- 1الـ Stash: درج للعمل غير المكتمل
- 2ملف .gitignore: ملفات يجب ألّا يتتبّعها Git أبدًا
- 3كيف تعمل الأنماط
- 4التجاهل لا يلغي التتبّع
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
أداتان صغيرتان تُبقيان الـ working tree تحت السيطرة. git stash يعطيك درجًا للعمل غير الجاهز للـ commit. و .gitignore يخبر Git بالملفات التي يجب ألّا يتتبّعها أبدًا. وكلتاهما تمنعان النوع نفسه من الحوادث: أن يتسلّل الشيء الخطأ إلى commit.
الـ Stash: درج للعمل غير المكتمل
أنت في منتصف نموذج التواصل في الموقع الشخصي على فرع contact-form، حين ينبّهك أحدهم إلى خطأ إملائي في الصفحة الرئيسية المنشورة. تحتاج إلى main، الآن. لكن git switch main يرفض، لأن تعديلاتك على index.html ستُكتب فوقها، ولا تريد تسجيل نموذج نصف مبني في commit.
خبّئه (stash):
git stash push -m "contact form: fields done, validation next"
git status # nothing to commit, working tree cleanتغييراتك، المجهّزة وغير المجهّزة، تُحفظ في مدخل stash وتُزال من الـ working tree. الآن أصلح الخطأ الإملائي:
git switch main
# fix, commit, push
git switch contact-form
git stash popالـ pop يعيد تطبيق أحدث stash ويحذفه. وتعود تمامًا إلى حيث كنت.
أوامر الـ stash الأخرى التي ستستخدمها:
git stash list # stash@{0}: On contact-form: contact form: fields done…
git stash show -p stash@{0} # the diff inside a stash
git stash apply stash@{1} # reapply but keep the stash
git stash drop stash@{1} # delete one stash
git stash push -u -m "…" # include untracked (new) files tooالخيار الأخير مهم. افتراضيًا لا يحفظ الـ stash إلا التغييرات على الملفات المتتبَّعة. أما contact.js الجديد كليًا فيبقى في مجلدك دون أن يُمسّ، وهذا يفاجئ الناس حين ينفّذون pop ولا «يُستعاد». استخدم -u كلما أنشأت ملفات.
الـ stash غير مربوط بفرع: تستطيع تنفيذ pop له على أي فرع، وهذا مفيد أحيانًا ومفاجئ أحيانًا. وإن أدركت أن العمل المخبّأ يستحق فرعًا خاصًا به في النهاية، فإن git stash branch contact-validation ينشئ فرعًا عند الـ commit الذي خبّأت عنده، ويطبّق الـ stash هناك ثم يحذفه، فيتجنّب التعارضات مع أي شيء تغيّر منذ ذلك الحين.
إن اصطدم الـ pop بتعارض، يطبّق Git ما يستطيعه، ويعلّم التعارض كالمعتاد، ويحتفظ بالـ stash بدل حذفه. حُلّ التعارض، ونفّذ git add، وشغّل git stash drop حين تتأكّد.
ملف .gitignore: ملفات يجب ألّا يتتبّعها Git أبدًا
بعض الملفات مكانها في مجلد مشروعك، لكن ليس في السجلّ أبدًا:
- الاعتماديات (dependencies) التي تستطيع إعادة تثبيتها، مثل
node_modules/؛ - ناتج البناء الذي تستطيع إعادة توليده، مثل
dist/؛ - الأسرار والإعدادات الخاصة بالجهاز، مثل
.env؛ - فوضى نظام التشغيل والمحرّر، مثل
.DS_Storeعلى macOS.
اسردها في ملف اسمه .gitignore في جذر الـ repository وسجّله في commit، ليتشارك كل من في المشروع القواعد نفسها:
# Dependencies
node_modules/
# Build output
/dist/
# Local environment and secrets
.env
.env.*
!.env.example
# OS and editor files
.DS_Store
*.logالملفات المتجاهَلة تختفي من git status، ويتخطّاها git add ..
كيف تعمل الأنماط
كل سطر نمط (pattern)، يُطابق مع المسارات نسبةً إلى مجلد ملف .gitignore:
#تبدأ تعليقًا، لكن فقط في بداية السطر. والأسطر الفارغة تُتجاهل.*.logيطابق أي ملف ينتهي بـ.log، في أي مجلد.- الشرطة المائلة
/في النهاية تطابق المجلدات فقط:node_modules/. - الشرطة المائلة
/في البداية تثبّت النمط على هذا المجلد:/dist/يتجاهلdistفي الجذر لكن لا يتجاهلsrc/dist. **/يطابق أي عمق:**/fixtures/*.json.!تعيد تضمين شيء استبعده سطر سابق:!.env.exampleيُبقي القالب للمطوّرين الآخرين. لكنها لا تستطيع إعادة تضمين ملف استُبعد المجلد الأب الخاص به، لأن Git لا ينظر أبدًا داخل مجلد متجاهَل.
حين يكون ملف ما متجاهَلًا ولا تعرف السبب، اسأل Git:
git check-ignore -v dist/app.js.gitignore:5:/dist/ dist/app.jsيطبع الملف ورقم السطر والنمط المسؤول.
وللفوضى التي لا يُنشئها إلا جهازك، لا تُثقل ملف .gitignore في كل مشروع. فـ Git يقرأ أيضًا ملف تجاهل عامًا، ~/.config/git/ignore، وهو مكان مناسب لـ .DS_Store ومجلدات المحرّر. ويحتفظ GitHub بمجموعة من قوالب .gitignore الجاهزة لمعظم اللغات، ويعرض عليك واحدًا حين تنشئ repository.
التجاهل لا يلغي التتبّع
.gitignore لا يؤثّر إلا في الملفات غير المتتبَّعة. إن كان .env قد سُجّل في commit قبل أن تتجاهله، فسيواصل Git تتبّعه. أزله من الـ index وأنشئ commit، وهذا يُبقي ملفك المحلي:
git rm --cached .env
git commit -m "Stop tracking .env"صار الـ working tree نظيفًا، ولا يحتوي الـ repository إلا ما يجب أن يحتويه. في الدرس التالي ستجعل ما يحتويه مقروءًا: رسائل الـ commits، والـ tags، والإصدارات.
أهم النقاط
git stash push -m "…"يحفظ تغييراتك غير المسجّلة ويُنظّف الـ working tree؛ وgit stash popيعيدها ويحذف الـ stash.git stashيتخطّى الملفات غير المتتبَّعة ما لم تضف-u(--include-untracked)..gitignoreلا يؤثّر إلا في الملفات غير المتتبَّعة؛ ولإيقاف تتبّع ملف مسجّل، شغّلgit rm --cachedوأنشئ commit.- في
.gitignore، الشرطة المائلة/في النهاية تطابق المجلدات فقط، وفي البداية تثبّت النمط على ذلك المجلد، و!تعيد تضمين ملف. - السرّ الذي سُجّل في commit ورُفع ولو مرة يجب إلغاؤه واستبداله، لأن السجلّ ما زال يحتويه.