git commit
تسجيل التغييرات في المستودع
ينشئ الأمر 'git commit' commit جديدًا يحتوي المحتوى الحالي للفهرس (منطقة التجهيز) ورسالة تصف التغييرات. الـ commit الجديد ابن مباشر لـ HEAD ويصبح الرأس الجديد للفرع الحالي. كل commit لقطة دائمة في تاريخ المشروع يمكن الرجوع إليها أو مقارنتها أو استعادتها في أي وقت.
الصيغة
git commit [-a] [-m <msg>] [--amend] [--no-edit] [-v] [-n] [--dry-run] [-s] [-S] [--] [<pathspec>...]الخيارات
اختيار الخيار المناسب
خيارات الرسالة
طرق مختلفة لتقديم رسالة الـ commit أو تعديلها
| الأمر | المصدر | يفتح المحرر | حالة الاستخدام |
|---|---|---|---|
git commit -m "msg" | في السطر | ✗ | commits سريعة برسائل قصيرة |
git commit -F file | ملف | ✗ | رسالة مكتوبة مسبقًا في ملف |
git commit -t file | قالب | ✓ | البدء بقالب في المحرر |
git commit -e | المحرر | ✓ | إجبار المحرر حتى مع -m |
git commit -C <commit> | نسخ | ✗ | إعادة استخدام رسالة commit آخر |
git commit -c <commit> | نسخ + تعديل | ✓ | تعديل رسالة commit آخر |
تنظيف الرسالة
كيف تُعالَج رسالة الـ commit قبل حفظها
| الأمر | الوضع | يزيل التعليقات | يزيل المسافات | الأنسب لـ |
|---|---|---|---|---|
--cleanup=strip | strip | ✓ | ✓ | معظم الـ commits |
--cleanup=whitespace | المسافات | ✗ | ✓ | إبقاء تعليقات # |
--cleanup=verbatim | حرفيًا | ✗ | ✗ | الحفاظ على الرسالة كما هي تمامًا |
--cleanup=scissors | المقص | تحت سطر المقص فقط | ✓ | إبقاء أسطر # عند استخدام المحرر |
المؤلف والتاريخ
تغيير من نفّذ الـ commit ومتى
| الأمر | يتجاوز | التنسيق | الاستخدام المعتاد |
|---|---|---|---|
--author="Name <email>" | المؤلف | الاسم <email> | تنفيذ commit نيابةً عن شخص آخر |
--date="date" | تاريخ التأليف | ISO 8601 / نسبي | تأريخ commits بتاريخ سابق |
--reset-author | كلاهما | المستخدم/الوقت الحاليان | تبنّي patch مطبّق |
الـ amend وإصلاح التاريخ
خيارات لتعديل commits موجودة
| الأمر | ينشئ | يعدّل HEAD | يُستخدم مع |
|---|---|---|---|
git commit --amend | استبدال | ✓ | إصلاح رسالة آخر commit أو محتواه |
git commit --fixup=<sha> | commit من نوع fixup! | ✗ | git rebase -i --autosquash |
git commit --squash=<sha> | commit من نوع squash! | ✗ | git rebase -i --autosquash |
ما الذي يدخل الـ commit
التحكم في الملفات المضمَّنة في الـ commit
| الأمر | يجهّز أولًا | الـ commits | مجلد العمل |
|---|---|---|---|
git commit | ✗ | المجهَّز فقط | دون تغيير |
git commit -a | الملفات المتتبَّعة | كل المتتبَّعة | دون تغيير |
git commit -i <file> | المحددة | المجهَّز + الملف | دون تغيير |
git commit -o <file> | المحددة فقط | الملف فقط | تُستبعد المجهّزات الأخرى |
git commit -p | تفاعلي | أجزاء مختارة | دون تغيير |
توقيع GPG
توقيع الـ commits تشفيريًا للتحقق منها
| الأمر | الإجراء | المفتاح المستخدم | متى تستخدمه |
|---|---|---|---|
git commit -S | التوقيع | مفتاح GPG الافتراضي | إثبات أصالة الـ commit |
git commit -S<keyid> | التوقيع | مفتاح محدد | استخدام مفتاح توقيع بديل |
git commit --no-gpg-sign | دون توقيع | لا شيء | تجاوز commit.gpgSign=true |
التحكم في الـ hooks
تجاوز hooks الـ pre-commit والـ post-commit أو التحكم فيها
| الأمر | يتخطّى | مستوى الخطر | متى تستخدمه |
|---|---|---|---|
git commit --no-verify | pre-commit + commit-msg | متوسط | إصلاح طارئ، وإصلاح الـ hooks لاحقًا |
git commit --no-post-rewrite | post-rewrite | منخفض | تخطّي المعالجة البطيئة بعد الـ amend |
Dry-run وتنسيق المخرجات
معاينة ما سيُحفظ دون تنفيذ الـ commit فعلًا
| الأمر | التنسيق | قابل للتحليل | يعرض |
|---|---|---|---|
--dry-run | طويل (افتراضي) | ✗ | حالة كاملة مع تلميحات |
--dry-run --short | مختصر | ✓ | رموز حالة مختصرة |
--dry-run --porcelain | Porcelain | ✓ | تنسيق ثابت للسكربتات |
--dry-run --branch | مع الفرع | ✓ | يضيف معلومات التتبّع إلى التنسيق المختصر |
--dry-run -z | مفصولة بـ NUL | ✓ | آمن لأسماء الملفات الخاصة |
عرض الحالة في المحرر
التحكم فيما يظهر في المحرر عند كتابة رسالة الـ commit
| الأمر | في المحرر | الأثر |
|---|---|---|
git commit --status | الحالة كتعليقات | رؤية الملفات التي ستُحفظ (افتراضي) |
git commit --no-status | دون قائمة ملفات | محرر أنظف، تشتيت أقل |
git commit -v | الـ diff الكامل | مراجعة التغييرات بدقة أثناء الكتابة |
git commit -q | محرر عادي | إخفاء الملخّص بعد الـ commit |
commits خاصة
إنشاء commits في حالات غير معتادة
| الأمر | يسمح | ينشئ commit | حالة الاستخدام |
|---|---|---|---|
--allow-empty | لا تغييرات | ✓ | مشغّلات CI، علامات الفروع |
--allow-empty-message | دون رسالة | ✓ | سكربتات آلية (غير مستحسن) |
--trailer "Key: value" | البيانات الوصفية | ✓ | Co-authored-by، Fixes، Reviewed-by |
أمثلة على سير العمل
git add .جهّز تغييراتك
git commit -m "Fix typo in README"نفّذ commit برسالة قصيرة
git add -Aجهّز كل التغييرات
git commitيفتح المحرر لرسالة متعددة الأسطر
(Write: subject line, blank line, detailed body)اتبع قاعدة 50/72 في التنسيق
git add forgotten-file.jsجهّز الملف المنسي
git commit --amend --no-editأضفه إلى آخر commit دون تغيير الرسالة
git commit --amend -m "Corrected message"استبدل آخر commit برسالة جديدة
git commit -a -m "Update config files"جهّز تلقائيًا الملفات المتتبَّعة المعدّلة/المحذوفة ونفّذ commit
git add .جهّز التغييرات
git commit -S -m "Verified security patch"أنشئ commit موقّعًا بـ GPG
مفاتيح المحرر والوضع التفاعلي
اختصارات لوحة المفاتيح عندما يفتح Git محررًا لرسالة الـ commit، أو عند استخدام الأوضاع التفاعلية.
Vim (الافتراضي في أنظمة كثيرة)
core.editor = vimNano
core.editor = nanoVS Code
core.editor = "code --wait"وضع patch (-p)
git commit -pحل المشكلات
no changes added to commit (use "git add" and/or "git commit -a")
السبب: تغيّرت ملفات لكن لا شيء مجهَّز - نسيت تشغيل 'git add'. (إن رأيت 'nothing to commit, working tree clean' فلا توجد تغييرات إطلاقًا.)
جهّز التغييرات بـ 'git add' قبل الـ commit. استخدم 'git status' لترى ما يحتاج إلى تجهيز.
git add . && git commit -m "message"Please tell me who you are (Author identity unknown)
السبب: يتطلب Git ضبط user.name وuser.email قبل أول commit لك.
اضبط هويتك على مستوى النظام أو لهذا المستودع.
git config --global user.name "Your Name" && git config --global user.email "you@example.com"Aborting commit due to empty commit message
السبب: أغلقت المحرر دون كتابة رسالة، أو لم تحتوِ الرسالة إلا تعليقات.
اكتب رسالة commit في المحرر، أو استخدم الخيار '-m' لرسالة في السطر.
git commit -m "Your message here"فشل hook الـ pre-commit
السبب: وجد hook الـ pre-commit (فحص الشيفرة، الاختبارات، التنسيق) مشكلات ومنع الـ commit.
أصلح المشكلات التي أبلغ عنها الـ hook. ولا تتجاوزه بـ '--no-verify' إلا عند الضرورة القصوى.
git commit --no-verify -m "message"فشل hook الـ commit-msg
السبب: رسالة الـ commit لا تطابق التنسيق الذي تفرضه أعراف المشروع.
اتبع عُرف رسائل الـ commit في مشروعك (مثل تنسيق Conventional Commits).
git commit -m "feat: add new feature"Changes not staged for commit
السبب: عدّلت ملفات لكنك لم تضفها إلى منطقة التجهيز.
استخدم 'git add' لتجهيز ملفات محددة، أو 'git commit -a' لتجهيز الملفات المتتبَّعة تلقائيًا.
git add <file> && git commit -m "message"error: failed to push some refs (بعد amend)
السبب: نفّذت amend على commit مدفوع أصلًا، فنشأ تاريخ متباعد.
إما أن تدفع بالإجبار (إن كنت وحدك على الفرع) أو تنفّذ revert وتنشئ commit جديدًا.
git push --force-with-leaseYour branch is ahead of 'origin/main' by X commits
السبب: لديك commits محلية لم تُدفع بعد.
هذا طبيعي! ادفع حين تكون جاهزًا، أو تابع العمل محليًا.
git push origin mainنصائح وأخطاء شائعة
أفضل الممارسات
- ✓اكتب رسائل commit واضحة: ابدأ بفعل (Add، Fix، Update، Remove) وأبقِ العنوان أقل من 50 محرفًا.
- ✓استخدم صيغة الأمر: اكتب 'Add feature' لا 'Added feature' - تخيّل أنك تكمل عبارة «This commit will...»
- ✓اجعل الـ commits ذرّية: يجب أن يمثّل كل commit تغييرًا منطقيًا واحدًا. لا تخلط إصلاح الأخطاء بالميزات الجديدة.
- ✓راجع قبل الـ commit: استخدم 'git diff --staged' لترى بالضبط ما ستحفظه.
- ✓لا تنفّذ amend أبدًا على commits مدفوعة: الـ amend يعيد كتابة التاريخ. عدّل فقط الـ commits التي لم تُشارك.
- ✓افصل العنوان عن المتن بسطر فارغ: في الرسائل الطويلة، السطر الأول هو العنوان، ثم سطر فارغ، ثم التفاصيل.
- ✓لفّ نص المتن عند 72 محرفًا: يضمن هذا سهولة القراءة في الطرفيات وفي مخرجات git log.
- ✓أشر إلى أرقام التذاكر: ضمّن 'Fixes #123' أو 'Closes #456' لربط الـ commits بمتتبّع التذاكر.
- ✓نفّذ commit كثيرًا وpush أقل: الـ commits الصغيرة المتكررة أسهل في المراجعة والتراجع من الكبيرة.
- ✓لا تحفظ الملفات المولَّدة: أبقِ مخرجات البناء والاعتماديات (node_modules) والملفات المُترجَمة خارج الـ commits.
أخطاء متكررة
- ✗تشغيل 'git commit' دون تجهيز التغييرات أولًا: يجب استخدام 'git add' أولًا، إلا مع 'git commit -a' الذي يجهّز الملفات المتتبَّعة فقط.
- ✗كتابة رسائل مبهمة مثل 'fix' أو 'update': استخدم رسائل واضحة ووصفية تشرح سبب التغيير.
- ✗حفظ تغييرات كثيرة لا علاقة بينها دفعة واحدة: اجعل الـ commits ذرّية - تغيير منطقي واحد لكل commit لتسهيل المراجعة والتراجع.
- ✗استخدام --amend على commits مدفوعة أصلًا إلى فروع مشتركة: الـ amend يعيد كتابة التاريخ ويسبب مشكلات للآخرين.
- ✗نسيان ضبط user.name وuser.email: يتطلب Git هوية المؤلف قبل أول commit لك.
الأسئلة الشائعة
'git commit' يحفظ فقط ما في منطقة التجهيز. أما 'git commit -a' فيجهّز تلقائيًا كل الملفات المتتبَّعة المعدّلة والمحذوفة قبل الحفظ - لكن ليس الملفات الجديدة غير المتتبَّعة. ما زلت تحتاج إلى 'git add' للملفات الجديدة.
للـ commits غير المدفوعة: 'git reset --soft HEAD~1' يُبقي التغييرات مجهّزة، و'git reset HEAD~1' (مثل --mixed) يلغي تجهيزها، و'git reset --hard HEAD~1' يتخلّص منها. للـ commits المدفوعة: استخدم 'git revert HEAD' لإنشاء commit جديد يلغي التغييرات.
لآخر commit: 'git commit --amend -m "New message"'. للـ commits الأقدم: استخدم 'git rebase -i' وغيّر 'pick' إلى 'reword'. لا تفعل ذلك أبدًا مع commits مدفوعة إلى فروع مشتركة.
يفتح Git محررك المضبوط لكتابة رسالة. إن أغلقته دون حفظ رسالة، يُلغى الـ commit. استخدم '-m' لرسالة في السطر أو '--allow-empty-message' للحفظ دون رسالة (غير مستحسن).
جهّز الملفات الإضافية بـ 'git add <file>'، ثم شغّل 'git commit --amend --no-edit'. يضيفها هذا إلى الـ commit السابق دون تغيير رسالته.
'--amend' يستبدل آخر commit بالكامل (hash جديد!). استخدمه لتصحيح أخطاء الرسائل أو إضافة ملفات منسية. لا تستخدمه أبدًا على commits مدفوعة إلى فروع مشتركة - فهو يعيد كتابة التاريخ.
استخدم عدة خيارات -m: 'git commit -m "Subject" -m "Body paragraph"'. كل -m ينشئ فقرة جديدة. أو شغّل 'git commit' فقط لفتح محررك.
أبقِ سطر العنوان أقل من 50 محرفًا (الحد الأقصى 72). ولفّ المتن عند 72 محرفًا. يضمن هذا سهولة القراءة في الطرفية وgit log وواجهات GitHub/GitLab.
استخدم 'git commit --no-verify' أو '-n'. يتجاوز هذا hooks الـ pre-commit والـ commit-msg. استخدمه باعتدال - الـ hooks موجودة للحفاظ على جودة الشيفرة.
نعم، استخدم 'git commit --allow-empty -m "message"'. مفيد لتشغيل خطوط CI/CD أو تعليم محطات في التاريخ دون تغيير الشيفرة.