{"id":"l-git-2-3","courseId":"git-github","lang":"ar","kind":"lesson","summary":"اقرأ تعارض الدمج بهدوء، وحرّر علامات التعارض حتى تصل إلى النتيجة التي تريدها، وعلّم الملفات بأنها حُلّت وأكمل الدمج، أو ألغِه وابدأ من جديد.","html":"<p>عاجلًا أو آجلًا سيغيّر فرعان السطر نفسه. تغيّر سطر التعريف (tagline) على <code dir=\"ltr\">main</code> إلى “Front-end developer in Lagos.”، بينما فرعك <code dir=\"ltr\">tagline</code> الذي بدأته في وقت سابق أعاد كتابة السطر نفسه إلى “Front-end developer who loves accessible UI.”. لا يستطيع Git أن يعرف أيهما الصحيح، فيتوقّف ويسأل. هذا كل ما في تعارض الدمج (merge conflict): سؤال. ساعدت مئات الأشخاص في تعارضهم الأول، والذعر يأتي دائمًا من العلامات غير المألوفة، لا من المشكلة نفسها.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">ما يخبرك به Git</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> switch</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> main</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> merge</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> tagline</span></span></code></pre></div>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Text</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>Auto-merging index.html\nCONFLICT (content): Merge conflict in index.html\nAutomatic merge failed; fix conflicts and then commit the result.</code></pre></div>\n<p>أنت الآن <em>في منتصف دمج</em>. الملفات التي اندمجت بلا مشكلة مجهّزة أصلًا. شغّل <code dir=\"ltr\">git status</code> لترى البقية:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Text</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>On branch main\nYou have unmerged paths.\n  (fix conflicts and run &quot;git commit&quot;)\n  (use &quot;git merge --abort&quot; to abort the merge)\n\nUnmerged paths:\n  (use &quot;git add &lt;file&gt;...&quot; to mark resolution)\n\tboth modified:   index.html\n\nno changes added to commit (use &quot;git add&quot; and/or &quot;git commit -a&quot;)</code></pre></div>\n<p>اقرأ هذا الناتج؛ ففيه الإجراء كاملًا. أصلح التعارضات، وعلّم كل ملف بأنه حُلّ بـ <code dir=\"ltr\">git add</code>، ثم <code dir=\"ltr\">git commit</code>. أو ألغِ الدمج.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">قراءة العلامات</h2>\n<p>افتح <code dir=\"ltr\">index.html</code>. كتب Git النسختين كلتيهما في الملف، محاطتين بعلامات:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"html\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">index.html</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Maya Okafor&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#82071E;--shiki-light-font-style:italic;--shiki-dark:#FFA198;--shiki-dark-font-style:italic\">&#x3C;&#x3C;&#x3C;&#x3C;&#x3C;&#x3C;&#x3C;</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> HEAD</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Front-end developer in Lagos.&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=======</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Front-end developer who loves accessible UI.&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>>>>>>> tagline</span></span></code></pre></div>\n<ul>\n<li>النصف العلوي، من العلامة الافتتاحية التي تحمل الاسم <code dir=\"ltr\">HEAD</code> حتى <code dir=\"ltr\">=======</code>، هو <strong>طرفك</strong>: الفرع الذي أنت عليه، وهو هنا <code dir=\"ltr\">main</code>.</li>\n<li>النصف السفلي، من <code dir=\"ltr\">=======</code> حتى العلامة الختامية التي تحمل الاسم <code dir=\"ltr\">tagline</code>، هو <strong>طرفهم</strong>: الفرع الذي تدمجه.</li>\n</ul>\n<p>كل ما هو خارج العلامات اندمج دون مشكلة. وقد يحتوي الملف عدة كتل من هذا النوع، فابحث في الملف عن العلامة الافتتاحية (سبعة رموز <code dir=\"ltr\">&lt;</code> متتالية) حتى لا يبقى منها شيء.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 250\" role=\"img\" aria-labelledby=\"l-git-2-3-t1\"><defs><marker id=\"arrow-l-git-2-3-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-git-2-3-t1\">في الـ merge base النص 'Front-end developer in progress.' غيّره main إلى 'in Lagos.' وغيّره فرع tagline إلى 'who loves accessible UI.' غيّر الطرفان السطر نفسه، فلا يستطيع Git الاختيار وتكتب أنت النتيجة بيدك.</title>\n  <rect class=\"d-box\" x=\"230\" y=\"15\" width=\"240\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"350\" y=\"38\" text-anchor=\"middle\">Merge base</text>\n  <text class=\"d-label-muted\" x=\"350\" y=\"60\" text-anchor=\"middle\">\"…developer in progress.\"</text>\n  <rect class=\"d-box-accent\" x=\"20\" y=\"105\" width=\"270\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"155\" y=\"128\" text-anchor=\"middle\">HEAD (main)</text>\n  <text class=\"d-label-muted\" x=\"155\" y=\"150\" text-anchor=\"middle\">\"…developer in Lagos.\"</text>\n  <rect class=\"d-box-accent\" x=\"410\" y=\"105\" width=\"270\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"545\" y=\"128\" text-anchor=\"middle\">tagline</text>\n  <text class=\"d-label-muted\" x=\"545\" y=\"150\" text-anchor=\"middle\">\"…loves accessible UI.\"</text>\n  <path class=\"d-arrow\" d=\"M300 71 L190 103\" marker-end=\"url(#arrow-l-git-2-3-1)\"/>\n  <path class=\"d-arrow\" d=\"M400 71 L510 103\" marker-end=\"url(#arrow-l-git-2-3-1)\"/>\n  <rect class=\"d-box-warn\" x=\"190\" y=\"190\" width=\"320\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"350\" y=\"220\" text-anchor=\"middle\">سطر واحد تغيّر مرتين: القرار لك</text>\n  <path class=\"d-arrow\" d=\"M155 161 L260 188\" marker-end=\"url(#arrow-l-git-2-3-1)\"/>\n  <path class=\"d-arrow\" d=\"M545 161 L440 188\" marker-end=\"url(#arrow-l-git-2-3-1)\"/>\n</svg><figcaption>يقارن Git الطرفين بالـ merge base</figcaption></figure>\n<h2 id=\"sec-3\" tabindex=\"-1\">الحلّ خطوة بخطوة</h2>\n<p><strong>1. قرّر ما يجب أن تكون عليه النتيجة.</strong> ليس «أيّ الطرفين يفوز» كردّ فعل تلقائي، بل ما الذي يجب أن تقوله الصفحة فعلًا؟ غالبًا تكون النتيجة مزيجًا. وهنا المعلومتان كلتاهما جيدتان:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"html\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">index.html</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Maya Okafor&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Front-end developer in Lagos who loves accessible UI.&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span></code></pre></div>\n<p><strong>2. أزل كل العلامات.</strong> يجب أن تختفي أسطر العلامات الثلاثة. لا يقرأ Git الملف ليتحقّق؛ هذه مهمّتك أنت.</p>\n<p><strong>3. افحص النتيجة.</strong> افتح الصفحة في المتصفّح، وشغّل اختباراتك (<code dir=\"ltr\">npm test</code> حين تصبح للموقع اختبارات)، وشغّل:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"5\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> diff</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --check</span></span></code></pre></div>\n<p>ينبّهك إلى أي علامات تعارض متبقّية. خمس ثوانٍ في محلّها.</p>\n<p><strong>4. علّمه بأنه حُلّ وأكمل.</strong></p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"6\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> add</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> index.html</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> status</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">        # \"All conflicts fixed but you are still merging.\"</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> commit</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">        # editor opens with \"Merge branch 'tagline'\"; save and close</span></span></code></pre></div>\n<p>الأمر <code dir=\"ltr\">git merge --continue</code> يفعل ما يفعله <code dir=\"ltr\">git commit</code> الأخير هذا. والـ merge commit الآن له أبوان، كأي merge commit آخر.</p>\n<p>وإن كنت تعرف أن أحد الطرفين يجب أن يفوز في ملف كامل، فتجاوز التحرير: <code dir=\"ltr\">git restore --ours index.html</code> يحتفظ بنسخة فرعك، و <code dir=\"ltr\">git restore --theirs index.html</code> يحتفظ بالنسخة القادمة. ثم نفّذ <code dir=\"ltr\">git add</code> كالمعتاد.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>تسجيل العلامات في commit</span></p>\n<p>أكثر أخطاء التعارض شيوعًا ليس الاختيار الخاطئ؛ بل سطر <code dir=\"ltr\">=======</code> شارد أو سطر علامة ختامية يُسجَّل في الملف، ويصل أحيانًا إلى بيئة الإنتاج. لن يوقفك Git، لأنه بالنسبة إليه مجرد نص. اجعل <code dir=\"ltr\">git diff --check</code> والنظر الفعلي إلى الصفحة جزءًا من كل حلّ.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">الانسحاب</h2>\n<p>إن كان التعارض أكبر مما توقّعت، أو دمجت الفرع الخطأ، تستطيع دائمًا التراجع:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"7\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> merge</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --abort</span></span></code></pre></div>\n<p>يعود فرعك والـ index وملفاتك تمامًا إلى ما كانت عليه قبل <code dir=\"ltr\">git merge</code>. لا يضيع شيء. وكثيرًا ما يكون من الحكمة أن تلغي، ثم تحدّث الفرع أو ترتّبه، وتحاول من جديد بذهن صافٍ.</p>\n<p>العلامات نفسها وروتين «أصلِح ثم add ثم أكمل» نفسه يظهران كلما جمع Git نسختين من سطر واحد: أثناء الـ rebase، وحين تطبّق stash، وحين يدمج <code dir=\"ltr\">git pull</code> عمل شخص آخر في عملك. تعلّم الروتين مرة واحدة هنا، وسيبدو كل تعارض لاحق في هذا الكورس مألوفًا. ما يتغيّر فقط هو الأمر الذي تستخدمه للإكمال أو الإلغاء.</p>\n<h2 id=\"sec-5\" tabindex=\"-1\">جعل التعارضات أسهل في القراءة</h2>\n<p>افتراضيًا ترى الطرفين فقط. اطلب من Git أن يعرض الأسطر الأصلية أيضًا:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"8\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> config</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --global</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> merge.conflictStyle</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> zdiff3</span></span></code></pre></div>\n<p>الآن لكل تعارض قسم ثالث بين <code dir=\"ltr\">|||||||</code> و <code dir=\"ltr\">=======</code> يعرض الـ merge base. رؤية ما كان عليه السطر <em>قبل</em> أيّ من التغييرين تجعل الجواب الصحيح واضحًا في الغالب: ترى ما قصده كل طرف، لا ما انتهى إليه فقط.</p>\n<p>المحرّرات تساعد أيضًا. يميّز VS Code كل كتلة بأزرار مثل Accept Current Change و Accept Incoming Change و Accept Both Changes، إضافة إلى محرّر دمج ثلاثي. استخدمها، لكن اقرأ النتيجة؛ فـ Accept Both كثيرًا ما ينتج وسمَي <code dir=\"ltr\">&lt;p&gt;</code> حيث أردت واحدًا.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>تعارضات أقل وأصغر</span></p>\n<p>تكبر التعارضات مع الوقت ومع حجم الفرع. أبقِ الفروع قصيرة العمر، وادمجها سريعًا، وأدخِل <code dir=\"ltr\">main</code> إلى الفرع طويل العمر كل يوم أو يومين بدل مرة واحدة في النهاية. وشخصان يعدّلان ملفًا مشتركًا واحدًا طوال الأسبوع حالة تستدعي حديثًا قبل الدمج، لا أثناءه.</p>\n</aside>\n<p>الدمج طريقة واحدة لجمع السجلّات. في الدرس التالي ستتعرّف على الطريقة الأخرى، الـ rebase، والقاعدة الوحيدة التي تُبقيه آمنًا.</p>\n","toc":[{"id":"sec-1","text":"ما يخبرك به Git","level":2},{"id":"sec-2","text":"قراءة العلامات","level":2},{"id":"sec-3","text":"الحلّ خطوة بخطوة","level":2},{"id":"sec-4","text":"الانسحاب","level":2},{"id":"sec-5","text":"جعل التعارضات أسهل في القراءة","level":2}],"takeaways":["التعارض يعني أن الفرعين غيّرا الأسطر نفسها منذ الـ merge base، فيطلب منك Git أن تختار؛ لا شيء ضاع ولا شيء تعطّل.","ما بين <code dir=\"ltr\">&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code> و <code dir=\"ltr\">=======</code> هو فرعك الحالي (HEAD)؛ وما بين <code dir=\"ltr\">=======</code> و <code dir=\"ltr\">&gt;&gt;&gt;&gt;&gt;&gt;&gt;</code> هو الفرع الذي يُدمج.","تحلّ التعارض بتحرير الملف إلى شكله النهائي، وإزالة كل العلامات، ثم <code dir=\"ltr\">git add</code> للملف و <code dir=\"ltr\">git commit</code>.","<code dir=\"ltr\">git merge --abort</code> يعيد كل شيء تمامًا كما كان قبل بدء الدمج.","ضبط <code dir=\"ltr\">merge.conflictStyle</code> على <code dir=\"ltr\">zdiff3</code> يعرض الأسطر الأصلية أيضًا، وهذا يجعل الحكم على معظم التعارضات سهلًا."],"further":[{"title":"Basic Merge Conflicts (Pro Git)","url":"https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merge_conflicts"},{"title":"Resolving a merge conflict using the command line","url":"https://docs.github.com/en/pull-requests/how-tos/merge-and-close-pull-requests/resolving-a-merge-conflict-using-the-command-line"},{"title":"git merge, How conflicts are presented","url":"https://git-scm.com/docs/git-merge#_how_conflicts_are_presented"}],"quiz":[{"q":"<p>أنت على <code dir=\"ltr\">main</code> وشغّلت <code dir=\"ltr\">git merge tagline</code>. وترى في <code dir=\"ltr\">index.html</code>:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Text</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD\n&lt;p&gt;Front-end developer in Lagos.&lt;/p&gt;\n=======\n&lt;p&gt;Front-end developer who loves accessible UI.&lt;/p&gt;\n&gt;&gt;&gt;&gt;&gt;&gt;&gt; tagline</code></pre></div>\n<p>أيّ السطرين جاء من <code dir=\"ltr\">main</code>؟</p>\n","options":[{"text":"الثاني، لأن الفرع الذي يُدمج يظهر أولًا دائمًا.","why":"العكس هو الصحيح. النصف العلوي هو دائمًا الفرع الذي أنت عليه، ويحمل الاسم HEAD."},{"text":"<code dir=\"ltr\">Front-end developer in Lagos.</code>، لأن النصف العلوي هو الـ HEAD، أي فرعك الحالي.","why":"صحيح. أنت على <code dir=\"ltr\">main</code>، إذن الـ HEAD هو <code dir=\"ltr\">main</code>. والنصف السفلي، الذي يحمل الاسم <code dir=\"ltr\">tagline</code>، هو ما يُدمج."},{"text":"لا هذا ولا ذاك؛ السطران اقتراحان من Git لنسخة مدمجة.","why":"لا يخترع Git نصوصًا. كل نصف هو بالضبط ما يحتويه أحد الفرعين."}],"answer":1},{"q":"<p>حرّرت <code dir=\"ltr\">index.html</code> حتى صار كما تريد، وأزلت كل العلامات. لكن <code dir=\"ltr\">git status</code> ما زال يدرجه تحت “Unmerged paths”. ما الخطوة التالية؟</p>","options":[{"text":"شغّل <code dir=\"ltr\">git merge tagline</code> مجددًا كي يلاحظ Git الإصلاح.","why":"هناك دمج قيد التنفيذ أصلًا. بدء دمج آخر يفشل؛ فـ Git ينتظر منك أن تعلّم الملفات بأنها حُلّت."},{"text":"شغّل <code dir=\"ltr\">git commit -a --no-verify</code>.","why":"<code dir=\"ltr\">--no-verify</code> يتخطّى الـ hooks ولا علاقة له بالتعارضات. جهّز الملف وأنشئ الـ commit بشكل عادي."},{"text":"شغّل <code dir=\"ltr\">git add index.html</code> لتعلّمه بأنه حُلّ، ثم <code dir=\"ltr\">git commit</code>.","why":"صحيح. التجهيز يخبر Git بأن التعارض حُسم. وحين لا يبقى أي مسار غير مدموج، ينشئ <code dir=\"ltr\">git commit</code> الـ merge commit."},{"text":"احذف <code dir=\"ltr\">index.html</code> وشغّل <code dir=\"ltr\">git restore index.html</code>.","why":"هذا يرمي الحلّ الذي كتبته للتو. ولا داعي لحذف أي شيء."}],"answer":2},{"q":"<p>في منتصف تعارض فوضوي تدرك أنك دمجت الفرع الخطأ. كيف تعود تمامًا إلى حيث كنت قبل الدمج؟</p>","options":[{"text":"<code dir=\"ltr\">git merge --abort</code>","why":"صحيح. ما دام الدمج قيد التنفيذ، يعيد هذا الأمر الفرع والـ index وملفاتك إلى حالتها قبل <code dir=\"ltr\">git merge</code>."},{"text":"<code dir=\"ltr\">git restore .</code>","why":"هذا يرمي تغييرات الـ working tree لكنه يترك Git في منتصف الدمج، وحالة الدمج ما زالت نشطة."},{"text":"<code dir=\"ltr\">git branch -D main</code>","why":"حذف الفرع الذي أنت عليه غير مسموح، ولن يلغي أي شيء على أي حال."},{"text":"أغلق الطرفية؛ فعمليات الدمج غير المكتملة تُلغى تلقائيًا.","why":"حالة الدمج مخزّنة في <code dir=\"ltr\">.git</code>، لا في جلسة الطرفية. وستجدها حين تعيد فتحها."}],"answer":0},{"q":"<p>دُمج فرعك ورُفع، ثم يجد زميلك <code dir=\"ltr\">=======</code> مطبوعة على الصفحة الرئيسية في الموقع المنشور. أيّ عادة كانت ستكتشف هذا قبل الـ commit؟</p>","options":[{"text":"تشغيل <code dir=\"ltr\">git log --graph</code> بعد كل دمج.","why":"الرسم يعرض بنية الـ commits، لا محتوى الملفات، فلن تظهر العلامات المتبقّية."},{"text":"الحلّ دائمًا بـ <code dir=\"ltr\">git merge --abort</code>.","why":"الإلغاء يلغي الدمج بدل أن يحلّه، فلا يصل العمل أبدًا."},{"text":"استخدام <code dir=\"ltr\">git commit -m</code> بدل المحرّر.","why":"مصدر الرسالة لا علاقة له بالعلامات الموجودة داخل ملفاتك."},{"text":"تشغيل <code dir=\"ltr\">git diff --check</code> (وفتح الصفحة) قبل <code dir=\"ltr\">git add</code>.","why":"صحيح. <code dir=\"ltr\">git diff --check</code> ينبّه إلى علامات التعارض المتبقّية، والنظر الفعلي إلى النتيجة يكشف الباقي."}],"answer":3}],"exercise":{"kind":"order","items":["merge","status","open","edit","check","add","commit"],"title":"حُلّ تعارض سطر التعريف","prompt":"<p>أنت على <code dir=\"ltr\">main</code> وتريد دمج فرع <code dir=\"ltr\">tagline</code>. رتّب الخطوات بالترتيب الذي ستنفّذها به لتنتقل من التعارض إلى merge commit مكتمل.</p>\n","hints":["يجب أن يبلّغ Git عن التعارض قبل أن يكون هناك ما تصلحه، و <code dir=\"ltr\">git status</code> يخبرك أيّ الملفات تحتاجك.","تصلح الملف قبل أن تفحصه، وتفحصه قبل أن تخبر Git بأنه حُلّ.","الـ merge commit هو الخطوة الأخيرة دائمًا."],"explanation":"<p>يتوقّف الدمج عند التعارض؛ ويدرج <code dir=\"ltr\">git status</code> الملفات غير المدموجة. تفتح كل ملف منها، وتحرّره إلى النص النهائي وتحذف كل علامة، ثم تفحص النتيجة (<code dir=\"ltr\">git diff --check</code>، والنظر إلى الصفحة، وتشغيل الاختبارات). بعد ذلك فقط يعلّمه <code dir=\"ltr\">git add</code> بأنه حُلّ، ويسجّل <code dir=\"ltr\">git commit</code> (أو <code dir=\"ltr\">git merge --continue</code>) الـ merge commit. وإن ساء أي شيء قبل تلك الخطوة الأخيرة، يعيدك <code dir=\"ltr\">git merge --abort</code> إلى حيث بدأت.</p>\n","checkLabels":{},"itemText":{"merge":"شغّل <code dir=\"ltr\">git merge tagline</code> لترى <code dir=\"ltr\">CONFLICT (content): Merge conflict in index.html</code>.","status":"شغّل <code dir=\"ltr\">git status</code> لعرض المسارات غير المدموجة.","open":"افتح <code dir=\"ltr\">index.html</code> وجِد كتلة <code dir=\"ltr\">&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code>.","edit":"اكتب سطر التعريف النهائي واحذف أسطر العلامات الثلاثة.","check":"شغّل <code dir=\"ltr\">git diff --check</code> وانظر إلى الصفحة في المتصفّح.","add":"شغّل <code dir=\"ltr\">git add index.html</code> لتعلّم التعارض بأنه حُلّ.","commit":"شغّل <code dir=\"ltr\">git commit</code> لتسجيل الـ merge commit."}},"words":662,"readMinutes":4}