git merge

التفرّع والدمج

ضمّ تاريخين تطويريين أو أكثر معًا


يدمج الأمر 'git merge' في الفرع الحالي تغييرات الـ commits المسمّاة (منذ أن تباعد تاريخها عن الفرع الحالي). ينفّذ Git دمج «fast-forward» حين يمكن ذلك (حين يكون الفرع الحالي سلفًا للفرع المدموج)، أو ينشئ «commit دمج» حين يتباعد التاريخان. وإن وُجدت تعارضات بين الفرعين، يتوقف Git ويطلب منك حلّها قبل إكمال الدمج.

الصيغة

git merge [--no-ff | --ff-only] [--squash] [--no-commit] [-m <msg>] [--allow-unrelated-histories] [<commit>...]
git merge (--continue | --abort | --quit)
[ ] اختياري| أو<arg> قيمة تُستبدل... قابل للتكرار--flag خيار

الخيارات

انقر على أي خيار لتوسيعه

مبتدئ (5)

أنشئ commit دمج حتى حين يمكن إنهاء الدمج بـ fast-forward. يحافظ على تاريخ الفرع ويوضّح أين بدأ عمل الميزة وأين انتهى.

عند الحاجةيسجّل commit دمج دائمًا — اختيار حسب عرف الفريق

مثال

git merge --no-ff feature

ارفض الدمج ما لم يكن HEAD الحالي محدَّثًا أصلًا أو أمكن إنهاء الدمج بـ fast-forward. يمنع commits الدمج العرضية.

موصى بهلا ينشئ أبدًا commits دمج مفاجئة؛ ويفشل إذا تباعد التاريخان

مثال

git merge --ff-only feature

ألغِ عملية حل التعارضات الجارية وأعد المستودع إلى حالة ما قبل الدمج. استخدمه حين تريد إلغاء دمج فيه تعارضات.

موصى بهيخرج بأمان من دمج فيه تعارض ويعود إلى ما قبله

مثال

git merge --abort

بعد حل تعارضات الدمج، أنهِ الدمج. يعادل تشغيل git commit بعد حل التعارضات.

موصى بهيُتمّ الدمج بعد حل التعارضات وتجهيزها

مثال

git merge --continue

عيّن رسالة مخصصة لـ commit الدمج. لا يفرض commit دمج: في fast-forward تُتجاهل الرسالة (اجمعه مع ‎--no-ff لتحصل على واحد دائمًا).

عند الحاجةرسالة مخصّصة لـ commit الدمج؛ تُتجاهل عندما يكون الدمج fast-forward

مثال

git merge -m "Integrate login feature" feature

متوسط (2)

اجمع كل commits الفرع المدموج في مجموعة واحدة من التغييرات المجهّزة. لا ينشئ commit ولا يسجّل دمجًا (لا MERGE_HEAD) - تنفّذ الـ commit يدويًا، والنتيجة commit عادي بأب واحد.

عند الحاجةcommit واحد نظيف، لكنه ليس دمجًا حقيقيًا؛ ويحتاج الفرع -D بعدها

مثال

git merge --squash feature

نفّذ الدمج لكن توقّف قبل إنشاء commit. يتيح لك فحص نتيجة الدمج وتعديلها قبل الحفظ. ما زال fast-forward يحدث؛ أضف ‎--no-ff لضمان التوقف.

عند الحاجةافحص النتيجة قبل التسجيل؛ واجمعه مع ‎--no-ff

مثال

git merge --no-commit feature

متقدم (1)

اسمح بدمج تواريخ لا يجمعها سلف مشترك. مفيد عند جمع مستودعين أو مشروعين منفصلين.

عند الحاجةفقط لوصل مشاريع منفصلة عن قصد

مثال

git merge --allow-unrelated-histories other-project/main

اختيار الخيار المناسب

استراتيجيات الدمج

كيف تتحكم في نوع الدمج الذي ينفّذه Git

الأمرينشئ commit دمجيحافظ على التاريخالأنسب لـ
git merge (default)إن تباعدانعمالدمج المعتاد للميزات
git merge --no-ffدائمًانعمتوثيق دمج الميزات
git merge --ff-onlyأبدًاخطي فقطفرض تاريخ نظيف
git merge --squashلا (commit عادي)لا (مسطّح)فرع main نظيف

التعامل مع التعارضات

ماذا تفعل حين يحتوي الدمج على تعارضات

الأمرالإجراءيُبقي العملمتى تستخدمه
(resolve manually)عدّل الملفات، git addنعمتحتاج أجزاء من الطرفين
--continueإكمال الدمجنعمبعد حل التعارضات
--abortإلغاء الدمجحالة ما قبل الدمجلست مستعدًا للحل الآن
checkout --ours/--theirsاختر طرفًانسخة واحدةأحد الطرفين صحيح بوضوح

merge مقابل rebase

طريقتان لدمج التغييرات - بمزايا وعيوب مختلفة

الأمرالتاريخحل التعارضاتالأنسب لـ
git mergeيحافظ على كل الـ commitsمرة واحدةالفروع المشتركة، طلبات الدمج
git rebaseيعيد الكتابة خطيًالكل commitالتنظيف المحلي، الفروع الخاصة
git merge --squashcommit واحدمرة واحدةميزة بتاريخ فوضوي

التحكم في الـ commit

خيارات لتخصيص commit الدمج

الأمريحفظ تلقائيًاحالة الاستخدام
git merge featureنعم (إن لم توجد تعارضات)دمج عادي
git merge --no-commitلا (مجهَّز)المراجعة قبل الـ commit
git merge -m "msg"نعم (يُتجاهل في fast-forward)commits دمج وصفية
git merge --squashلا (يجب الحفظ)جمع كل الـ commits في واحد

أمثلة على سير العمل

1
git checkout main

انتقل إلى الفرع main

2
git pull origin main

اجلب أحدث التغييرات من المستودع البعيد

3
git merge --no-ff feature-branch

ادمج الميزة بـ commit دمج من أجل التاريخ

4
git push origin main

ادفع التغييرات المدموجة إلى المستودع البعيد

5
git branch -d feature-branch

احذف فرع الميزة المدموج

1
git merge feature

حاول الدمج (تظهر تعارضات)

2
git status

اعرف الملفات التي فيها تعارضات

3
(edit conflicted files)

ابحث عن علامات <<<<<<< وحلّها يدويًا

4
git add <resolved-files>

جهّز الملفات المحلولة

5
git merge --continue

أكمل الدمج بـ commit

1
git checkout main

انتقل إلى الفرع main

2
git merge --squash feature-branch

اجمع كل الـ commits في تغييرات مجهّزة

3
git commit -m "Add feature X"

أنشئ commit واحدًا نظيفًا بكل التغييرات

4
git branch -D feature-branch

احذف فرع الميزة بالإجبار

1
git merge feature

ابدأ الدمج (تظهر مشكلات)

2
git status

اعرض حالة التعارض

3
git merge --abort

ألغِ واستعد حالة ما قبل الدمج

4
git status

تأكد أنك عدت إلى حالة نظيفة

حل المشكلات

CONFLICT (content): Merge conflict in file.js

السبب: عدّل الفرعان الأسطر نفسها في الملف

افتح الملف، وابحث عن علامات <<<<<<<، وحلّ التعارض، ثم git add وgit merge --continue

fatal: refusing to merge unrelated histories

السبب: ليس للفرعين سلف مشترك (مستودعات منفصلة)

استخدم git merge --allow-unrelated-histories إن كنت تريد عمدًا جمع مشاريع منفصلة

Already up to date

السبب: الفرع الذي تدمجه مضمَّن أصلًا في فرعك الحالي

لا شيء لفعله - فرعك يحتوي أصلًا كل commits الهدف

error: Your local changes to the following files would be overwritten by merge

السبب: لديك تغييرات غير محفوظة تتعارض مع الدمج

احفظ تغييراتك في commit، أو خبّئها (git stash)، أو تخلّص منها قبل الدمج

تمّ الدمج لكنني أردت المراجعة أولًا

السبب: حفظ Git الدمج تلقائيًا

في المرة القادمة استخدم ‎--no-ff --no-commit. لإعادته: git reset --merge ORIG_HEAD، ثم ادمج مجددًا مع ‎--no-commit

نصائح وأخطاء شائعة

أفضل الممارسات

  • ✓اسحب دائمًا أحدث التغييرات قبل الدمج لتقليل التعارضات
  • ✓استخدم ‎--no-ff لفروع الميزات للحفاظ على سياق الدمج في التاريخ
  • ✓اكتب رسائل دمج وصفية تشرح ما الذي دُمج
  • ✓احذف فروع الميزات بعد الدمج ليبقى المستودع نظيفًا
  • ✓اختبر شيفرتك بعد الدمج وقبل الدفع للتأكد أن شيئًا لم يتعطل
  • ✓استخدم git merge --abort إن لم تكن مستعدًا لحل التعارضات - لا تترك الدمج في حالة معطوبة
  • ✓في الفروع طويلة الأمد، ادمج main في فرع ميزتك دوريًا لتقليل تعارضات الدمج النهائي

أخطاء متكررة

  • ✗الدمج دون سحب أحدث التغييرات من المستودع البعيد أولًا. نفّذ دائمًا 'git pull' قبل الدمج لتجنّب التعارضات.
  • ✗تجهيز ملفات ما زالت فيها علامات التعارض. يمنع Git الـ commits ما دامت هناك مسارات غير مدموجة، لكن بمجرد أن تنفّذ 'git add' على ملف يحفظ علامات <<<<<<< كما هي.
  • ✗استخدام دمج fast-forward لفروع الميزات يُضيّع تاريخ الفرع. استخدم '--no-ff' للحفاظ على السياق.
  • ✗تشغيل 'git merge --abort' بعد حل التعارضات يدويًا يُضيّع كل عمل الحل.
  • ✗الدمج في الفرع الخطأ. تحقّق دائمًا بـ 'git branch' أنك على الفرع الهدف الصحيح قبل الدمج.

الأسئلة الشائعة

A:

يحافظ merge على التاريخ وينشئ commit دمج. ويعيد rebase كتابة التاريخ ليصبح خطيًا. استخدم merge للفروع المشتركة، وrebase للتنظيف المحلي.

A:

استخدم ‎--no-ff عند دمج فروع الميزات في main. ينشئ commit دمج يوثّق متى دُمجت الميزة، حتى لو كان fast-forward ممكنًا.

A:

إن لم يُدفع: git reset --hard ORIG_HEAD (يعمل مع fast-forward أيضًا؛ ويتخلّص من التغييرات غير المحفوظة). إن دُفع: git revert -m 1 <merge-commit> لإنشاء commit جديد يلغي الدمج.

A:

يحدث fast-forward حين لا يحتوي فرعك على commits جديدة منذ نقطة التفرّع. فيحرّك Git المؤشر إلى الأمام فقط بدل إنشاء commit دمج.

A:

افتح الملفات المتعارضة، وابحث عن علامات <<<<<<<، وعدّلها لتُبقي الشيفرة التي تريدها، وأزل العلامات، ثم نفّذ git add على الملفات وgit merge --continue.

A:

الدمج العادي يحافظ على كل تاريخ الـ commits. ودمج squash يجمع كل شيء في commit واحد. استخدم squash حين يحتوي فرع الميزة على commits مؤقتة فوضوية لا تريدها في main.