Git & GitHub

الدمج في Git — دليل شامل Merge 2026

📅 2026-11-25⏱ 8 دقائق قراءة
في المقال السابق، تعلمت الفروع. الآن سنتعلم **الدمج (Merge)** — كيف نُدمج الفروع ببعضها بأمان واحترافية. في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم الدمج، مع تمارين وحلول. ## ما هو الدمج (Merge)؟ **الدمج** هو **ضم فرع** إلى فرع آخر. **مثال:** - أنت على `main`. - أنشأت `feature/login` وأضفت فيها صفحة تسجيل دخول. - بعد الانتهاء، **تدمج** `feature/login` في `main`. ## أنواع الدمج <table> <thead> <tr> <th>النوع</th> <th>الوصف</th> <th>متى يحدث</th> </tr> </thead> <tbody> <tr> <td><strong>Fast-forward</strong></td> <td>تقديم مباشر</td> <td>عندما لا يوجد تغييرات في main</td> </tr> <tr> <td><strong>Three-way Merge</strong></td> <td>دمج 3 نقاط</td> <td>عندما تغيّر main أيضاً</td> </tr> <tr> <td><strong>Squash Merge</strong></td> <td>دمج كـ commit واحد</td> <td>لتبسيط السجل</td> </tr> <tr> <td><strong>Rebase</strong></td> <td>إعادة ترتيب</td> <td>لتاريخ نظيف</td> </tr> </tbody> </table> ## Fast-forward Merge **يحدث عندما:** - `main` **لم يتغير** منذ إنشاء الفرع. - الفرع **أمام** `main` بعدة commits. **مثال:** ```bash # 1. من main، أنشئ فرعاً git checkout -b feature/login # 2. أضف commits echo "login" > login.html git add . git commit -m "feat: login" echo "styles" > login.css git add . git commit -m "style: login styles" # 3. ارجع لـ main git checkout main # 4. ادمج git merge feature/login ``` **النتيجة:** ``` Updating abc1234..def5678 Fast-forward login.html | 1 + login.css | 1 + 2 files changed, 2 insertions(+) ``` **الفائدة:** سجل **خطي نظيف**. ## Three-way Merge **يحدث عندما:** - `main` **تغيّر** منذ إنشاء الفرع. - لا يمكن "التقديم" مباشرة. **مثال:** ```bash # 1. من main، أنشئ فرعاً git checkout -b feature/login # 2. أضف commit echo "login" > login.html git add . git commit -m "feat: login" # 3. ارجع لـ main، وعدّل git checkout main echo "homepage" > index.html git add . git commit -m "feat: homepage" # 4. ادمج git merge feature/login ``` **النتيجة:** ``` Merge made by the 'ort' strategy. login.html | 1 + 1 file changed, 1 insertion(+) create mode 100644 login.html ``` **Git يُنشئ commit جديد** يجمع التغييرات. ## Squash Merge **يدمج كل commits الفرع في commit واحد.** ```bash git checkout main git merge --squash feature/login git commit -m "feat: إضافة تسجيل الدخول" ``` **الفائدة:** سجل **نظيف** بدون تفاصيل صغيرة. **العيب:** تفقد تاريخ الفرع. ## Rebase **بديل للـ Merge**، يُعيد ترتيب commits. ```bash git checkout feature/login git rebase main # أو git rebase main feature/login ``` **النتيجة:** commits الفرع **تظهر بعد** main. **الميزة:** سجل **خطي تماماً**. **⚠️ تحذير:** لا تستخدم `rebase` على commits **مرفوعة**. ## Merge vs Rebase <table> <thead> <tr> <th>المعيار</th> <th>Merge</th> <th>Rebase</th> </tr> </thead> <tbody> <tr> <td><strong>السجل</strong></td> <td>متشعب</td> <td>خطي</td> </tr> <tr> <td><strong>Commit إضافي</strong></td> <td>✅ نعم</td> <td>❌ لا</td> </tr> <tr> <td><strong>الأمان</strong></td> <td>✅ آمن دائماً</td> <td>⚠️ خطر على commits مرفوعة</td> </tr> <tr> <td><strong>الاستخدام</strong></td> <td>في main</td> <td>في الفروع المحلية</td> </tr> </tbody> </table> **القاعدة الذهبية:** - **`merge`** على `main`. - **`rebase`** على الفروع المحلية قبل الدمج. ## مثال عملي كامل ### السيناريو: إضافة ميزة جديدة **الخطوة 1: تحديث main** ```bash git checkout main git pull ``` **الخطوة 2: إنشاء فرع** ```bash git checkout -b feature/search ``` **الخطوة 3: العمل على الميزة** ```bash echo "<input type='search'>" > search.html git add . git commit -m "feat: إضافة شريط البحث" echo "input { padding: 10px; }" > search.css git add . git commit -m "style: تنسيق شريط البحث" ``` **الخطوة 4: رفع الفرع** ```bash git push -u origin feature/search ``` **الخطوة 5: Pull Request على GitHub** - اذهب إلى GitHub. - اضغط **Compare & pull request**. - املأ الوصف. - اضغط **Create pull request**. **الخطوة 6: بعد المراجعة، الدمج** ```bash git checkout main git pull git merge feature/search git push ``` **الخطوة 7: حذف الفرع** ```bash git branch -d feature/search git push origin --delete feature/search ``` ## فحص ما قبل الدمج ```bash # ما سيُدمج؟ git log main..feature/login --oneline # الفرق بين الفرعين git diff main feature/login # هل سيكون fast-forward؟ git merge --no-commit --no-ff feature/login git merge --abort ``` ## إلغاء الدمج **قبل الـ Commit:** ```bash git merge --abort ``` **بعد الـ Commit:** ```bash git reset --hard HEAD~1 ``` ## الدمج مع استراتيجيات ### 1. `--no-ff` — دائماً إنشاء commit ```bash git merge --no-ff feature/login ``` **الفائدة:** حتى لو fast-forward، يُنشئ commit يوضح الدمج. ### 2. `--ff-only` — Fast-forward فقط ```bash git merge --ff-only feature/login ``` **يفشل** إذا كان three-way مطلوباً. ### 3. `--squash` — دمج كـ commit واحد ```bash git merge --squash feature/login git commit -m "feat: login" ``` ## حل التعارضات (Conflict) **التعارض يحدث** عندما: - نفس السطر تم تعديله في **فرعين**. - Git لا يعرف أي نسخة يفوز. **مثال:** ```bash git checkout main git merge feature/login ``` **النتيجة:** ``` Auto-merging login.html CONFLICT (content): Merge conflict in login.html Automatic merge failed; fix conflicts and then commit the result. ``` **حل التعارض:** ### 1. افتح الملف المتعارض ```html <<<<<<< HEAD <h1>الرئيسية</h1> ======= <h1>تسجيل الدخول</h1> >>>>>>> feature/login ``` **التفسير:** - `<<<<<<< HEAD` → نسخة `main`. - `=======` → فاصل. - `>>>>>>> feature/login` → نسخة الفرع. ### 2. احل التعارض يدوياً ```html <h1>الرئيسية</h1> <h1>تسجيل الدخول</h1> ``` ### 3. أضف الملف ```bash git add login.html ``` ### 4. أنشئ commit ```bash git commit -m "merge: حل تعارض في login.html" ``` ### 5. أدوات مساعدة **VS Code:** يعرض التعارضات بشكل مرئي. **`git mergetool`:** ```bash git mergetool ``` ## أفضل الممارسات ### 1. حدّث main قبل الإنشاء ```bash git checkout main git pull git checkout -b feature/new ``` ### 2. حدّث main قبل الدمج ```bash git checkout main git pull git merge feature/new ``` ### 3. استخدم Pull Requests **لا تدمج مباشرة — افتح PR.** ### 4. اختبر قبل الدمج ```bash npm test npm run build ``` ### 5. فرع = ميزة = PR **لا تجمع ميزات متعددة في فرع واحد.** ### 6. احذف الفروع المدمجة ```bash git branch -d feature/done ``` ## تمارين عملية ### تمرين 1: Fast-forward Merge أنشئ فرعاً وادمجه (fast-forward). **الحل:** ```bash git checkout -b feature/a echo "a" > a.txt git add . && git commit -m "feat: a" git checkout main git merge feature/a ``` ### تمرين 2: Three-way Merge أنشئ تعارضاً بسيطاً وحله. **الحل:** ```bash # على main echo "main" > file.txt && git add . && git commit -m "main" # على فرع git checkout -b feature/b echo "feature" > file.txt && git add . && git commit -m "feature" # ارجع لـ main وعدّل git checkout main echo "main2" > file.txt && git add . && git commit -m "main2" # ادمج git merge feature/b # حل التعارض يدوياً ``` ### تمرين 3: Squash Merge ادمج فرعاً بـ `--squash`. **الحل:** ```bash git checkout main git merge --squash feature/b git commit -m "feat: b" ``` ### تمرين 4: Rebase أعد ترتيب فرع فوق main. **الحل:** ```bash git checkout feature/b git rebase main ``` ### تمرين 5: إلغاء الدمج ادمج ثم ألغِ. **الحل:** ```bash git merge feature/b git reset --hard HEAD~1 ``` ### تمرين 6: --no-ff ادمج مع `--no-ff`. **الحل:** ```bash git merge --no-ff feature/b ``` ### تمرين 7: عرض الفرق اعرض الفرق قبل الدمج. **الحل:** ```bash git diff main feature/b ``` ### تمرين 8: مشروع كامل أنشئ 3 فروع، ادمجها معاً. **الحل:** ```bash # فرع 1 git checkout -b feature/a git commit -m "feat: a" git checkout main git merge feature/a # فرع 2 git checkout -b feature/b git commit -m "feat: b" git checkout main git merge feature/b # فرع 3 git checkout -b feature/c git commit -m "feat: c" git checkout main git merge feature/c ``` ## حل المشاكل الشائعة ### 🔴 المشكلة 1: `CONFLICT` **الحل:** افتح الملف، حل التعارض، `git add`، `git commit`. ### 🔴 المشكلة 2: `Merge aborted` **الحل:** ```bash git merge --abort ``` ### 🔴 المشكلة 3: دمج خاطئ **الحل:** ```bash git reset --hard HEAD~1 ``` ### 🔴 المشكلة 4: `rebase` فشل **الحل:** ```bash git rebase --abort ``` ### 🔴 المشكلة 5: نسيت حل التعارض **الحل:** ```bash git status # يعرض الملفات المتعارضة ``` ## جدول أوامر الدمج <table> <thead> <tr> <th>الأمر</th> <th>الوظيفة</th> </tr> </thead> <tbody> <tr> <td><code>git merge feature</code></td> <td>دمج</td> </tr> <tr> <td><code>git merge --no-ff feature</code></td> <td>دائماً commit</td> </tr> <tr> <td><code>git merge --squash feature</code></td> <td>دمج كـ commit واحد</td> </tr> <tr> <td><code>git merge --abort</code></td> <td>إلغاء</td> </tr> <tr> <td><code>git rebase main</code></td> <td>إعادة ترتيب</td> </tr> <tr> <td><code>git rebase --abort</code></td> <td>إلغاء rebase</td> </tr> <tr> <td><code>git diff main feature</code></td> <td>الفرق</td> </tr> <tr> <td><code>git log main..feature</code></td> <td>commits الفرع</td> </tr> </tbody> </table> ## قائمة تحقق نهائية <table> <thead> <tr> <th>المهمة</th> <th>الحالة</th> </tr> </thead> <tbody> <tr> <td>Fast-forward Merge</td> <td>⬜</td> </tr> <tr> <td>Three-way Merge</td> <td>⬜</td> </tr> <tr> <td>Squash Merge</td> <td>⬜</td> </tr> <tr> <td>Rebase</td> <td>⬜</td> </tr> <tr> <td>حل التعارضات</td> <td>⬜</td> </tr> <tr> <td>إلغاء الدمج</td> <td>⬜</td> </tr> <tr> <td>حل التمارين الثمانية</td> <td>⬜</td> </tr> </tbody> </table> ## ماذا بعد هذا المقال؟ الآن بعد أن أتقنت الدمج، أنت جاهز للمقال التالي: 1. **GitHub** — مقدمة في المنصة. 2. **Pull Requests** — العمل الجماعي. 3. **حل التعارضات المتقدم**. ## الخلاصة في هذا المقال، تعلمت: - ✅ ما هو الدمج. - ✅ أنواع الدمج (Fast-forward، Three-way). - ✅ Squash و Rebase. - ✅ حل التعارضات. - ✅ أفضل الممارسات. - ✅ حل 8 تمارين عملية. **تذكر:** الدمج هو **قلب العمل الجماعي** في Git. أتقنه جيداً.