{"id":"l-git-1-1","courseId":"git-github","lang":"ar","kind":"intro","summary":"اشرح المشكلة التي يحلّها التحكم في الإصدارات، وكيف يختلف نموذج اللقطات في Git عن حفظ نسخ من الملفات، وكيف يتقاسم Git و GitHub العمل.","html":"<p>لدى كل مطوّر مجلد ما فيه <code dir=\"ltr\">index.html</code> و <code dir=\"ltr\">index-old.html</code> و <code dir=\"ltr\">index-final.html</code> و <code dir=\"ltr\">index-final-REAL.html</code>. ينجح هذا الأسلوب حتى اليوم الذي تحتاج فيه إلى معرفة أي نسخة كانت فيها القائمة تعمل، أو ما الذي غيّرته بين الثلاثاء والخميس، أو كيف تجمع إصلاحك مع تعديلات صديقك من الصباح نفسه. النسخ المتفرّقة من الملفات لا تجيب عن أيّ من ذلك.</p>\n<p>التحكم في الإصدارات (version control) هو الأداة التي تجيب عن هذه الأسئلة. فهو يحفظ سجلّ مشروعك كسلسلة من الحالات المحفوظة، لكل منها تاريخ ومؤلف وملاحظة تشرح السبب. تستطيع مقارنة أي حالتين، والعودة إلى حالة قديمة، وتجربة فكرة جانبية ثم رميها، ومشاركة السجلّ كاملًا مع الآخرين. و Git هو نظام التحكم في الإصدارات الذي تستخدمه الغالبية الساحقة من الفرق في 2026، و GitHub هو المكان الذي تحتفظ فيه معظم هذه الفرق بنسختها المشتركة.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">لقطات، لا تعديلات</h2>\n<p>فكرة Git الأساسية صغيرة. حين تنشئ commit (لقطة محفوظة)، يسجّل Git <strong>لقطة</strong> (snapshot): المحتوى الكامل لكل ملف يتتبّعه في تلك اللحظة. الملفات التي لم تتغيّر لا تُخزَّن مرتين، بل يعيد Git استخدام ما لديه أصلًا. ويخزّن كل commit أيضًا مؤشّرًا إلى الـ commit الذي سبقه، أي <strong>الأب</strong> (parent). اتبع هذه المؤشّرات إلى الخلف وستحصل على سجلّ المشروع.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 250\" role=\"img\" aria-labelledby=\"l-git-1-1-t1\"><defs><marker id=\"arrow-l-git-1-1-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-1-t1\">يسارًا: ثلاث نسخ متفرّقة من index.html لا رابط بينها. يمينًا: ثلاثة commits، كل منها لقطة للمشروع كله، ويشير كل منها إلى أبيه، ولكل commit رسالة.</title>\n  <text class=\"d-label-strong\" x=\"30\" y=\"30\">نسخ</text>\n  <rect class=\"d-box-warn\" x=\"30\" y=\"50\" width=\"200\" height=\"40\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"45\" y=\"76\">index.html</text>\n  <rect class=\"d-box-warn\" x=\"30\" y=\"105\" width=\"200\" height=\"40\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"45\" y=\"131\">index-final.html</text>\n  <rect class=\"d-box-warn\" x=\"30\" y=\"160\" width=\"200\" height=\"40\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"45\" y=\"186\">index-final-REAL.html</text>\n  <text class=\"d-label-muted\" x=\"30\" y=\"230\">أيها الأحدث؟ ما الذي تغيّر؟</text>\n  <text class=\"d-label-strong\" x=\"290\" y=\"30\">Commits</text>\n  <rect class=\"d-box-primary\" x=\"290\" y=\"60\" width=\"120\" height=\"110\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"305\" y=\"85\">a1f3</text>\n  <text class=\"d-code\" x=\"305\" y=\"110\">index.html</text>\n  <text class=\"d-code\" x=\"305\" y=\"130\">styles.css</text>\n  <text class=\"d-label-muted\" x=\"305\" y=\"155\">\"Add home\"</text>\n  <rect class=\"d-box-primary\" x=\"440\" y=\"60\" width=\"120\" height=\"110\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"455\" y=\"85\">7c2e</text>\n  <text class=\"d-code\" x=\"455\" y=\"110\">index.html</text>\n  <text class=\"d-code\" x=\"455\" y=\"130\">styles.css</text>\n  <text class=\"d-label-muted\" x=\"455\" y=\"155\">\"Add menu\"</text>\n  <rect class=\"d-box-primary\" x=\"590\" y=\"60\" width=\"100\" height=\"110\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"605\" y=\"85\">d90b</text>\n  <text class=\"d-code\" x=\"605\" y=\"110\">index.html</text>\n  <text class=\"d-code\" x=\"605\" y=\"130\">styles.css</text>\n  <text class=\"d-label-muted\" x=\"605\" y=\"155\">\"Fix nav\"</text>\n  <path class=\"d-arrow\" d=\"M440 115 L414 115\" marker-end=\"url(#arrow-l-git-1-1-1)\"/>\n  <path class=\"d-arrow\" d=\"M590 115 L564 115\" marker-end=\"url(#arrow-l-git-1-1-1)\"/>\n  <text class=\"d-label-muted\" x=\"290\" y=\"205\">كل commit يشير إلى أبيه.</text>\n</svg><figcaption>نسخ من الملفات مقابل سلسلة من الـ commits</figcaption></figure>\n<p>لاحظ أن الأسهم تشير إلى الخلف. الـ commit يعرف أباه، ولا يعرف أبناءه أبدًا، لأن الأبناء لم يكونوا موجودين حين أُنشئ. هذه التفصيلة الواحدة تفسّر الكثير من سلوك Git لاحقًا، ومنه سبب عجزك عن «تعديل» commit قديم، وكل ما تستطيعه هو استبداله بآخر جديد.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">Git مقابل GitHub</h2>\n<p>يستخدم الناس الاسمين كأنهما شيء واحد، وهما ليسا كذلك.</p>\n<ul>\n<li><strong>Git</strong> برنامج على حاسوبك. يعيش السجلّ كله في مجلد مخفي اسمه <code dir=\"ltr\">.git</code> داخل مشروعك. إنشاء الـ commits والفروع والدمج وقراءة السجلّ كلها تحدث محليًا، وتعمل حتى وأنت في الطائرة.</li>\n<li><strong>GitHub</strong> موقع وخدمة تستضيف مستودعات Git (repositories). يضيف حول Git ما يحتاجه الفريق: نسخة مشتركة يرفع إليها الجميع، و pull requests (طلبات الدمج) لمراجعة الكود، و issues، ولوحات المشاريع، و GitHub Actions للفحوص الآلية.</li>\n</ul>\n<p>تستطيع استخدام Git دون GitHub (فرق كثيرة تستخدم GitLab أو Bitbucket)، لكن GitHub دون Git لا معنى له. يعلّمك هذا الكورس Git أولًا، ثم GitHub فوقه.</p>\n<aside class=\"callout callout-why\" 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\"/><circle cx=\"12\" cy=\"12\" r=\"6\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/></svg><span><span class=\"callout-kind\">لماذا يهمّ هذا</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>لماذا يبدو Git صعبًا، وكيف يعالج هذا الكورس ذلك</span></p>\n<p>يتعلّم معظم الناس Git كقائمة أوامر يحفظونها، فتبدو كل رسالة غير متوقَّعة كارثة. أوامر Git في الحقيقة حركات على رسم بياني صغير من الـ commits والأسماء الدالّة عليها. وحين تستطيع تخيّل هذا الرسم، يتوقّف الأمر عن كونه مقامرة ويصبح توقّعًا تستطيع التحقّق منه بـ <code dir=\"ltr\">git log --graph</code>. توقّع الكثير من الرسوم التوضيحية.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">ما الذي ستبنيه</h2>\n<p>ستعمل على مشروع واحد طوال الكورس: موقعك الشخصي، وهو repository (مستودع) اسمه <code dir=\"ltr\">portfolio</code> فيه <code dir=\"ltr\">index.html</code> و <code dir=\"ltr\">styles.css</code> وصفحة للمشاريع وسكربت صغير <code dir=\"ltr\">npm test</code> يفحص الـ HTML. في القسم الأول تحوّل المجلد إلى repository وتتعلّم قراءة سجلّه. في القسم الثاني تنشئ الفروع وتدمج وتنفّذ rebase وتصلح تعارضًا حقيقيًا. في القسم الثالث تضعه على GitHub وتعمل عبر الـ pull requests. وفي القسم الرابع تتعلّم التراجع عن الأخطاء بأمان، وتنتهي بفرع <code dir=\"ltr\">main</code> محميّ تفحص فيه GitHub Actions كل pull request قبل أن يُسمح بدمجه.</p>\n<p>في الدرس التالي تثبّت Git، وتعرّفه بنفسك، وتنشئ أول commit لك.</p>\n","toc":[{"id":"sec-1","text":"لقطات، لا تعديلات","level":2},{"id":"sec-2","text":"Git مقابل GitHub","level":2},{"id":"sec-3","text":"ما الذي ستبنيه","level":2}],"takeaways":["يسجّل التحكم في الإصدارات لقطات مسمّاة ومؤرّخة للمشروع كله، فتستطيع مقارنة التغييرات والتراجع عنها ومشاركتها بأمان.","الـ commit في Git لقطة لكل الملفات المتتبَّعة مع مؤشّر إلى الـ commit الذي سبقه، وليس قائمة بالتعديلات.","يعمل Git على جهازك ويعمل دون اتصال؛ أما GitHub فخدمة استضافة مبنية حول مستودعات Git.","يختفي معظم الارتباك في Git حين تستطيع رسم الرسم البياني للـ commits وتحديد أين يشير فرعك وأين يشير الـ HEAD."],"further":[{"title":"Pro Git, Getting Started - What is Git?","url":"https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F"},{"title":"About Git (GitHub Docs)","url":"https://docs.github.com/en/get-started/using-git/about-git"}],"quiz":[{"q":"<p>تحفظ <code dir=\"ltr\">index.html</code> و <code dir=\"ltr\">index-v2.html</code> و <code dir=\"ltr\">index-final.html</code> في مجلد واحد. ما المشكلة التي يحلّها Git ولا تحلّها هذه العادة؟</p>","options":[{"text":"يجعل Git الملفات أصغر، فيشغل المجلد مساحة أقل على القرص.","why":"صحيح أن Git يضغط ما يخزّنه، لكن توفير المساحة ليس المشكلة هنا. المشكلة هي معرفة ما الذي تغيّر، ومتى، ولماذا، وفي أي ملفات."},{"text":"يسجّل Git المشروع كله عند كل نقطة، مع رسالة وتاريخ، فتستطيع مقارنة أي نسخة أو العودة إليها.","why":"صحيح. الـ commit يلتقط كل الملفات المتتبَّعة معًا، مع من غيّرها ومتى ولماذا، وهذا ما لا تستطيعه نسخ متفرّقة من ملف واحد."},{"text":"يمنعك Git من تعديل الملفات التي لها نسخة محفوظة.","why":"لا يقفل Git الملفات أبدًا. تعدّل بحرية، ولا يسجّل Git إلا ما تختار أن تضعه في commit."},{"text":"يرفع Git كل نسخة إلى السحابة تلقائيًا.","why":"يعمل Git محليًا بالكامل إلى أن تنفّذ push. الرفع خطوة منفصلة ومقصودة تتطلّب remote مثل GitHub."}],"answer":1},{"q":"<p>ماذا يحتوي الـ commit الواحد في Git؟</p>","options":[{"text":"الأسطر التي تغيّرت منذ الـ commit السابق فقط.","why":"هذا وصف للـ diff. يعرض لك Git الفروقات، لكنه يحسبها بمقارنة لقطتين؛ أما الـ commit نفسه فيسجّل الحالة الكاملة."},{"text":"نسخة من الملفات التي جهّزتها، ولا شيء عن الـ commits السابقة.","why":"الـ commit يشير دائمًا إلى الـ commit الأب (أو الآباء). هذا الرابط هو ما يحوّل اللقطات المنفصلة إلى سجلّ."},{"text":"لقطة لكل الملفات المتتبَّعة، والمؤلف، ورسالة، ومؤشّر إلى الـ commit الأب.","why":"صحيح. اللقطة مع مؤشّر الأب هي النموذج كله؛ والسجلّ والفروع والدمج كلها تنتج عنه."}],"answer":2},{"q":"<p>لا يوجد Wi-Fi في القطار. أيّ هذه الأمور ما زال بإمكانك فعله؟</p>","options":[{"text":"إنشاء commits، وعرض السجلّ، وإنشاء الفروع ودمجها.","why":"صحيح. المستودع الكامل يعيش في مجلد <code dir=\"ltr\">.git</code> على جهازك، لذا يعمل كل شيء دون اتصال ما عدا التواصل مع الـ remote."},{"text":"لا شيء؛ يحتاج Git إلى الوصول إلى GitHub مع كل أمر.","why":"صُمّم Git ليكون موزَّعًا. وحدها الأوامر التي تتواصل مع remote، مثل push و fetch و pull و clone، تحتاج اتصالًا بالشبكة."},{"text":"الأمر <code dir=\"ltr\">git status</code> فقط، لأن الـ commits تُنشأ على خوادم GitHub.","why":"تُنشأ الـ commits محليًا بالأمر <code dir=\"ltr\">git commit</code>. ولا يستقبلها GitHub إلا لاحقًا حين تنفّذ push."}],"answer":0}],"exercise":null,"words":500,"readMinutes":3}