دمج الفروع
الدمج هو كيفية دمج التغييرات من فرع إلى آخر. في هذا الدرس، ستتعلم أنواع الدمج المختلفة، وكيفية حل التعارضات، وأفضل الممارسات للحفاظ على تاريخ مشروعك نظيفاً ومنظماً.
ما هو الدمج؟
الدمج يجمع التغييرات من فرع واحد (المصدر) إلى فرع آخر (الهدف):
سيناريوهات الدمج الشائعة:
- دمج فرع الميزة في main (بعد التطوير)
- دمج main في فرع الميزة (حافظ على الميزة محدثة)
- دمج إصلاح الخطأ في فرع الإصدار
- دمج الإصلاح العاجل في كل من main و develop
المفهوم الأساسي: الدمج ينشئ التزاماً جديداً له أبوان - واحد من كل فرع يتم دمجه. هذا يحافظ على التاريخ الكامل لكلا الفرعين.
أمر الدمج الأساسي
سير عمل الدمج الأساسي:
# انتقل إلى الفرع الهدف (حيث تريد التغييرات)
git switch main
# دمج الفرع المصدر في الفرع الحالي
git merge feature-branch
# عرض نتيجة الدمج
git log --oneline --graph
# إذا نجح، فإن تغييرات فرع الميزة الآن في main
دمج التقديم السريع (Fast-Forward)
عندما لم يتغير الفرع الهدف منذ إنشاء الفرع المصدر:
# السيناريو: main لم يتغير منذ إنشاء فرع الميزة
main: A---B
\
feature: C---D
# بعد الدمج (تقديم سريع):
main: A---B---C---D
feature: C---D
# أمر دمج التقديم السريع:
git switch main
git merge feature-branch
# المخرجات: "Fast-forward"
# لم يتم إنشاء التزام دمج - تحرك المؤشر للأمام فقط
نصيحة: عمليات الدمج بالتقديم السريع نظيفة وبسيطة لأنه لا حاجة للدمج الفعلي - Git تحرك مؤشر الفرع للأمام فقط. يبقى التاريخ خطياً.
الدمج الثلاثي (Three-Way Merge)
عندما يكون لكلا الفرعين التزامات جديدة منذ انفصالهما:
# السيناريو: كلا الفرعين لديه تغييرات
main: A---B---E---F
\
feature: C---D
# بعد الدمج الثلاثي:
main: A---B---E---F---M
\ /
feature: C---D---/
# M هو التزام الدمج بأبوين
# أمر الدمج الثلاثي:
git switch main
git merge feature-branch
# Git ينشئ التزام دمج تلقائياً
الفهم: الدمج الثلاثي يستخدم ثلاثة التزامات: السلف المشترك، وطرف الفرع الهدف، وطرف الفرع المصدر. Git يجمع التغييرات من كلا الفرعين بذكاء.
دمج بدون تقديم سريع (No Fast-Forward)
إجبار إنشاء التزام دمج حتى عندما يكون التقديم السريع ممكناً:
# أنشئ دائماً التزام دمج (يحافظ على تاريخ الفرع)
git merge --no-ff feature-branch
# لماذا نستخدم --no-ff؟
✓ يظهر بوضوح أن ميزة تم دمجها
✓ يسهل التراجع عن ميزات كاملة
✓ يحافظ على السياق حول وجود الفرع
✓ أفضل لسير عمل الفريق
# مثال على رسالة التزام الدمج:
Merge branch 'feature-login'
This feature adds user authentication with:
- Login form
- Password validation
- Session management
تعارضات الدمج
التعارضات تحدث عندما لا تستطيع Git دمج التغييرات تلقائياً:
التعارضات تحدث عندما:
- نفس السطر تم تحريره في كلا الفرعين
- ملف محذوف في فرع، معدل في آخر
- نفس الملف تمت إضافته بمحتوى مختلف
- ملفات ثنائية تغيرت في كلا الفرعين
# عند حدوث تعارض:
git merge feature-branch
# Auto-merging file.txt
# CONFLICT (content): Merge conflict in file.txt
# Automatic merge failed; fix conflicts and then commit
مهم: عند حدوث تعارض دمج، تتوقف Git في منتصف الدمج. يجب عليك حل جميع التعارضات وإكمال الدمج يدوياً قبل متابعة العمل.
فهم علامات التعارض
Git تحدد التعارضات في الملفات بعلامات خاصة:
# محتوى ملف متعارض:
<<<<<<< HEAD
const greeting = "Hello from main branch";
=======
const greeting = "Hello from feature branch";
>>>>>>> feature-branch
معاني العلامات:
<<<<<<< HEAD - بداية تغييرات فرعك الحالي
======= - فاصل بين النسختين
>>>>>>> feature-branch - علامة النهاية تظهر الفرع المصدر
# مهمتك: اختر أي نسخة تحتفظ بها (أو ادمجهما)
حل تعارضات الدمج
حل التعارض خطوة بخطوة:
# الخطوة 1: حدد الملفات المتعارضة
git status
# Both modified: file.txt
# Both modified: app.js
# الخطوة 2: افتح الملفات المتعارضة وحررها
# احذف علامات التعارض واختر الكود الصحيح:
# قبل (متعارض):
<<<<<<< HEAD
const version = "1.0";
=======
const version = "2.0";
>>>>>>> feature-branch
# بعد الحل (اختر واحداً أو ادمج):
const version = "2.0";
# الخطوة 3: حدد على أنه محلول
git add file.txt
git add app.js
# الخطوة 4: أكمل الدمج
git commit
# Git يفتح المحرر برسالة التزام الدمج
# يمكنك التحرير أو قبول الرسالة الافتراضية
# الخطوة 5: تحقق من الدمج
git log --oneline --graph
نصيحة احترافية: استخدم git diff لرؤية التعارضات قبل الحل: git diff --name-only --diff-filter=U يعرض الملفات غير المدمجة فقط.
استراتيجيات حل تعارض الدمج
الاستراتيجية 1: قبول الفرع الحالي (Ours)
git checkout --ours file.txt
git add file.txt
الاستراتيجية 2: قبول الفرع الوارد (Theirs)
git checkout --theirs file.txt
git add file.txt
الاستراتيجية 3: التحرير اليدوي
# افتح الملف في المحرر، احلل يدوياً
vim file.txt
git add file.txt
الاستراتيجية 4: استخدام أداة الدمج
git mergetool
# يفتح أداة الدمج المرئية المكونة
# أدوات شائعة: meld, kdiff3, vimdiff, VS Code
إلغاء الدمج
إذا كانت التعارضات معقدة جداً أو تحتاج إلى إعادة النظر:
# إلغاء الدمج والعودة إلى الحالة قبل الدمج
git merge --abort
# هذا آمن - يستعيد كل شيء إلى قبل الدمج
# استخدمه عندما:
✓ التعارضات معقدة جداً للحل فوراً
✓ دمجت الفرع الخطأ
✓ تحتاج إلى استشارة أعضاء الفريق
✓ تريد تجربة نهج مختلف (rebase)
استراتيجيات الدمج
Git تدعم استراتيجيات دمج مختلفة للحالات الخاصة:
# الاستراتيجية التكرارية الافتراضية (تستخدم تلقائياً)
git merge feature-branch
# استراتيجية Ours - احتفظ فقط بتغييرات الفرع الحالي
git merge -s ours old-branch
# استراتيجية Theirs (عبر الخيار) - فضل التغييرات الواردة
git merge -X theirs feature-branch
# استراتيجية Octopus - دمج فروع متعددة مرة واحدة
git merge branch1 branch2 branch3
# استراتيجية Resolve - لفرعين (نادراً ما تستخدم)
git merge -s resolve feature-branch
الاستخدام الشائع: -X theirs و -X ours مفيدة عندما تريد دائماً تفضيل جانب واحد في التعارضات. مثال: git merge -X theirs main يحدث فرع الميزة الخاص بك، مفضلاً تغييرات main في التعارضات.
أفضل الممارسات للدمج
قبل الدمج:
✓ تأكد من أن دليل العمل نظيف
✓ تأكد من أنك على الفرع الهدف الصحيح
✓ اسحب أحدث التغييرات من البعيد
✓ راجع ما سيتم دمجه (git log, git diff)
✓ قم بتشغيل الاختبارات للتأكد من أن الكود يعمل
أثناء الدمج:
✓ اقرأ علامات التعارض بعناية
✓ اختبر بعد حل كل تعارض
✓ لا تقبل جانباً واحداً بشكل أعمى
✓ تواصل مع مؤلفي الكود المتعارض
✓ اكتب رسائل التزام دمج واضحة
بعد الدمج:
✓ قم بتشغيل مجموعة اختبار كاملة
✓ تحقق من أن التطبيق لا يزال يعمل
✓ ادفع التغييرات المدمجة بسرعة
✓ احذف فروع الميزات المدمجة
✓ أبلغ الفريق بإكمال الدمج
سير عمل الدمج العملي
مثال دمج كامل من العالم الحقيقي:
# السيناريو: دمج feature-login في main
# 1. تحضير فرع main
git switch main
git pull origin main
# 2. معاينة الدمج
git log main..feature-login --oneline
git diff main..feature-login --stat
# 3. تنفيذ الدمج
git merge --no-ff feature-login
# 4أ. إذا لم تكن هناك تعارضات:
# حرر رسالة الدمج إذا لزم الأمر، احفظ واخرج
git push origin main
# 4ب. إذا حدثت تعارضات:
git status # انظر الملفات المتعارضة
# حرر الملفات المتعارضة، احلل التعارضات
git add resolved-file1.txt
git add resolved-file2.js
git commit # أكمل الدمج
# 5. تحقق واختبر
git log --oneline --graph -5
npm test # قم بتشغيل الاختبارات
# 6. نظف
git branch -d feature-login
git push origin --delete feature-login
استخدام أدوات الدمج
الأدوات المرئية تجعل حل التعارضات أسهل:
# تكوين أداة الدمج (إعداد لمرة واحدة)
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED'
# أو استخدم الأدوات المدمجة
git config --global merge.tool vimdiff
# عند حدوث تعارضات، قم بتشغيل أداة الدمج
git mergetool
# أداة الدمج تعرض ثلاث لوحات:
# - LOCAL: تغييرات فرعك الحالي
# - BASE: نسخة السلف المشترك
# - REMOTE: تغييرات الفرع الوارد
# - MERGED: النتيجة التي تنشئها
# بعد الحل في الأداة، احفظ واخرج
git commit
تمرين تطبيقي:
السيناريو: تدرب على سير عمل الدمج الكامل مع حل التعارض:
- أنشئ فرعين من main:
feature-a و feature-b
- في كلا الفرعين، عدّل نفس السطر في نفس الملف
- ادمج
feature-a في main (يجب أن ينجح)
- حاول دمج
feature-b في main (سيتعارض)
- احلل التعارض وأكمل الدمج
الأوامر:
# 1. أنشئ الفروع
git switch main
git switch -c feature-a
echo "Version A" > file.txt
git add file.txt
git commit -m "Feature A changes"
git switch main
git switch -c feature-b
echo "Version B" > file.txt
git add file.txt
git commit -m "Feature B changes"
# 2. ادمج feature-a (لا تعارض)
git switch main
git merge feature-a
# 3. حاول دمج feature-b (تعارض!)
git merge feature-b
# CONFLICT!
# 4. احلل التعارض
git status # انظر الملف المتعارض
# حرر file.txt، اختر "Version B" أو ادمج
echo "Version B (resolved)" > file.txt
git add file.txt
# 5. أكمل الدمج
git commit
git log --oneline --graph
# نظف
git branch -d feature-a feature-b
الدمج مقابل Rebase
مقارنة سريعة (سنستكشف rebase بالتفصيل لاحقاً):
استخدم الدمج عندما:
✓ العمل على فروع مشتركة/عامة
✓ تريد الحفاظ على التاريخ الكامل
✓ دمج فروع طويلة العمر
✓ الفريق يفضل التزامات دمج صريحة
✓ العمل مع مساهمين متعددين
استخدم Rebase عندما:
✓ العمل على فروع خاصة/محلية
✓ تريد تاريخاً خطياً ونظيفاً
✓ تحديث فرع الميزة مع main
✓ تحضير فرع للدمج/PR
✓ عمل منفرد أو فريق صغير بتنسيق
القاعدة الذهبية:
لا تعيد أبداً rebase الفروع العامة التي يعمل عليها الآخرون!
الملخص
في هذا الدرس، تعلمت:
- ما هو الدمج ولماذا هو ضروري للتعاون
- الفرق بين التقديم السريع والدمج الثلاثي
- إنشاء التزامات دمج صريحة باستخدام
--no-ff
- فهم وتحديد تعارضات الدمج
- قراءة علامات التعارض وحل التعارضات يدوياً
- استخدام استراتيجيات الدمج (
--ours, --theirs)
- إلغاء عمليات الدمج بأمان باستخدام
git merge --abort
- استخدام أدوات الدمج المرئية لحل أسهل
- أفضل ممارسات سير عمل الدمج الكامل
- متى تستخدم الدمج مقابل rebase
التالي: في الدرس التالي، سنستكشف rebasing - بديل للدمج ينشئ تاريخاً خطياً عن طريق إعادة تشغيل الالتزامات!