حل التعارضات في Git خطوة بخطوة
في درس الفروع رأيت تعارضاً بسيطاً في سطر واحد وحللته بيدك. في العمل الحقيقي التعارضات أكبر: عدة ملفات في دمج واحد، وأحياناً تريد نسخة زميلك كاملة، وأحياناً تريد إلغاء الدمج كله والتفكير من جديد. في هذا الدرس ستتعلم التعامل مع التعارضات بهدوء وبأدوات واضحة، حتى تصبح أمراً روتينياً لا يخيفك.
متى يحدث التعارض؟
Section titled “متى يحدث التعارض؟”Git يدمج التعديلات تلقائياً ما دامت في أماكن مختلفة: ملفان مختلفان، أو سطور متباعدة في الملف نفسه. التعارض يحدث فقط حين يعدّل الفرعان السطور نفسها بشكلين مختلفين، أو حين يعدّل أحدهما ملفاً حذفه الآخر.
تخيّل زميلين يعدّلان مستنداً مطبوعاً: إذا عدّل كل منهما فقرة مختلفة فالجمع سهل. أما إذا أعاد كل منهما كتابة الجملة نفسها فلا بد من إنسان يقرر الصيغة النهائية.
المشهد: دمج بتعارضين
Section titled “المشهد: دمج بتعارضين”في مشروعنا فرع dark-theme غيّر لون العنوان في style.css وعدّل عنوان index.html وأضاف ملفاً جديداً. وفي الوقت نفسه غيّرنا في main السطرين نفسيهما بطريقة أخرى:
git merge dark-themeAuto-merging index.htmlCONFLICT (content): Merge conflict in index.htmlAuto-merging style.cssCONFLICT (content): Merge conflict in style.cssAutomatic merge failed; fix conflicts and then commit the result.تعارضان في ملفين. الدمج لم يفشل، بل توقف في منتصفه ينتظر قرارك.
أول خطوة دائماً: git status
Section titled “أول خطوة دائماً: git status”git statusOn branch mainYou have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge)
Changes to be committed: new file: footer.html
Unmerged paths: (use "git add <file>..." to mark resolution) both modified: index.html both modified: style.cssاقرأ الرسالة جيداً، ففيها كل ما تحتاج:
Changes to be committed: ما دُمج تلقائياً بلا مشاكل (الملف الجديدfooter.html).Unmerged paths: الملفات التي تنتظر حلاً. وboth modifiedتعني أن الفرعين عدّلا الملف.- وبين الأقواس تذكير بالأوامر المتاحة: الحل ثم
commit، أو الإلغاء.
وهذا محتوى style.css الآن:
<<<<<<< HEADh1 { color: green; }=======h1 { color: white; }>>>>>>> dark-themebody { font-size: 16px; }ما بين <<<<<<< HEAD و ======= نسختك الحالية، وما بعدها حتى >>>>>>> نسخة الفرع القادم. والسطر الأخير خارج العلامات: دُمج بلا مشاكل.
زر الطوارئ: merge –abort
Section titled “زر الطوارئ: merge –abort”التعارض أكبر مما توقعت، أو لست متأكداً من القرار؟ ألغِ الدمج كله وارجع لما قبله:
git merge --abortgit status --shortgit log --oneline -1f29b601 ألوان خضراء وعنوان رسميgit status --short لم تطبع شيئاً: المجلد نظيف، والعلامات اختفت من الملفات، والفرع عند آخر commit كأنك لم تبدأ الدمج. اسأل زميلك، ثم أعد المحاولة متى شئت.
الحل الأول: خذ نسخة كاملة
Section titled “الحل الأول: خذ نسخة كاملة”نعيد الدمج. في style.css قررنا أن ألوان الوضع الليلي هي الصحيحة كاملة، فلا داعي لتحرير الملف بيدنا:
git merge dark-themegit checkout --theirs style.cssUpdated 1 path from the index--theirs: نسخة الفرع القادم (dark-theme).--ours: نسخة الفرع الحالي (main).
الملف الآن نظيف وفيه color: white، بلا أي علامات. ثم نخبر Git أن التعارض حُل:
git add style.cssgit status --shortA footer.htmlUU index.htmlM style.cssUU تعني «ما زال متعارضاً». بقي ملف واحد.
الحل الثاني: التحرير اليدوي
Section titled “الحل الثاني: التحرير اليدوي”في index.html لا نريد أياً من النسختين كما هي، بل صيغة تجمعهما. نفتح الملف، ونحذف العلامات الثلاث، ونكتب السطر النهائي، ونحفظ. ثم:
git add index.htmlgit statusOn branch mainAll conflicts fixed but you are still merging. (use "git commit" to conclude merge)
Changes to be committed: new file: footer.html modified: style.css«كل التعارضات حُلّت، لكنك ما زلت في منتصف الدمج». تبقى خطوة الإنهاء:
git commit -m "دمج الوضع الليلي مع حل التعارضات"git log --oneline --graph -4* 241edea دمج الوضع الليلي مع حل التعارضات|\| * 3d5adcd الوضع الليلي* | f29b601 ألوان خضراء وعنوان رسمي|/* 31b963a إضافة style.cssالرسم يوضح القصة: خطان افترقا ثم التقيا في commit الدمج.
الخطوات باختصار
Section titled “الخطوات باختصار”git statusلمعرفة الملفات المتعارضة.- لكل ملف: حرّره يدوياً، أو خذ نسخة كاملة بـ
--oursأو--theirs. git addلكل ملف بعد حله.git commitلإنهاء الدمج.- في أي لحظة قبل الخطوة الرابعة:
git merge --abortللتراجع.
لا تنسَ علامة!
Section titled “لا تنسَ علامة!”أخطر خطأ: أن تنفّذ git add وفي الملف علامات تعارض منسية، فتدخل المشروع وتكسره. تحقق قبل الحفظ:
git diff --checknote.md:1: leftover conflict markernote.md:3: leftover conflict markernote.md:5: leftover conflict markerالأمر يدلك على كل علامة منسية برقم سطرها. وبعد الحل شغّل المشروع وتأكد أنه يعمل: Git يضمن أن الملفات خالية من العلامات، لا أن الكود صحيح.
التعارض عند git pull
Section titled “التعارض عند git pull”git pull يجلب تعديلات زملائك ثم يدمجها. فإذا عدّلوا السطور التي عدّلتها ظهرت الرسائل نفسها، والحل بالخطوات نفسها تماماً: status، ثم الحل، ثم add، ثم commit، ثم git push.
كيف تقلل التعارضات؟
Section titled “كيف تقلل التعارضات؟”- اسحب كثيراً: ابدأ يومك بـ
git pull، وادمجmainفي فرعك كل يوم أو يومين. - فروع قصيرة العمر: فرع يعيش يومين يتعارض أقل بكثير من فرع يعيش شهراً.
- commits صغيرة ومركزة: تعديل واحد واضح في كل commit.
- تواصل مع فريقك: إذا كنتما ستعدّلان الملف نفسه، فاتفقا مسبقاً.
- لا تعد تنسيق ملفات كاملة دون داعٍ: تغيير المسافات في كل السطور يتعارض مع كل من يعمل على الملف.
جرّب بنفسك
Section titled “جرّب بنفسك”- في مستودع تجريبي أنشئ ملفاً من ثلاثة أسطر واحفظه.
- أنشئ فرعاً وعدّل فيه السطر الأول، ثم عد إلى
mainوعدّل السطر نفسه بشكل مختلف، واحفظ في كل فرع. - ادمج، واقرأ
git status، ثم ألغِ الدمج بـgit merge --abort. - أعد الدمج وحل التعارض مرة بـ
--ours، ثم كرر التجربة كلها وحلّه يدوياً.
أخطاء شائعة
Section titled “أخطاء شائعة”- الخلط بين ours و theirs:
oursالفرع الذي تقف عليه، وtheirsالفرع الذي تدمجه. راجع الملف بعد الاختيار. - نسيان
git addبعد الحل: يبقى الملفUUويرفض Git إنهاء الدمج. - حذف نسخة الزميل دون قراءة: اختيار نسختك دائماً يمحو عمل غيرك بصمت. افهم التعديلين قبل القرار.
- علامات منسية: استخدم
git diff --checkوجرّب المشروع قبلcommit.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
أنت على الفرع main وتدمج الفرع feature. أي أمر يأخذ نسخة feature كاملة لملف متعارض؟
theirs تعني الفرع القادم الذي تدمجه، و ours الفرع الحالي الذي تقف عليه.
سؤال
ماذا يفعل git merge --abort أثناء دمج فيه تعارضات؟
يعيد المستودع إلى حالته قبل بدء الدمج، دون أي أثر للعلامات.
الخلاصة
Section titled “الخلاصة”- التعارض يحدث عند تعديل السطور نفسها في فرعين، والدمج يتوقف منتظراً قرارك.
git statusيعرض الملفات المتعارضة والأوامر المتاحة.git merge --abortيلغي الدمج بأمان في أي لحظة قبل الحفظ.- الحل: تحرير يدوي أو
--ours/--theirs، ثمgit add، ثمgit commit. git diff --checkيكشف العلامات المنسية، والسحب المتكرر يقلل التعارضات.