كيفية فهم النزاعات وحلها في Git

ها هي الكلمة التي يكره كل مطور رؤيتها: الصراع. ? لا توجد طريقة للتغلب على تعارض الدمج العرضي عند العمل مع Git (أو أنظمة التحكم في الإصدار الأخرى).

ولكن عند التحدث مع المطورين ، غالبًا ما أسمع أن هناك شعورًا بالقلق أو عدم الراحة حول موضوع تعارضات الدمج.

غالبًا ما يظل التعامل مع النزاعات مكانًا مظلمًا وغامضًا: موقف تتعطل فيه الأشياء بشكل سيء ويكون من غير الواضح كيفية الخروج منه (دون جعل الأمور أسوأ).

في حين أنه من الصحيح أن تعارضات الدمج هي جزء لا يمكن تجنبه من حياة المطور ، فإن الانزعاج في هذه المواقف اختياري تمامًا.

أعتزم من هذه المقالة توضيح هذا الموضوع: كيف ومتى تحدث التعارضات عادةً ، وما هي في الواقع ، وكيفية حلها - أو التراجع عنها.

عندما تفهم هذه الأشياء بشكل صحيح ، ستتمكن من التعامل مع تعارضات الدمج بطريقة أكثر استرخاءً وثقةً. ?

كيف ومتى تحدث النزاعات

يقول الاسم بالفعل: يمكن أن تحدث "تعارضات الدمج" في عملية دمج الالتزامات من مصدر مختلف.

ومع ذلك ، ضع في اعتبارك أن "التكامل" لا يقتصر على "دمج الفروع" فقط. يمكن أن يحدث أيضًا عند إعادة التأسيس أو إعادة التأسيس التفاعلي ، أو عند إجراء اختيار الكرز أو السحب ، أو حتى عند إعادة تطبيق Stash.

تؤدي كل هذه الإجراءات نوعًا من التكامل - وذلك عندما تحدث تعارضات الدمج.

لكن بالطبع ، لا تؤدي هذه الإجراءات إلى تعارض دمج في كل مرة (الحمد لله!). من الناحية المثالية ، يجب ألا تجد نفسك في هذه المواقف إلا نادرًا. لكن متى تحدث الصراعات بالضبط؟

في الواقع ، تعد إمكانات Git الدامجة واحدة من أعظم مزاياها: يعمل دمج الفروع بسهولة في معظم الأوقات ، لأن Git عادة ما تكون قادرة على اكتشاف الأشياء بمفردها.

ولكن هناك مواقف تم فيها إجراء تغييرات متناقضة - وحيث لا تستطيع التكنولوجيا ببساطة أن تقرر ما هو الصواب أو الخطأ. تتطلب هذه المواقف ببساطة قرارًا من إنسان.

الكلاسيكية الحقيقية هي عندما تم تغيير نفس سطر الكود في إلتزامين ، على فرعين مختلفين. ليس لدى Git طريقة لمعرفة التغيير الذي تفضله! ?

هناك بعض المواقف الأخرى المشابهة - على سبيل المثال عندما تم تعديل ملف في فرع وحذفه في فرع آخر - لكنها أقل شيوعًا.

في "برج" بوابة سطح المكتب واجهة المستخدم الرسومية ، على سبيل المثال، لديها طريقة لطيفة تصور مثل هذه الحالات:

كيف تعرف وقت حدوث الصراع

لا تقلق: سيخبرك Git بوضوح شديد عند حدوث تعارض. ?  

أولاً ، سيُعلمك فورًا بالموقف ، على سبيل المثال عند فشل الدمج أو إعادة الأساسي بسبب تعارض:

$ git merge develop Auto-merging index.html CONFLICT (content): Merge conflict in index.html CONFLICT (modify/delete): error.html deleted in HEAD and modified in develop. Version develop of error.html left in tree. Automatic merge failed; fix conflicts and then commit the result.

كما ترى من المثال أعلاه ، عندما حاولت إجراء عملية دمج ، قمت بإنشاء تعارض دمج - ويقوم Git بتوصيل المشكلة بوضوح شديد وعلى الفور:

  • حدث تعارض في ملف "index.html".
  • حدث تعارض آخر في ملف "error.html".
  • وأخيرًا ، بسبب التعارضات ، فشلت عملية الدمج.

هذه هي المواقف التي يتعين علينا فيها البحث في الكود ومعرفة ما يجب القيام به.

في حالة التغاضي عن رسائل التحذير هذه عند حدوث التعارض ، وهو أمر بعيد الاحتمال ، يُعلمك Git أيضًا كلما قمت بتشغيل git status:

$ git status 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/rm ..." as appropriate to mark resolution) deleted by us: error.html both modified: index.html

بمعنى آخر: لا تقلق بشأن عدم ملاحظة تعارضات الدمج. يتأكد Git من أنك لا تستطيع التغاضي عنهم.

كيفية التراجع عن الصراع في Git والبدء من جديد

تأتي صراعات الاندماج مع جو معين من الإلحاح. وهي محقة في ذلك: سيتعين عليك التعامل معهم قبل أن تتمكن من متابعة عملك.

ولكن على الرغم من أن تجاهلها ليس خيارًا ، فإن "التعامل مع تعارضات الدمج" لا يعني بالضرورة أنه يتعين عليك حلها. التراجع عنها ممكن أيضًا!

قد يستحق هذا التكرار: لديك دائمًا خيار التراجع عن تعارض الدمج والعودة إلى الحالة السابقة. هذا صحيح حتى عندما تكون قد بدأت بالفعل في حل الملفات المتعارضة وتجد نفسك في طريق مسدود.

في هذه المواقف ، من الرائع أن تضع في اعتبارك أنه يمكنك دائمًا البدء من جديد والعودة إلى حالة نظيفة قبل حدوث الصراع.

لهذا الغرض ، تأتي معظم الأوامر مع --abortخيار ، على سبيل المثال git merge --abortو git rebase --abort:

$ git merge --abort $ git status On branch main nothing to commit, working tree clean

يجب أن يمنحك هذا الثقة أنك لا تستطيع فعلاً العبث. يمكنك دائمًا الإجهاض والعودة إلى الحالة النظيفة والبدء من جديد.

كيف تبدو الصراعات حقًا في Git

الآن ، مع العلم أنه لا يوجد شيء يمكن أن ينكسر ، دعونا نرى كيف يبدو الصراع تحت الغطاء. سيؤدي ذلك إلى إزالة الغموض عن هؤلاء المتلاعبين الصغار ، وفي نفس الوقت ، سيساعدك على فقدان الاحترام لهم واكتساب الثقة في نفسك.

كمثال ، دعنا نلقي نظرة على محتويات ملف "index.html" (المتعارض حاليًا) في محرر:

كان Git لطيفًا بما يكفي لوضع علامة على منطقة المشكلة في الملف ، وإرفاقها في <<<<<<< HEADو >>>>>>> [other/branch/name]. المحتوى الذي يأتي بعد العلامة الأولى ينشأ من فرع العمل الحالي لدينا. أخيرًا ، =======يفصل سطر به أحرف بين التغييرين المتعارضين.

كيفية حل تضارب في Git

مهمتنا كمطورين الآن هي تنظيف هذه السطور: بعد الانتهاء ، يجب أن يبدو الملف كما نريده تمامًا.

قد يكون من الضروري التحدث إلى زميل الفريق الذي كتب التغييرات "الأخرى" وتحديد الرمز الصحيح بالفعل. ربما يكون هذا ملكًا لنا ، أو ربما يكون ملكهم - أو ربما مزيجًا بين الاثنين.

هذه العملية - تنظيف الملف والتأكد من احتوائه على ما نريده بالفعل - لا يجب أن تنطوي على أي سحر. يمكنك القيام بذلك ببساطة عن طريق فتح محرر النصوص أو IDE والبدء في إجراء التغييرات.

ومع ذلك ، ستجد في كثير من الأحيان أن هذه ليست الطريقة الأكثر فعالية. عندها يمكن للأدوات المخصصة توفير الوقت والجهد:

  • أدوات Git GUI: يمكن أن تكون بعض واجهات المستخدم الرسومية لـ Git مفيدة عند حل التعارضات. و برج بوابة GUI ، على سبيل المثال، تقدم مخصصة "معالج الصراع" التي تساعد على تصور وحل الوضع:
  • Dedicated Merge Tools: For more complicated conflicts, it can be great to have a dedicated "Diff & Merge Tool" at hand. You can configure your tool of choice using the "git config" command. (Consult your tool's documentation for detailed instructions.) Then, in case of a conflict, you can invoke it by simply typing git mergetool. As an example, here's a screenshot of "Kaleidoscope" on macOS:

After cleaning up the file - either manually or in a Git GUI or Merge Tool - we have to commit this like any other change:

  • By using git add on the (previously) conflicted file, we inform Git that the conflict has been solved.
  • When all conflicts have been solved and added to the Staging Area, you need to complete the resolution by creating a regular commit.

How to Become More Confident and Productive

Many years ago, when I started using version control, merge conflicts regularly freaked me out: I was afraid that, finally, I had managed to break things for good. ?

Only when I took the time to truly understand what was going on under the hood was I able to deal with conflicts confidently and efficiently.

The same was true, for example, when dealing with mistakes: only once I learned how to undo mistakes with Git was I able to become more confident and productive in my work.

I highly recommend taking a look at the free "First Aid Kit for Git", a collection of short videos about how to undo and recover from mistakes with Git.

Have fun becoming a better programmer!

About the Author

Tobias Günther هو الرئيس التنفيذي لشركة Tower ، عميل سطح المكتب الشهير Git الذي يساعد أكثر من 100000 مطور حول العالم ليكونوا أكثر إنتاجية مع Git.