EduFlow
Git و GitHub
⁦0%⁩

الوحدة 2 · الفروع والدمج

حلّ تعارضات الدمج خطوة بخطوة

17 دقراءة 4 درتّب الخطوات

الدرس في لمحة

اقرأ تعارض الدمج بهدوء، وحرّر علامات التعارض حتى تصل إلى النتيجة التي تريدها، وعلّم الملفات بأنها حُلّت وأكمل الدمج، أو ألغِه وابدأ من جديد.

  1. 1ما يخبرك به Git
  2. 2قراءة العلامات
  3. 3الحلّ خطوة بخطوة
  4. 4الانسحاب
  5. 5جعل التعارضات أسهل في القراءة

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

عاجلًا أو آجلًا سيغيّر فرعان السطر نفسه. تغيّر سطر التعريف (tagline) على main إلى “Front-end developer in Lagos.”، بينما فرعك tagline الذي بدأته في وقت سابق أعاد كتابة السطر نفسه إلى “Front-end developer who loves accessible UI.”. لا يستطيع Git أن يعرف أيهما الصحيح، فيتوقّف ويسأل. هذا كل ما في تعارض الدمج (merge conflict): سؤال. ساعدت مئات الأشخاص في تعارضهم الأول، والذعر يأتي دائمًا من العلامات غير المألوفة، لا من المشكلة نفسها.

ما يخبرك به Git

Terminal
git switch main
git merge tagline
Text
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

أنت الآن في منتصف دمج. الملفات التي اندمجت بلا مشكلة مجهّزة أصلًا. شغّل git status لترى البقية:

Text
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

اقرأ هذا الناتج؛ ففيه الإجراء كاملًا. أصلح التعارضات، وعلّم كل ملف بأنه حُلّ بـ git add، ثم git commit. أو ألغِ الدمج.

قراءة العلامات

افتح index.html. كتب Git النسختين كلتيهما في الملف، محاطتين بعلامات:

index.html
    <h1>Maya Okafor</h1>
<<<<<<< HEAD
    <p>Front-end developer in Lagos.</p>
=======
    <p>Front-end developer who loves accessible UI.</p>
>>>>>>> tagline
  • النصف العلوي، من العلامة الافتتاحية التي تحمل الاسم HEAD حتى =======، هو طرفك: الفرع الذي أنت عليه، وهو هنا main.
  • النصف السفلي، من ======= حتى العلامة الختامية التي تحمل الاسم tagline، هو طرفهم: الفرع الذي تدمجه.

كل ما هو خارج العلامات اندمج دون مشكلة. وقد يحتوي الملف عدة كتل من هذا النوع، فابحث في الملف عن العلامة الافتتاحية (سبعة رموز < متتالية) حتى لا يبقى منها شيء.

في الـ merge base النص 'Front-end developer in progress.' غيّره main إلى 'in Lagos.' وغيّره فرع tagline إلى 'who loves accessible UI.' غيّر الطرفان السطر نفسه، فلا يستطيع Git الاختيار وتكتب أنت النتيجة بيدك. Merge base "…developer in progress." HEAD (main) "…developer in Lagos." tagline "…loves accessible UI." سطر واحد تغيّر مرتين: القرار لك
يقارن Git الطرفين بالـ merge base

الحلّ خطوة بخطوة

1. قرّر ما يجب أن تكون عليه النتيجة. ليس «أيّ الطرفين يفوز» كردّ فعل تلقائي، بل ما الذي يجب أن تقوله الصفحة فعلًا؟ غالبًا تكون النتيجة مزيجًا. وهنا المعلومتان كلتاهما جيدتان:

index.html
    <h1>Maya Okafor</h1>
    <p>Front-end developer in Lagos who loves accessible UI.</p>

2. أزل كل العلامات. يجب أن تختفي أسطر العلامات الثلاثة. لا يقرأ Git الملف ليتحقّق؛ هذه مهمّتك أنت.

3. افحص النتيجة. افتح الصفحة في المتصفّح، وشغّل اختباراتك (npm test حين تصبح للموقع اختبارات)، وشغّل:

Terminal
git diff --check

ينبّهك إلى أي علامات تعارض متبقّية. خمس ثوانٍ في محلّها.

4. علّمه بأنه حُلّ وأكمل.

Terminal
git add index.html
git status        # "All conflicts fixed but you are still merging."
git commit        # editor opens with "Merge branch 'tagline'"; save and close

الأمر git merge --continue يفعل ما يفعله git commit الأخير هذا. والـ merge commit الآن له أبوان، كأي merge commit آخر.

وإن كنت تعرف أن أحد الطرفين يجب أن يفوز في ملف كامل، فتجاوز التحرير: git restore --ours index.html يحتفظ بنسخة فرعك، و git restore --theirs index.html يحتفظ بالنسخة القادمة. ثم نفّذ git add كالمعتاد.

الانسحاب

إن كان التعارض أكبر مما توقّعت، أو دمجت الفرع الخطأ، تستطيع دائمًا التراجع:

Terminal
git merge --abort

يعود فرعك والـ index وملفاتك تمامًا إلى ما كانت عليه قبل git merge. لا يضيع شيء. وكثيرًا ما يكون من الحكمة أن تلغي، ثم تحدّث الفرع أو ترتّبه، وتحاول من جديد بذهن صافٍ.

العلامات نفسها وروتين «أصلِح ثم add ثم أكمل» نفسه يظهران كلما جمع Git نسختين من سطر واحد: أثناء الـ rebase، وحين تطبّق stash، وحين يدمج git pull عمل شخص آخر في عملك. تعلّم الروتين مرة واحدة هنا، وسيبدو كل تعارض لاحق في هذا الكورس مألوفًا. ما يتغيّر فقط هو الأمر الذي تستخدمه للإكمال أو الإلغاء.

جعل التعارضات أسهل في القراءة

افتراضيًا ترى الطرفين فقط. اطلب من Git أن يعرض الأسطر الأصلية أيضًا:

Terminal
git config --global merge.conflictStyle zdiff3

الآن لكل تعارض قسم ثالث بين ||||||| و ======= يعرض الـ merge base. رؤية ما كان عليه السطر قبل أيّ من التغييرين تجعل الجواب الصحيح واضحًا في الغالب: ترى ما قصده كل طرف، لا ما انتهى إليه فقط.

المحرّرات تساعد أيضًا. يميّز VS Code كل كتلة بأزرار مثل Accept Current Change و Accept Incoming Change و Accept Both Changes، إضافة إلى محرّر دمج ثلاثي. استخدمها، لكن اقرأ النتيجة؛ فـ Accept Both كثيرًا ما ينتج وسمَي <p> حيث أردت واحدًا.

الدمج طريقة واحدة لجمع السجلّات. في الدرس التالي ستتعرّف على الطريقة الأخرى، الـ rebase، والقاعدة الوحيدة التي تُبقيه آمنًا.

أهم النقاط

  • التعارض يعني أن الفرعين غيّرا الأسطر نفسها منذ الـ merge base، فيطلب منك Git أن تختار؛ لا شيء ضاع ولا شيء تعطّل.
  • ما بين <<<<<<< و ======= هو فرعك الحالي (HEAD)؛ وما بين ======= و >>>>>>> هو الفرع الذي يُدمج.
  • تحلّ التعارض بتحرير الملف إلى شكله النهائي، وإزالة كل العلامات، ثم git add للملف و git commit.
  • git merge --abort يعيد كل شيء تمامًا كما كان قبل بدء الدمج.
  • ضبط merge.conflictStyle على zdiff3 يعرض الأسطر الأصلية أيضًا، وهذا يجعل الحكم على معظم التعارضات سهلًا.

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

تحقّق من فهمك

4 أسئلة

السؤال 1 من 4

أنت على main وشغّلت git merge tagline. وترى في index.html:

Text
<<<<<<< HEAD
<p>Front-end developer in Lagos.</p>
=======
<p>Front-end developer who loves accessible UI.</p>
>>>>>>> tagline

أيّ السطرين جاء من main؟

السؤال 2 من 4

حرّرت index.html حتى صار كما تريد، وأزلت كل العلامات. لكن git status ما زال يدرجه تحت “Unmerged paths”. ما الخطوة التالية؟

السؤال 3 من 4

في منتصف تعارض فوضوي تدرك أنك دمجت الفرع الخطأ. كيف تعود تمامًا إلى حيث كنت قبل الدمج؟

السؤال 4 من 4

دُمج فرعك ورُفع، ثم يجد زميلك ======= مطبوعة على الصفحة الرئيسية في الموقع المنشور. أيّ عادة كانت ستكتشف هذا قبل الـ commit؟

تدريب

رتّب الخطوات

حُلّ تعارض سطر التعريف

أنت على main وتريد دمج فرع tagline. رتّب الخطوات بالترتيب الذي ستنفّذها به لتنتقل من التعارض إلى merge commit مكتمل.

استخدم أزرار الأسهم لإعادة الترتيب.

  1. 1شغّل git merge tagline لترى CONFLICT (content): Merge conflict in index.html.
  2. 2شغّل git add index.html لتعلّم التعارض بأنه حُلّ.
  3. 3شغّل git commit لتسجيل الـ merge commit.
  4. 4اكتب سطر التعريف النهائي واحذف أسطر العلامات الثلاثة.
  5. 5افتح index.html وجِد كتلة <<<<<<<.
  6. 6شغّل git diff --check وانظر إلى الصفحة في المتصفّح.
  7. 7شغّل git status لعرض المسارات غير المدموجة.