{"id":"l-git-4-3","courseId":"git-github","lang":"ar","kind":"lesson","summary":"اكتب رسائل commit تشرح السبب، واتبع صيغة Conventional Commits حين يستخدمها الفريق، وعلّم الإصدارات بـ tags مشروحة (annotated)، وانشر GitHub Release بملاحظات مولَّدة.","html":"<p>بعد ستة أشهر من الآن ستشغّل <code dir=\"ltr\">git log</code> على موقعك الشخصي باحثًا عن اللحظة التي تعطّل فيها الثيم الداكن، وستقرأ رسائل كتبتها أنت في الماضي. “updates” و “fix” و “asdf” لن تساعدك. فائدة السجلّ بقدر فائدة الكلمات المرفقة به. يدور هذا الدرس حول جعل هذه الكلمات ذات قيمة، ثم حول تسمية اللحظات المهمّة: الإصدارات.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">كيف تبدو رسالة الـ commit الجيدة</h2>\n<p>لرسالة الـ commit <strong>سطر عنوان</strong> (subject line)، ثم سطر فارغ، ثم <strong>نص</strong> (body) اختياري:</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>Fix footer overlapping content on mobile\n\nThe footer used position: fixed, so on screens shorter than\nthe content it covered the last project card. Switch to a\nnormal flow footer and add bottom padding to the grid.\n\nCloses #13</code></pre></div>\n<p>الأعراف، وسبب وجودها:</p>\n<ul>\n<li><strong>عنوان في حدود 50 حرفًا.</strong> إنه ما يعرضه <code dir=\"ltr\">git log --oneline</code> وقوائم الـ commits في GitHub وعناوين الـ pull requests؛ والعناوين الطويلة تُقتطع.</li>\n<li><strong>صيغة الأمر:</strong> “Fix” و “Add” و “Remove”، لا “Fixed” ولا “Adds”. واختبار مفيد: العنوان يُكمل الجملة “If applied, this commit will…”. وهو أيضًا يطابق الرسائل التي يكتبها Git بنفسه، مثل “Merge branch ‘footer’”.</li>\n<li><strong>لا نقطة</strong> في نهاية العنوان.</li>\n<li><strong>النص يشرح السبب</strong>، ويُلفّ عند نحو 72 حرفًا. الـ diff يبيّن أصلًا <em>ما</em> الذي تغيّر؛ وأنت وحدك تعرف السبب، والبديل الذي رفضته، والخطأ الذي يصلحه.</li>\n<li><strong>التذييلات (trailers) في الأسفل</strong>: <code dir=\"ltr\">Closes #13</code>، أو <code dir=\"ltr\">Co-authored-by: Name &lt;email&gt;</code> الذي يستخدمه GitHub لنسب العمل إلى شركاء البرمجة الثنائية.</li>\n</ul>\n<p>استخدم <code dir=\"ltr\">git commit</code> دون <code dir=\"ltr\">-m</code> حين يحتاج التغيير إلى نص؛ فمحرّرك يسهّل كتابة الرسائل متعدّدة الأسطر. أما للتغييرات ذات السطر الواحد، فـ <code dir=\"ltr\">-m</code> كافٍ.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الـ Conventional Commits</h2>\n<p>كثير من الفرق تعتمد صيغة منظّمة تُسمّى <strong>Conventional Commits</strong>:</p>\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>feat(projects): add tag filter to projects page\nfix(nav): close mobile menu when a link is clicked\ndocs: add setup steps to README\nci: run HTML check on pull requests\nfeat!: rename data-theme attribute to data-color-scheme</code></pre></div>\n<p>الشكل هو <code dir=\"ltr\">type(optional scope): description</code>. تعرّف المواصفة <code dir=\"ltr\">feat</code> (feature جديدة) و <code dir=\"ltr\">fix</code> (إصلاح خطأ)؛ وتضيف الفرق عادةً <code dir=\"ltr\">docs</code> و <code dir=\"ltr\">style</code> (تنسيق فقط، لا CSS) و <code dir=\"ltr\">refactor</code> و <code dir=\"ltr\">perf</code> و <code dir=\"ltr\">test</code> و <code dir=\"ltr\">build</code> و <code dir=\"ltr\">ci</code> و <code dir=\"ltr\">chore</code>. وعلامة <code dir=\"ltr\">!</code> قبل النقطتين، أو تذييل <code dir=\"ltr\">BREAKING CHANGE:</code>، تعلّم تغييرًا يكسر التوافق مع المستخدمين الحاليين.</p>\n<p>والمكسب هو الأتمتة. لأن النوع قابل للقراءة آليًا، تستطيع الأدوات توليد سجلّات التغيير (changelogs) واختيار <strong>الإصدار الدلالي</strong> (semantic version) التالي لك: <code dir=\"ltr\">fix</code> يرفع رقم الـ patch (من 1.4.2 إلى 1.4.3)، و <code dir=\"ltr\">feat</code> يرفع الـ minor (1.5.0)، والتغيير الكاسر يرفع الـ major (2.0.0).</p>\n<p>عادةً ما تُبقي الـ Conventional Commits الوصف بأحرف صغيرة، وهذا يختلف عن الأسلوب ذي الحرف الأول الكبير أعلاه. وليس أيٌّ منهما خاطئًا. استخدم ما يستخدمه الـ repository أصلًا؛ فالاتساق يتفوّق على التفضيل الشخصي. وفي موقعك الشخصي، جرّب الـ Conventional Commits؛ فهي شائعة بما يكفي في الفرق لتؤتي هذه العادة ثمارها.</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>الرسالة التي تحتاج إلى «و» ثلاث مرات (“add contact form and fix nav and change colours”) تخبرك أن الـ commit كان يجب أن يُقسَّم. قبل الـ commit، شغّل <code dir=\"ltr\">git diff --staged</code> واسأل هل تغطّيه جملة واحدة. إن لم تغطّه، فألغِ التجهيز وسجّل على أجزاء بـ <code dir=\"ltr\">git add -p</code>.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">الـ Tags: تسمية لحظة</h2>\n<p>الفروع تتحرّك؛ أما الـ <strong>tags</strong> (الوسوم) فلا. الـ tag اسم دائم لـ commit واحد، يُستخدم لتعليم الإصدارات: الموقع الشخصي كما كان عند الإطلاق، وعند v1.1، وهكذا.</p>\n<p>في Git نوعان. الـ tag <strong>الخفيف</strong> (lightweight) مجرد اسم يشير إلى commit. والـ tag <strong>المشروح</strong> (annotated) كائن كامل فيه اسم الواسم وتاريخ ورسالة. استخدم الـ tags المشروحة للإصدارات:</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\"> tag</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -a</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> v1.0.0</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -m</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Portfolio launch\"</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> tag</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">                       # list tags</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> show</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> v1.0.0</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">               # tag message, then the commit it points at</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> tag</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -a</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> v0.9.0</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> b2e04f3</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -m</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Preview for mentors\"</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">   # tag an older commit</span></span></code></pre></div>\n<p>تبقى الـ tags على جهازك حتى ترفعها، وهذا يفاجئ معظم الناس في المرة الأولى:</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\"> push</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> origin</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> v1.0.0</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">        # one tag</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">git</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> push</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --follow-tags</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">        # commits plus any annotated tags that point at them</span></span></code></pre></div>\n<p>تعامل مع الـ tag المرفوع على أنه دائم. إن وسمت الـ commit الخطأ ورفعته بالفعل، فانشر إصدارًا جديدًا (v1.0.1) بدل تحريك v1.0.0 من تحت أقدام من ربما استخدموه.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">الـ GitHub Releases</h2>\n<p>الـ <strong>release</strong> (الإصدار) على GitHub هو tag مع عنوان وملاحظات وملفات اختيارية للتنزيل. افتح صفحة Releases في الـ repository، واختر Draft a new release، وحدّد الـ tag (أو أنشئ واحدًا)، ثم انقر <strong>Generate release notes</strong>: يسرد GitHub الـ pull requests المدموجة منذ الإصدار السابق، مع كاتبيها. حرّر الملاحظات حتى تصبح شيئًا يرغب إنسان في قراءته، ثم انشر.</p>\n<p>والـ CLI يفعل الشيء نفسه في سطر واحد:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"4\"><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\">gh</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> release</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> create</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> v1.0.0</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --title</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Portfolio v1.0.0\"</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --generate-notes</span></span></code></pre></div>\n<p>عناوين الـ pull requests الجيدة تصبح ملاحظات إصدار جيدة مجانًا، وهذا سبب إضافي لكون العادات السابقة تؤتي ثمارها.</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\">git diff v1.0.0 v2.0.0 -- styles.css</code>) والعودة إليها، وهذا يستحق العشر ثوانٍ.</p>\n</aside>\n<p>الرسائل النظيفة والـ tags والإصدارات تجعل السجلّ مقروءًا. والخطوة الأخيرة جعل <code dir=\"ltr\">main</code> جديرًا بالثقة دون أن تضطر إلى مراقبته بنفسك: فحوص آلية على كل pull request، وقواعد تفرضها.</p>\n","toc":[{"id":"sec-1","text":"كيف تبدو رسالة الـ commit الجيدة","level":2},{"id":"sec-2","text":"الـ Conventional Commits","level":2},{"id":"sec-3","text":"الـ Tags: تسمية لحظة","level":2},{"id":"sec-4","text":"الـ GitHub Releases","level":2}],"takeaways":["سطر العنوان الجيد قصير وبصيغة الأمر ومحدّد (“Fix footer overlap on mobile”)؛ والنص، بعد سطر فارغ، يشرح السبب.","الـ Conventional Commits تسبق العنوان بنوع مثل <code dir=\"ltr\">feat</code> أو <code dir=\"ltr\">fix</code> أو <code dir=\"ltr\">docs</code>، وهذا يسمح للأدوات باستنتاج أرقام الإصدارات وسجلّات التغيير.","الـ tags المشروحة (<code dir=\"ltr\">git tag -a v1.0.0 -m &quot;…&quot;</code>) تسجّل من وسم ماذا ومتى؛ وهي النوع المناسب للإصدارات.","<code dir=\"ltr\">git push</code> لا يرسل الـ tags؛ ارفعها بـ <code dir=\"ltr\">git push origin v1.0.0</code> أو <code dir=\"ltr\">git push --follow-tags</code>.","الـ GitHub Release هو tag مع ملاحظات وملفات اختيارية، ويستطيع GitHub توليد الملاحظات من الـ pull requests المدموجة."],"further":[{"title":"Git Basics, Tagging (Pro Git)","url":"https://git-scm.com/book/en/v2/Git-Basics-Tagging"},{"title":"Commit Guidelines (Pro Git)","url":"https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines"},{"title":"About releases","url":"https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases"},{"title":"Automatically generated release notes","url":"https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes"}],"quiz":[{"q":"<p>أيّ سطر عنوان يتبع أعراف Git الشائعة على أفضل وجه؟</p>","options":[{"text":"<code dir=\"ltr\">Fixed some bugs.</code>","why":"فعل ماضٍ، ونقطة في النهاية، و “some bugs” لا تخبر القارئ في المستقبل بشيء عمّا تغيّر."},{"text":"<code dir=\"ltr\">Changes to the footer, nav, colours and the contact form so it works on phones now</code>","why":"أطول بكثير مما يناسب العنوان، ويسرد أربعة تغييرات، ما يوحي بأربعة commits."},{"text":"<code dir=\"ltr\">WIP</code>","why":"مقبول كـ commit محلي مؤقت ستضغطه لاحقًا، لكنه بلا معنى حين يدخل السجلّ المشترك."},{"text":"<code dir=\"ltr\">Fix footer overlapping content on mobile</code>","why":"صحيح. بصيغة الأمر، ومحدّد، وأقل من 50 حرفًا. ويُكمل الجملة “If applied, this commit will…”."}],"answer":3},{"q":"<p>وفق الـ Conventional Commits والترقيم الدلالي (semantic versioning)، أيّ تغيير يجب أن ينقل الإصدار 1.4.2 إلى 2.0.0؟</p>","options":[{"text":"<code dir=\"ltr\">fix: correct contrast on dark mode links</code>","why":"الإصلاح يقابله إصدار patch، أي 1.4.3."},{"text":"<code dir=\"ltr\">feat: add tag filter to projects page</code>","why":"الـ feature الجديدة يقابلها إصدار minor، أي 1.5.0."},{"text":"<code dir=\"ltr\">feat!: rename the data-theme attribute to data-color-scheme</code>","why":"صحيح. علامة <code dir=\"ltr\">!</code> (أو تذييل <code dir=\"ltr\">BREAKING CHANGE:</code>) تعلّم تغييرًا كاسرًا للتوافق، ويقابله إصدار major."},{"text":"<code dir=\"ltr\">docs: explain how to run the HTML check</code>","why":"تغييرات الوثائق لا تؤثّر في السلوك المنشور، ولا تستدعي عادةً أي إصدار."}],"answer":2},{"q":"<p>شغّلت <code dir=\"ltr\">git tag -a v1.0.0 -m &quot;Portfolio launch&quot;</code> ثم <code dir=\"ltr\">git push</code>. والـ tag غير موجود على GitHub. لماذا؟</p>","options":[{"text":"<code dir=\"ltr\">git push</code> لا يرفع الـ tags افتراضيًا؛ شغّل <code dir=\"ltr\">git push origin v1.0.0</code> (أو <code dir=\"ltr\">git push --follow-tags</code>).","why":"صحيح. الـ tags تُرفع صراحةً، كي لا تنشر tags تجريبية بالخطأ."},{"text":"الـ tags المشروحة لا يمكن رفعها؛ وحدها الـ tags الخفيفة (lightweight) يمكن رفعها.","why":"النوعان كلاهما يمكن رفعهما. والـ tags المشروحة هي النوع الموصى به للإصدارات."},{"text":"لا يقبل GitHub إلا الـ tags المنشأة عبر صفحة Releases.","why":"يقبل GitHub أي tag مرفوع، ويمكن إنشاء release منه بعد ذلك."},{"text":"يجب أن يبدأ اسم الـ tag بـ <code dir=\"ltr\">release-</code>.","why":"أسماء الـ tags حرّة. و <code dir=\"ltr\">v1.0.0</code> هو العُرف الشائع."}],"answer":0},{"q":"<p>ما الميزة الأساسية للـ tag المشروح على الـ tag الخفيف في الإصدار؟</p>","options":[{"text":"الـ tags المشروحة يمكن أن تشير إلى أي commit؛ والخفيفة إلى الـ HEAD فقط.","why":"النوعان كلاهما يمكن أن يشيرا إلى أي commit. اكتب معرّف الـ commit بعد اسم الـ tag."},{"text":"الـ tag المشروح كائن كامل فيه الواسم والتاريخ والرسالة، فيسجّل الإصدار من علّمه ولماذا.","why":"صحيح. الـ tag الخفيف مجرد اسم لـ commit، كفرع لا يتحرّك أبدًا."},{"text":"الـ tags المشروحة تتقدّم مع الـ commits الجديدة، كالفروع.","why":"لا يتحرّك أيّ من نوعي الـ tags. وهذا هو جوهر الـ tag."}],"answer":1}],"exercise":{"kind":"spot-bug","language":"text","code":"feat(projects): add tag filter to projects page\nfix: stop footer overlapping content on mobile\nUpdated stuff\ndocs: add setup steps to README\nfeat(contact): Added contact form, fixed nav and changed colors\nchore: update html-validate dev dependency\nfix(nav): close mobile menu when a link is clicked\nstyle projects grid spacing","bugLines":[3,5,8],"title":"راجِع رسائل الـ commits","prompt":"<p>هذه عناوين الـ commits في pull request إلى موقعك الشخصي، وهو repository يتبع الـ Conventional Commits (<code dir=\"ltr\">type(optional scope): description</code>، بصيغة الأمر، وتغيير واحد لكل commit). حدّد الأسطر الثلاثة التي يجب أن يطلب المراجِع إعادة كتابتها.</p>\n","hints":["كل عنوان يحتاج إلى نوع تتبعه نقطتان.","تحقّق من صيغة الأفعال، وعُدّ كم تغييرًا يصفه السطر الواحد.","في الـ Conventional Commits، يعني <code dir=\"ltr\">style</code> تنسيق الكود لا العمل على CSS، وهو يحتاج أيضًا إلى النقطتين."],"explanation":"<p>السطر 3، <code dir=\"ltr\">Updated stuff</code>، بلا نوع ولا يقول شيئًا؛ أما شيء مثل <code dir=\"ltr\">refactor: rename nav classes to BEM</code> فيقول. والسطر 5 يستخدم الفعل الماضي ويجمع ثلاثة تغييرات (نموذج التواصل، وقائمة التنقّل، والألوان) في commit واحد؛ قسّمه إلى <code dir=\"ltr\">feat(contact): add contact form</code> و <code dir=\"ltr\">fix(nav): …</code> و commit منفصل للألوان مثل <code dir=\"ltr\">feat(theme): …</code> (لا <code dir=\"ltr\">style:</code>، فهو للتنسيق فقط). والسطر 8 ينقصه النقطتان، فلا تستطيع الأدوات تحليله، و <code dir=\"ltr\">style</code> في الـ Conventional Commits يعني تغييرات التنسيق فقط؛ والتباعد في الشبكة تغيير مرئي، لذا يناسبه أكثر <code dir=\"ltr\">fix(projects): tighten grid spacing on mobile</code>. أما بقية الأسطر فسليمة الصياغة: نوع، ونطاق اختياري، ونقطتان، ووصف محدّد بصيغة الأمر.</p>\n","checkLabels":{}},"words":679,"readMinutes":4}