الوحدة الخامسة: أفضل الممارسات وقوة الـ git reset
في حياة المبرمج المحترف، تقع الأخطاء أحياناً. قد تقوم بعمل commit لملف يحتوي على كلمات مرور بالخطأ، أو تنسى إضافة ملف مهم، أو تكتشف أن ميزة كاملة كانت فكرة سيئة. هنا تأتي قوة (وخطورة) أداة git reset.
1. الأنماط الثلاثة لـ reset
git reset هو أداة قوية للتراجع عن التغييرات عن طريق تحويل مؤشر الفرع لـ commit سابق، ولها 3 أوضاع رئيسية:
| الوضع (Mode) | ماذا يحدث للـ Commit؟ | ماذا يحدث للملفات؟ | متى نستخدمه؟ |
|---|---|---|---|
--soft | يتم إلغاؤه من التاريخ | تبقى التغييرات في منطقة التحضير (Staging) | نسيت إضافة ملف للـ commit الأخير |
--mixed | يتم إلغاؤه من التاريخ | تعود التغييرات لملفاتك (غير محضرّة) | تريد إعادة تنظيم وتوزيع الـ commits |
--hard | يتم إلغاؤه من التاريخ | تُحذف التغييرات تماماً من جهازك | الكود الحالي كارثي وتريد مسحه بالكامل |
2. سيناريوهات عملية للتراجع
السيناريو 1: أريد إلغاء commit مع الاحتفاظ بالتغييرات (Soft)
تخيل أنك قمت بعمل commit، ثم اكتشفت أنك نسيت إضافة ملف config.js. لا تريد حذف تعبك، فقط تريد إلغاء الـ commit لتضيف الملف وتجرب مجدداً.
# العودة خطوة للوراء مع إبقاء الكود في منطقة التحضير
git reset --soft HEAD~1
# الآن أضف الملف الناقص
git add config.js
# قم بعمل commit جديد
git commit -m "feat: add initial configuration"السيناريو 2: أريد إلغاء commit وإعادة الملفات كما كانت (Hard)
إذا قمت بعمل تغييرات خربت المشروع تماماً، وتريد العودة للنقطة التي كان فيها المشروع مستقراً.
# ⚠️ تحذير: أي تغييرات غير محفوظة ستضيع تماماً!
git reset --hard HEAD~13. البديل الآمن: git revert
إذا كنت قد رفعت الـ commit للسيرفر (GitHub) ولا تريد تغيير تاريخ المشروع المشترك مع زملائك:
# ينشئ commit جديداً يقوم بعكس تأثير آخر commit
git revert HEAD
# هذا أفضل للعمل الجماعي لأنه لا يعيد كتابة التاريخ بل يضيف عليهالسيناريو 3: "أخطأت في كتابة رسالة الـ commit الأخيرة"
إذا لم تكن قد رفعت الـ commit بعد إلى GitHub، يمكنك تعديله:
git commit --amend -m "الرسالة الصحيحة هنا"4. نصيحة ذهبية قبل الاستخدام
قبل استخدام --hard أو أي نوع من الـ reset، تأكد دائماً من حالة مشروعك:
git status # لرؤية إذا كان هناك تغييرات لم تحفظها
git log --oneline -3 # للتأكد من الـ commit الذي تريد العودة إليه5. قوة ملف .gitignore
كما ذكرنا سابقاً، يجب على Git تتبع ما هو ضروري فقط. إليك نظرة مفصلة على ما يحتوي عليه ملف .gitignore احترافي لمشروع ويب حديث:
# المجلدات التابعة (Dependencies)
node_modules/
.pnpm-store/
# مخرجات البناء (Build outputs)
dist/
build/
.next/
# ملفات البيئة (الأسرار! لا تقم برفعها أبداً)
.env
.env.local
.env.*.local
# ملفات المحرر (IDE Files)
.vscode/
.idea/
# ملفات النظام
.DS_Store
Thumbs.dbWARNING
إذا قمت بإضافة ملف إلى Git ثم أضفته لاحقًا إلى .gitignore، فلن يتوقف Git عن تتبعه تلقائيًا. لحذفه من التتبع دون حذف الملف من جهازك:
git rm --cached filenameثم:
git commit -m "chore: stop tracking file"6. قوة ملف .gitattributes
إذا كان .gitignore يتحكم في ما يتم تتبعه، فإن .gitattributes يتحكم في كيفية تعامل Git مع الملفات التي يتم تتبعها.
هو ملف متقدم نسبيًا، لكنه مهم في المشاريع الاحترافية.
1- توحيد أسطر نهاية السطر (Line Endings)
المشكلة:
- Windows يستخدم CRLF
- macOS/Linux يستخدم LF
- يؤدي ذلك إلى اختلافات وهمية في commits
الحل داخل .gitattributes:
* text=autoأو بشكل أدق:
*.js text eol=lf
*.ts text eol=lf
*.css text eol=lf
*.html text eol=lfهذا يفرض توحيد نهاية السطر في جميع الأنظمة.
2- تعريف الملفات الثنائية (Binary Files)
بعض الملفات لا يجب أن يحاول Git مقارنتها كنصوص:
*.png binary
*.jpg binary
*.pdf binaryهذا يمنع Git من محاولة عرض اختلافات غير مفهومة.
3- تخصيص استراتيجية الدمج
يمكنك تحديد كيفية دمج أنواع معينة من الملفات:
*.lock merge=oursمثال عملي: بعض الفرق تختار عدم دمج ملفات lock تلقائيًا بل الاعتماد على نسخة الفرع الحالي.
4- تجاهل الاختلافات في المسافات البيضاء
*.md whitespace=blank-at-eolيساعد على تقليل الضوضاء في المقارنات.
7. مشاكل شائعة وكيف تتصرف
1- Outgoing changes
لديك commits محليًا لم يتم رفعها.
الحل:
git push2- حذفت فرعًا بالخطأ
تحقق من reflog:
git reflogثم:
git checkout -b branch-name <commit-hash>3- main متقدم أو متأخر عن الريموت
تحقق:
git statusإذا ظهرت:
Your branch is ahead of 'origin/main'الحل:
git push8. أفضل Workflow لمطور يعمل منفردًا
# إنشاء فرع
git switch -c feature/x
# العمل
git add .
git commit -m "feat: add x"
# الدمج
git switch main
git merge --no-ff feature/x
git push
# حذف الفرع
git branch -d feature/xهذا الأسلوب:
- منظم
- آمن
- واضح في الشجرة
- قريب من أسلوب الفرق الاحترافية
كلمات ختامية
لقد أصبحت الآن تمتلك الأدوات لبناء، مشاركة، وحتى "التراجع" عن عملك باحترافية. سر إتقان Git هو عدم الخوف من الأوامر بل فهم كيف تحرك كودك بين المراحل الثلاث.
بالتوفيق في رحلتك البرمجية! 🚀