EduFlow
Git و GitHub
⁦0%⁩

الوحدة 4 · عادات احترافية

الـ Stash وملف .gitignore

15 دقراءة 4 داكتشف الخطأ

الدرس في لمحة

اركن العمل غير المكتمل جانبًا بـ git stash وأعده لاحقًا، واكتب ملف .gitignore يُبقي الاعتماديات وناتج البناء والأسرار وفوضى نظام التشغيل خارج الـ repository.

  1. 1الـ Stash: درج للعمل غير المكتمل
  2. 2ملف .gitignore: ملفات يجب ألّا يتتبّعها Git أبدًا
  3. 3كيف تعمل الأنماط
  4. 4التجاهل لا يلغي التتبّع

لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.

أداتان صغيرتان تُبقيان الـ working tree تحت السيطرة. git stash يعطيك درجًا للعمل غير الجاهز للـ commit. و .gitignore يخبر Git بالملفات التي يجب ألّا يتتبّعها أبدًا. وكلتاهما تمنعان النوع نفسه من الحوادث: أن يتسلّل الشيء الخطأ إلى commit.

الـ Stash: درج للعمل غير المكتمل

أنت في منتصف نموذج التواصل في الموقع الشخصي على فرع contact-form، حين ينبّهك أحدهم إلى خطأ إملائي في الصفحة الرئيسية المنشورة. تحتاج إلى main، الآن. لكن git switch main يرفض، لأن تعديلاتك على index.html ستُكتب فوقها، ولا تريد تسجيل نموذج نصف مبني في commit.

خبّئه (stash):

Terminal
git stash push -m "contact form: fields done, validation next"
git status        # nothing to commit, working tree clean

تغييراتك، المجهّزة وغير المجهّزة، تُحفظ في مدخل stash وتُزال من الـ working tree. الآن أصلح الخطأ الإملائي:

Terminal
git switch main
# fix, commit, push
git switch contact-form
git stash pop

الـ pop يعيد تطبيق أحدث stash ويحذفه. وتعود تمامًا إلى حيث كنت.

أوامر الـ stash الأخرى التي ستستخدمها:

Terminal
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، ليتشارك كل من في المشروع القواعد نفسها:

.gitignore
# 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:

Terminal
git check-ignore -v dist/app.js
Text
.gitignore:5:/dist/	dist/app.js

يطبع الملف ورقم السطر والنمط المسؤول.

وللفوضى التي لا يُنشئها إلا جهازك، لا تُثقل ملف .gitignore في كل مشروع. فـ Git يقرأ أيضًا ملف تجاهل عامًا، ~/.config/git/ignore، وهو مكان مناسب لـ .DS_Store ومجلدات المحرّر. ويحتفظ GitHub بمجموعة من قوالب .gitignore الجاهزة لمعظم اللغات، ويعرض عليك واحدًا حين تنشئ repository.

التجاهل لا يلغي التتبّع

.gitignore لا يؤثّر إلا في الملفات غير المتتبَّعة. إن كان .env قد سُجّل في commit قبل أن تتجاهله، فسيواصل Git تتبّعه. أزله من الـ index وأنشئ commit، وهذا يُبقي ملفك المحلي:

Terminal
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 ورُفع ولو مرة يجب إلغاؤه واستبداله، لأن السجلّ ما زال يحتويه.

قراءات إضافية

تحقّق من فهمك

4 أسئلة

السؤال 1 من 4

أنت في منتصف نموذج التواصل حين يلزم إصلاح خطأ إملائي عاجل على main. يرفض git switch main لأنه سيكتب فوق تغييراتك. ما أسرع طريق نظيف؟

السؤال 2 من 4

نفّذت stash، وانتقلت بين الفروع، ثم عدت. أعاد git stash pop تعديلاتك على contact.html لكن ملفك الجديد contact.js مفقود. لماذا؟

السؤال 3 من 4

سجّلت .env في commit الأسبوع الماضي. واليوم تضيف .env إلى .gitignore، لكن git status ما زال يعرض .env على أنه معدّل. لماذا؟

السؤال 4 من 4

أيّ سطر في .gitignore يتجاهل مجلد dist في جذر المشروع دون مجلد src/dist/؟

تدريب

اكتشف الخطأ

أصلح ملف .gitignore في الموقع الشخصي

يقع ملف .gitignore هذا في جذر repository الموقع الشخصي، الذي يحتوي index.html و styles.css و projects.html، وملف .env فيه مفتاح API، و secrets.json، وملفات .DS_Store الخاصة بـ macOS في عدة مجلدات. ثلاثة أسطر لا تفعل ما قصده كاتبها. حدّدها.

حدّد السطر أو الأسطر التي تظنها خاطئة، ثم تحقّق.