{"id":"l-git-1-3","courseId":"git-github","lang":"ar","kind":"lesson","summary":"انقل التغييرات بوعي بين الـ working tree والـ staging area والـ repository، وافحص كل خطوة بـ status و diff، وقسّم العمل الفوضوي إلى commits مركّزة.","html":"<p>قضيت أمسية كاملة على موقعك الشخصي. أضفت شريط تنقّل إلى <code dir=\"ltr\">index.html</code>، وأنشأت <code dir=\"ltr\">styles.css</code>، وصحّحت خطأً إملائيًا في اسمك أثناء ذلك. هذه ثلاثة تغييرات لا علاقة لبعضها ببعض. لو سجّلتها معًا في commit واحد باسم “updates”، فلن تستطيع لاحقًا التراجع عن شريط التنقّل دون التراجع عن تصحيح الخطأ الإملائي أيضًا. يعطيك Git مكانًا ترتّب فيه التغييرات قبل أن تصبح جزءًا من السجلّ.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">ثلاثة أماكن قد يكون فيها عملك</h2>\n<p>كل تغيير في مشروع Git يعيش في واحد من ثلاثة أماكن:</p>\n<ul>\n<li>الـ <strong>working tree</strong> (مجلد العمل) هو الملفات على القرص، تلك التي يفتحها محرّرك. تغيّرها بحرية، و Git يراقب فقط.</li>\n<li>الـ <strong>index</strong>، ويُسمّى أيضًا <strong>staging area</strong> (منطقة التجهيز)، هو الـ commit التالي قيد التجميع. الأمر <code dir=\"ltr\">git add</code> ينسخ المحتوى الحالي للملف إليه.</li>\n<li>الـ <strong>repository</strong> (المستودع) هو الـ commits المسجّلة بالفعل داخل <code dir=\"ltr\">.git</code>. والأمر <code dir=\"ltr\">git commit</code> يحوّل الـ index إلى commit جديد.</li>\n</ul>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 270\" role=\"img\" aria-labelledby=\"l-git-1-3-t1\"><defs><marker id=\"arrow-l-git-1-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-1-3-t1\">ثلاثة صناديق من اليسار إلى اليمين: الـ working tree، والـ index (منطقة التجهيز)، والـ repository. الأمر git add ينقل من الـ working tree إلى الـ index، و git commit من الـ index إلى الـ repository. وفي الأسفل، git restore --staged ينسخ من الـ repository عائدًا إلى الـ index، و git restore ينسخ من الـ index عائدًا إلى الـ working tree.</title>\n  <rect class=\"d-box\" x=\"20\" y=\"70\" width=\"180\" height=\"80\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"110\" y=\"105\" text-anchor=\"middle\">Working tree</text>\n  <text class=\"d-label-muted\" x=\"110\" y=\"128\" text-anchor=\"middle\">الملفات على القرص</text>\n  <rect class=\"d-box-accent\" x=\"260\" y=\"70\" width=\"180\" height=\"80\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"350\" y=\"105\" text-anchor=\"middle\">Index</text>\n  <text class=\"d-label-muted\" x=\"350\" y=\"128\" text-anchor=\"middle\">الـ commit التالي</text>\n  <rect class=\"d-box-primary\" x=\"500\" y=\"70\" width=\"180\" height=\"80\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"590\" y=\"105\" text-anchor=\"middle\">Repository</text>\n  <text class=\"d-label-muted\" x=\"590\" y=\"128\" text-anchor=\"middle\">commits مسجّلة</text>\n  <path class=\"d-arrow\" d=\"M200 90 L256 90\" marker-end=\"url(#arrow-l-git-1-3-1)\"/>\n  <text class=\"d-code\" x=\"228\" y=\"55\" text-anchor=\"middle\">git add</text>\n  <path class=\"d-arrow\" d=\"M440 90 L496 90\" marker-end=\"url(#arrow-l-git-1-3-1)\"/>\n  <text class=\"d-code\" x=\"468\" y=\"55\" text-anchor=\"middle\">git commit</text>\n  <path class=\"d-arrow d-dashed\" d=\"M500 140 C470 210 420 210 400 154\" marker-end=\"url(#arrow-l-git-1-3-1)\"/>\n  <text class=\"d-code\" x=\"470\" y=\"230\" text-anchor=\"middle\">git restore --staged</text>\n  <path class=\"d-arrow d-dashed\" d=\"M260 140 C230 210 180 210 160 154\" marker-end=\"url(#arrow-l-git-1-3-1)\"/>\n  <text class=\"d-code\" x=\"200\" y=\"230\" text-anchor=\"middle\">git restore</text>\n  <text class=\"d-label-muted\" x=\"350\" y=\"262\" text-anchor=\"middle\">المتقطّع: نسخ عكسي. git restore يكتب فوق ملفك.</text>\n</svg><figcaption>الأوامر تنقل المحتوى بين المناطق الثلاث</figcaption></figure>\n<p>بعد الـ commit لا يُفرَّغ الـ index. بل يظل يحمل اللقطة الكاملة التي سجّلتها للتو، فيطابق آخر commit إلى أن تجهّز شيئًا جديدًا. لهذا فإن «التغييرات المجهّزة» تعني الفرق بين الـ index وآخر commit.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">رؤية الفرق: status و diff بنوعيه</h2>\n<p>هذا عمل الأمسية كما يعرضه <code dir=\"ltr\">git status</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>On branch main\nChanges not staged for commit:\n  (use &quot;git add &lt;file&gt;...&quot; to update what will be committed)\n  (use &quot;git restore &lt;file&gt;...&quot; to discard changes in working directory)\n\tmodified:   index.html\n\nUntracked files:\n  (use &quot;git add &lt;file&gt;...&quot; to include in what will be committed)\n\tstyles.css\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 status</code> أيّ الملفات تختلف. ولرؤية الأسطر نفسها استخدم <code dir=\"ltr\">git diff</code>، وتذكّر أن هناك مقارنتين:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"1\"><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:#6E7781;--shiki-dark:#8B949E\">            # working tree vs index: what you haven't staged yet</span></span>\n<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\"> --staged</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">   # index vs last commit: what the next commit will contain</span></span></code></pre></div>\n<p>الخيار <code dir=\"ltr\">--cached</code> مرادف أقدم لـ <code dir=\"ltr\">--staged</code>؛ وستراهما كليهما في الشروحات. اجعل تشغيل <code dir=\"ltr\">git diff --staged</code> عادة قبل كل commit مباشرة. إنها اللحظة الأخيرة لتلاحظ <code dir=\"ltr\">console.log</code> نسيته أو ملفًا لا ينتمي إلى هذا الـ commit.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">تقسيم ملف واحد على اثنين من الـ commits</h2>\n<p>تصحيح الخطأ الإملائي وشريط التنقّل كلاهما في <code dir=\"ltr\">index.html</code>. الأمر <code dir=\"ltr\">git add index.html</code> سيجهّزهما معًا. جهّز تصحيح الخطأ وحده بدلًا من ذلك:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"2\"><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:#0550AE;--shiki-dark:#79C0FF\"> -p</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> index.html</span></span></code></pre></div>\n<p>يعرض Git كل كتلة متغيّرة، وتُسمّى hunk، ويسأل <code dir=\"ltr\">Stage this hunk [y,n,q,a,d,s,e,?]?</code> (تعرض الإصدارات الأحدث حروفًا إضافية، والحرف <code dir=\"ltr\">?</code> يشرحها كلها). أجب بـ <code dir=\"ltr\">y</code> على كتلة الخطأ الإملائي و <code dir=\"ltr\">n</code> على كتلة شريط التنقّل (والحرف <code dir=\"ltr\">s</code> يقسم الكتلة إن كانت كبيرة جدًا). ثم:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"3\"><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\"> --staged</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">          # only the typo fix</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:#0550AE;--shiki-dark:#79C0FF\"> -m</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Fix spelling of name in header\"</span></span>\n<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 style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> styles.css</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:#0550AE;--shiki-dark:#79C0FF\"> -m</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Add navigation bar with base styles\"</span></span></code></pre></div>\n<p>اثنان من الـ commits، لكل منهما غرض واحد. ولاحقًا، إن احتجت إلى إزالة شريط التنقّل، تستطيع التراجع عن ذلك الـ commit وحده.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">ما الحجم المناسب للـ commit؟</h2>\n<p>الـ commit الجيد يفعل شيئًا واحدًا تستطيع وصفه بجملة قصيرة دون كلمة «و». الرسالة “Fix spelling of name in header” تنجح في هذا الاختبار. أما “Add nav, fix typo, tweak colours” فتفشل، ويظهر الفشل لاحقًا: حين يتبيّن أن الألوان خاطئة، فإن التراجع عن ذلك الـ commit يزيل شريط التنقّل أيضًا ويعيد الخطأ الإملائي.</p>\n<p>لا يوجد حدّ لعدد الأسطر. الـ commit الذي يعيد تسمية class في CSS عبر اثني عشر ملفًا يظل فكرة واحدة، وتقسيمه سيترك الموقع معطّلًا بين الخطوتين. اسعَ إلى commits يبقى المشروع بعدها وقبلها يعمل، وكل واحد منها خطوة تستطيع شرحها للمراجِع في نَفَس واحد. ستقدّر هذا في القسم الرابع، حين يصبح التراجع عن commit واحد أمرًا من سطر واحد بدل ساعات من العمل الجراحي الدقيق.</p>\n<aside class=\"callout callout-note\" 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\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4\"/><path d=\"M12 8h.01\"/></svg><span><span class=\"callout-kind\">ملاحظة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>لماذا توجد منطقة تجهيز في Git أصلًا</span></p>\n<p>بعض أنظمة التحكم في الإصدارات تسجّل كل ملف متغيّر دفعة واحدة. يوجد الـ index في Git لكي يختلف ما <em>فعلته</em> (أمسية من التعديلات المختلطة) عمّا <em>تسجّله</em> (خطوات نظيفة لكل منها غرض واحد). لست مضطرًا لاستخدامه ببراعة في كل مرة، لكنه موجود حين يصبح عملك فوضويًا.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">الحالة المختصرة، والتراجع</h2>\n<p>يضغط <code dir=\"ltr\">git status -s</code> المعلومات نفسها في عمودين: الأيسر يقارن الـ index بآخر commit، والأيمن يقارن الـ working tree بالـ index.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"4\"><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>M  README.md\n M index.html\nMM styles.css\n?? projects.html</code></pre></div>\n<p><code dir=\"ltr\">README.md</code> مجهّز؛ و <code dir=\"ltr\">index.html</code> فيه تغييرات غير مجهّزة؛ و <code dir=\"ltr\">styles.css</code> فيه من الاثنين؛ و <code dir=\"ltr\">projects.html</code> غير متتبَّع (untracked).</p>\n<p>لإخراج ملف من الـ index دون أن تخسر تعديلاتك، استخدم <code dir=\"ltr\">git restore --staged styles.css</code>. ولرمي التعديلات غير المجهّزة والعودة إلى نسخة الـ index، استخدم <code dir=\"ltr\">git restore styles.css</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>الثقة بـ git commit -a مع الملفات الجديدة</span></p>\n<p><code dir=\"ltr\">git commit -am &quot;Add projects page&quot;</code> يجهّز كل ملف <em>متتبَّع ومعدّل</em> ثم ينشئ الـ commit. أما <code dir=\"ltr\">projects.html</code> الجديد كليًا فهو untracked، فيُستبعد بصمت وتكذب الرسالة. استخدم <code dir=\"ltr\">-a</code> فقط حين لا يعرض <code dir=\"ltr\">git status</code> ملفات غير متتبَّعة تهمّك، أو شغّل <code dir=\"ltr\">git add</code> للملفات الجديدة أولًا.</p>\n</aside>\n<p>صرت قادرًا على تسجيل السجلّ الذي تقصده بالضبط. في الدرس التالي ستقرأ هذا السجلّ، وترى لماذا يسمّيه Git رسمًا بيانيًا (graph) لا قائمة.</p>\n","toc":[{"id":"sec-1","text":"ثلاثة أماكن قد يكون فيها عملك","level":2},{"id":"sec-2","text":"رؤية الفرق: status و diff بنوعيه","level":2},{"id":"sec-3","text":"تقسيم ملف واحد على اثنين من الـ commits","level":2},{"id":"sec-4","text":"ما الحجم المناسب للـ commit؟","level":2},{"id":"sec-5","text":"الحالة المختصرة، والتراجع","level":2}],"takeaways":["الـ working tree هو ملفاتك، والـ index (منطقة التجهيز) هو الـ commit التالي قيد التجميع، والـ repository هو الـ commits المسجّلة بالفعل.","<code dir=\"ltr\">git diff</code> يقارن الـ working tree بالـ index؛ و <code dir=\"ltr\">git diff --staged</code> يقارن الـ index بآخر commit.","<code dir=\"ltr\">git add -p</code> يجهّز جزءًا من الملف، فتتحوّل جلسة تعديل فوضوية واحدة إلى عدة commits مركّزة.","<code dir=\"ltr\">git restore --staged &lt;file&gt;</code> يلغي التجهيز ويحتفظ بتعديلاتك؛ أما <code dir=\"ltr\">git restore &lt;file&gt;</code> فيرمي تعديلاتك غير المجهّزة.","<code dir=\"ltr\">git commit -a</code> يجهّز الملفات المتتبَّعة المعدّلة فقط؛ والملفات الجديدة كليًا ما زالت تحتاج <code dir=\"ltr\">git add</code>."],"further":[{"title":"Recording Changes to the Repository (Pro Git)","url":"https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository"},{"title":"git restore reference","url":"https://git-scm.com/docs/git-restore"},{"title":"git add reference","url":"https://git-scm.com/docs/git-add"}],"quiz":[{"q":"<p>جهّزت <code dir=\"ltr\">index.html</code>، ثم عدّلته مرة أخرى. يعرض <code dir=\"ltr\">git diff</code> التعديل الثاني فقط. لماذا؟</p>","options":[{"text":"أضاع Git التعديل الأول حين حفظت الملف مرة أخرى.","why":"لم يضِع شيء. التعديل الأول محفوظ بأمان في الـ index، والأمر <code dir=\"ltr\">git diff --staged</code> سيعرضه."},{"text":"<code dir=\"ltr\">git diff</code> لا يعرض إلا آخر حفظ لكل ملف.","why":"لا يتتبّع Git عمليات الحفظ. إنه يقارن حالتين كاملتين، وأيّ حالتين بالضبط يعتمد على الأمر."},{"text":"<code dir=\"ltr\">git diff</code> يقارن الـ working tree بالـ index، والتعديل الأول موجود في الـ index أصلًا.","why":"صحيح. بعد تجهيز التعديل الأول، لا يبقى من فرق بين الملف على القرص والـ index إلا التعديل الثاني."},{"text":"يلزم تنفيذ <code dir=\"ltr\">add</code> ثانية قبل أن يعرض <code dir=\"ltr\">git diff</code> أي شيء.","why":"<code dir=\"ltr\">git diff</code> يعرض التغييرات غير المجهّزة، وهذا بالضبط حال التعديل الثاني. ولو جهّزته لما عرض <code dir=\"ltr\">git diff</code> شيئًا."}],"answer":2},{"q":"<p>شغّلت <code dir=\"ltr\">git add styles.css</code> لكنك تريده في الـ commit القادم لا في هذا. أيّ أمر يحتفظ بتعديلاتك ويلغي تجهيز الملف فقط؟</p>","options":[{"text":"<code dir=\"ltr\">git restore --staged styles.css</code>","why":"صحيح. ينسخ آخر نسخة مسجّلة إلى الـ index، فيُلغى تجهيز الملف وتبقى تعديلاتك في الـ working tree."},{"text":"<code dir=\"ltr\">git restore styles.css</code>","why":"دون <code dir=\"ltr\">--staged</code> يستهدف هذا الأمر الـ working tree ويستبدل ملفك بنسخة الـ index. ستضيع تعديلاتك."},{"text":"<code dir=\"ltr\">git rm styles.css</code>","why":"هذا يجهّز حذف الملف ويزيله من القرص. وهو عكس ما تريده تمامًا."},{"text":"<code dir=\"ltr\">git commit --skip styles.css</code>","why":"لا يوجد خيار <code dir=\"ltr\">--skip</code> في <code dir=\"ltr\">git commit</code>. إلغاء التجهيز يحدث في الـ index قبل الـ commit."}],"answer":0},{"q":"<p>أنشأت <code dir=\"ltr\">projects.html</code> وعدّلت <code dir=\"ltr\">index.html</code>، ثم شغّلت <code dir=\"ltr\">git commit -am &quot;Add projects page&quot;</code>. ماذا احتوى الـ commit؟</p>","options":[{"text":"الملفين كليهما، لأن <code dir=\"ltr\">-a</code> تعني كل الملفات في المجلد.","why":"<code dir=\"ltr\">-a</code> تعني كل الملفات المتتبَّعة المعدّلة. والملف الذي لم يتتبّعه Git قط لا يُضمَّن."},{"text":"لا شيء، لأن <code dir=\"ltr\">-a</code> لا يمكن جمعها مع <code dir=\"ltr\">-m</code>.","why":"<code dir=\"ltr\">-am</code> تركيبة شائعة وصحيحة: جهّز تغييرات الملفات المتتبَّعة، ثم أنشئ الـ commit بهذه الرسالة."},{"text":"<code dir=\"ltr\">projects.html</code> فقط، لأنه الملف الأحدث.","why":"عمر الملف لا يهمّ Git. ما يهمّ هو هل الملف متتبَّع أم لا."},{"text":"تغييرات <code dir=\"ltr\">index.html</code> فقط؛ و <code dir=\"ltr\">projects.html</code> ما زال untracked.","why":"صحيح. <code dir=\"ltr\">-a</code> يتخطّى الملفات غير المتتبَّعة، ولهذا تصف رسالة الـ commit الآن صفحة ليست موجودة فيه."}],"answer":3},{"q":"<p>في ناتج <code dir=\"ltr\">git status -s</code>، ماذا يخبرك السطر <code dir=\"ltr\">MM index.html</code>؟</p>","options":[{"text":"عُدّل الملف مرتين منذ آخر commit.","why":"لا يعدّ Git التعديلات. العمودان يصفان مقارنتين مختلفتين."},{"text":"بعض تغييرات الملف مجهّزة وبعضها الآخر غير مجهّز.","why":"صحيح. العمود الأيسر يقارن الـ index بآخر commit، والعمود الأيمن يقارن الـ working tree بالـ index؛ وكلاهما يقول «معدّل»."},{"text":"في الملف تعارض دمج.","why":"تظهر التعارضات في الحالة المختصرة بالرمز <code dir=\"ltr\">UU</code> (unmerged)، لا <code dir=\"ltr\">MM</code>."}],"answer":1}],"exercise":{"kind":"fill","language":"bash","template":"git status\ngit add {{0}} index.html     # stage only the typo-fix hunk\ngit diff {{1}}               # check what the next commit contains\ngit commit -m \"Fix spelling of name in header\"\n\ngit add index.html styles.css\ngit restore {{2}} styles.css   # oops: unstage it, keep the edits\ngit commit -m \"Add navigation bar\"","blanks":[{"answers":["-p","--patch"]},{"answers":["--staged","--cached"]},{"answers":["--staged","-S"]}],"title":"جهّز عن قصد","prompt":"<p>أكمل الجلسة. تجهّز جزءًا فقط من <code dir=\"ltr\">index.html</code> (تصحيح الخطأ الإملائي)، وتتحقّق بالضبط مما سيدخل في الـ commit، وتسجّله، ثم تجهّز عمل شريط التنقّل لكنك تُخرج <code dir=\"ltr\">styles.css</code> من الـ index دون أن تخسر تعديلاتك.</p>\n","hints":["التجهيز الجزئي يعمل كتلةً كتلة (hunk by hunk). والخيار اختصار لكلمة patch.","<code dir=\"ltr\">git diff</code> وحده يعرض التغييرات غير المجهّزة. الخيار الذي تحتاجه يقارن الـ index بآخر commit.","الأمر <code dir=\"ltr\">git restore</code> نفسه يستطيع إما رمي التعديلات أو إلغاء التجهيز. واحد فقط من الاثنين آمن هنا."],"explanation":"<p><code dir=\"ltr\">git add -p</code> يمرّ على كل hunk فتستطيع تجهيز تصحيح الخطأ الإملائي وحده. و <code dir=\"ltr\">git diff --staged</code> (أو <code dir=\"ltr\">--cached</code>) يعرض الـ index مقارنةً بآخر commit، وهذا هو الـ commit التالي بالضبط. و <code dir=\"ltr\">git restore --staged styles.css</code> ينسخ النسخة المسجّلة إلى الـ index، فيُلغى تجهيز الملف وتبقى تعديلاتك في الـ working tree. ودون <code dir=\"ltr\">--staged</code> كان <code dir=\"ltr\">git restore</code> سيكتب فوق ملفك.</p>\n","checkLabels":{}},"words":686,"readMinutes":4}