EN
ابدأ هنا المواضيع الفِرَق المرجع المستجدّات المحفوظات
معرفة عمليّة

الـ version control (git)

ما هو git ولماذا يتحدّث Claude دائمًا عن الـ commits؟

الإجابة المختصرة

git أداة تسجّل كل تغيير يجري على مشروع، بحيث يمكن استرجاع أي إصدار سابق كما كان بالضبط. وهو ما يجعل السماح لـ agent بتعديل ملفاتك تصرّفًا معقولًا — فإن تبيّن أن تغييرًا ما خاطئ، تستعيد آخر حالة سليمة في ثوانٍ.

أسرع طريق للفهم هو أن تكفّ عن التفكير في git كأداة للمبرمجين وتبدأ التفكير فيه بوصفه undo لمشروع بأكمله. أنت تعرف الـ undo لمستند واحد، وتعرف حدوده: يغطّي ملفًا واحدًا، ولا يتذكّر إلا الـ session الحالية، ويختفي لحظة إغلاقك التطبيق. git يزيل الحدود الثلاثة. فهو يراقب كل ملف في مجلد دفعةً واحدة، ويحتفظ بالتاريخ بشكل دائم، ويتيح لك القفز إلى أي لحظة سابقة — لا آخر خمس ضغطات مفاتيح، بل الحالة الدقيقة لكل شيء كما كانت بعد ظهر الثلاثاء.

ووحدة ذلك التاريخ هي الـ commit: نقطة حفظ تنشئها عن قصد، مع ملاحظة قصيرة تقول ما الذي تغيّر. وكلمة «عن قصد» هي الجزء الذي يستحق التمهّل عنده. git ليس حفظًا تلقائيًا. أنت من يقرّر أن العمل بلغ حالة تستحق أن تكون قادرًا على العودة إليها، فتضع العلامة. والملاحظة لا تقلّ أهمية عن اللقطة نفسها، لأن التاريخ بعد شهر يُقرأ بوصفه سردًا لـ لماذا صار المشروع على ما هو عليه — لا مجرد كومة من الطوابع الزمنية.

أمّا المجلد نفسه، بمجرد أن يصير git يراقبه، فيُسمّى repository — أو «repo» في كل حديث ستخوضه عنه يومًا. وهنا تكتسب كلمة «مشروع» حدودها: الـ repo مجلد يملك ذاكرة كاملة عن نفسه. الملفات التي حذفتها قبل ثلاثة أسابيع ما زالت قابلة للاسترجاع منه. وهذا مربك أول مرة تعرفه، ومطمئن في كل مرة بعدها.

وإليك لماذا يظهر أيٌّ من هذا في منتج موجّه لغير المبرمجين. حين تسلّم مجلدًا إلى agent، فأنت تسمح لبرنامج بتغيير ملفات كثيرة دفعةً واحدة، وأسرع مما تستطيع قراءة النتائج. وما يجعل ذلك تصرّفًا معقولًا ليس ثقتك بأن الـ agent مصيب. بل أن كلفة الخطأ محدودة. اعمل commit قبل أن تطلب شيئًا طموحًا، وعندها تصير كل نتيجة ممكنة — باهرة أو متوسطة أو كارثية — على بعد ثوانٍ من التراجع. من دون ذلك، «لنرَ ما سيفعل» مقامرة؛ ومعه، تصبح تجربة. العمل الـ agentic من أقوى الحجج التي وُجدت يومًا لصالح الـ version control، وقد جاء بعد git بزمن طويل.

والـ branch يمدّ المنطق نفسه. إنه خط عمل موازٍ: تتفرّع عن الإصدار الرئيسي، وتغيّر ما شئت، ثم إمّا تدمج النتيجة عائدًا أو تتخلّى عنها كليًا. التشبيه المكتبي هو أن تأخذ نسخة من المستند المشترك لتخرّبها بحرّية — إلا أن دمج تعديلاتك عائدًا عملية مدعومة، لا كابوس توفيق بين ملفين. وفي العمل مع الـ agents، الـ branch هو الوعاء الطبيعي لـ «جرّب إعادة التصميم كاملة ودعني أنظر إليها»، لأن التخلّي عن المحاولة لا يكلّف شيئًا.

وفي العمل اليومي، لست بحاجة إلى حفظ الأوامر. اسأل بلغة عادية — اعمل commit لهذا برسالة معقولة، ما الذي تغيّر منذ الصباح، أعِد ذلك الملف إلى ما كان عليه — ويتولّى Claude الميكانيكا. ما يبقى لك هو الحكم، وهو حكم حقيقي: ما الذي يستحق نقطة حفظ، وماذا ينبغي أن تقول الملاحظة لتعني شيئًا لاحقًا، ومتى يستحق جزء من العمل branch خاصًا به، وهل التغيير الذي أنت على وشك الاحتفاظ به هو فعلًا ما أردته. وهذا السؤال الأخير هو مراجعة التغييرات، وهو مهارة منفصلة.

التاريخ يجيب عن أسئلة لا تجيب عنها الملفات

النصف الذي لا يبلغه الناس من git هو أن الـ repository ليس ملفات فحسب — بل كل إصدار من تلك الملفات، ومع كل تغيير ملاحظة. وذلك التاريخ هو عادةً أسرع طريق إلى «لماذا هذا هكذا؟» و*«ما الذي انكسر؟»*، ولست بحاجة إلى git log أو git blame أو git diff للوصول إليه. تسأل في المحادثة فينظر Claude:

  • نموذج التواصل كان يعمل الأسبوع الماضي ولم يعد — ما الذي تغيّر في server/index.js منذ ذلك الحين؟
  • لماذا يقرأ saveMessage الملف كله قبل الكتابة؟ ومتى أُضيف ذلك؟
  • من آخر من غيّر هذا السطر، وماذا كان يحاول إصلاحه؟
  • لم أنظر في هذا المشروع منذ شهر. ما الذي تغيّر منذ آخر مرة كنت فيها هنا؟

والأخير يساوي أكثر ممّا يبدو حين تعود إلى شيء نسيته: فبدل أن تفتح عشرين ملفًا عشوائيًا، تتوجّه في ثلاثين ثانية. (وكلمة blame من مصطلحات git لا حكمًا أخلاقيًا — فالميزة تخبرك من المسؤول عن سطر، لا من المذنب. وهو أنت غالبًا، قبل ستة أشهر.)

والغريزة التي تستحقّ إعادة التوصيل: حين ينكسر شيء فجأةً، «ما الذي تغيّر؟» أفضل من «ما الموجود؟». فالسبب ليس عادةً في الملف كما هو اليوم، بل في الفرق بين اليوم والأمس — فاقرأ الـ diff لا الكود. والتحفّظ الوحيد أن التاريخ لا يجود إلا بقدر ما كتبه الناس من رسائل. وسيعيد Claude بناء الحكاية من الـ diff حين لا يقول الـ commit سوى «إصلاحات»، لكنها إعادة بناء لا سجلّ. وهذه هي الحجّة العملية لكتابة رسائل commit لائقة: أنت تترك الشرح الذي سيبحث عنه نفسك في المستقبل.

وحدّان صادقان. git يتتبّع الملفات على القرص، فهو يحمي مجلد المشروع ولا شيء غيره — لا جدول البيانات في قرصك المشترك، ولا الـ CRM، ولا أي شيء غيّره agent عبر connector. والشبكة لا تمسك إلا ما عملت له commit فعلًا؛ فالعمل المنجز منذ آخر commit ليس فيها. والـ checkpoints والـ undo داخل Claude Code طبقة أمان مفيدة قصيرة العمر داخل الـ session، لكنها ليست بديلًا عن تاريخ commits تستطيع قراءته في الربع القادم.

المصطلحات

Git
الأداة التي تتتبّع تاريخ كودك — كل تغيير، ومن أجراه، والقدرة على العودة. الـ repository هو مشروع تحت رقابة Git. إنه المعيار في version control.
Repository repo
مجلد مشروع يتتبّع تاريخه الخاص — اختصارًا «repo». كل تغيير محفوظ يُسجَّل، فتستطيع أن ترى ما تغيّر، ومتى، وأن تتراجع عن أيٍّ منه. إنه مجلد بذاكرة كاملة.
Commit
لقطة محفوظة من كودك في لحظة واحدة، مع ملاحظة قصيرة عمّا تغيّر. تصطفّ الـ commits في تاريخ يمكنك قراءته وإرجاعه. تخيّله نقطة حفظ في لعبة.
Branch
خطّ عمل موازٍ في git — تتفرّع جانبًا، وتجري التغييرات بأمان، ثم تدمجها (merge) عند الجاهزية، دون المساس بالنسخة الرئيسية. أشبه بتحرير نسخة من مستند ثم دمج تعديلاتك لاحقًا.
GitHub
أوسع المواقع استخدامًا لاستضافة الـ git repositories. يحتفظ بالنسخة المشتركة من المشروع التي يدفع إليها الفريق ويسحب منها، ويضيف حولها طبقة التعاون — الـ pull requests ومراجعة الكود والـ issues والفحوص الآلية.
Remote origin
النسخة المشتركة من الـ repository التي تقيم في مكان غير جهازك — على GitHub عادةً. حاسوبك يحمل نسخة كاملة من المشروع؛ والـ remote هو النسخة التي يزامن الفريق كله معها. واسمه الافتراضي origin.
Push
إرسال الـ commits المحلية لديك إلى الـ remote، كي تصير في النسخة المشتركة. وعكسه pull، وهو جلب commits الآخرين إليك.
Pull request PR · merge request
اقتراح بدمج branch في آخر، يُفتح على GitHub. يعرض الـ diff، ويحمل وصفًا لما تغيّر ولماذا، ويمنح المراجعين مكانًا للتعليق — كل ذلك قبل أن يستقرّ شيء في main.
Merge
دمج الـ commits من branch في آخر — عادةً طيّ branch ميزة مكتملة داخل main. وحين يكون الـ branchان قد غيّرا الأسطر نفسها، لا يستطيع git أن يقرّر نيابةً عنك فيبلّغ عن merge conflict، وعلى أحدهم أن يحلّه يدويًا.
.gitignore
ملف في مشروعك يسرد ما ينبغي ألّا يتتبّعه git أبدًا — ملفات .env، وبيانات الاعتماد، ومخرجات البناء، والمجلدات المولَّدة الضخمة. وكل ما يطابق سطرًا فيه يبقى على جهازك وخارج كل commit.

قراءات أطول

أسئلة يطرحها الناس

ظللت أحفظ بـ Cmd-S طوال فترة الظهيرة. ما الذي يمنحني إياه الـ commit ولا يمنحه الحفظ؟
الحفظ يكتب فوق القديم — فالإصدار السابق يزول. أمّا الـ commit فيجمّد المشروع كله في تلك اللحظة ويحتفظ بكل تجميد سابق، فتستطيع العودة إلى ما كانت عليه الأمور يوم الثلاثاء بدل التراجع عن آخر ضغطات مفاتيح فقط. (ونقل ذلك التاريخ إلى نسخة مشتركة خطوة منفصلة اسمها الـ push.)
في جلسة واحدة أصلحت خللًا، وأعدت صياغة عنوان، وتغيّر ملف `.env` أيضًا. كيف أعمل لهذا commit؟
commitان — فالإصلاح وإعادة الصياغة فكرتان منفصلتان، وفصلهما هو ما يُبقي تراجعك دقيقًا. أمّا .env فلا يُعمل له commit أبدًا: فهو يحمل secret، ومتى دخل الـ secret التاريخ لم يُزِله حذفه في commit لاحق من القديم. أضِفه إلى .gitignore، وإن كان قد دُفع سلفًا فدوِّر بيانات الاعتماد.
عدّل Claude ثلاثة ملفات. اثنان ممتازان وواحد خاطئ، وآخر commit لديّ كان قبل ذلك كله. ما أنظف طريق للعودة؟
استعِد الملف الخاطئ وحده من آخر commit — فيبقى التعديلان الجيّدان كما هما تمامًا. وطلب التراجع من Claude قد ينفع، لكنه إعادة بناء؛ أمّا الاستعادة من commit فدقيقة. وهذه هي الحجّة كلها لعمل commit قبل أن تُطلِق وكيلًا: فهي تجعل «أبقِ اثنين واطرح واحدًا» عمليةً من عشر ثوانٍ.
هل عليّ أن أتعلّم أوامر git للعمل بهذه الطريقة؟
لا. اسأل بلغة عادية — اعمل commit لهذا برسالة معقولة، ما الذي تغيّر منذ هذا الصباح، أعِد ذلك الملف كما كان — وينفّذ Claude الآليّات. وما يبقى لك هو الحكم: ما الذي يستحقّ نقطة حفظ، وماذا ينبغي أن تقول الرسالة كي تعني شيئًا بعد ستة أشهر، وهل التغيير الذي أنت مقبل على إبقائه هو الذي أردته.