git reset

اللقطات الأساسية

إعادة ضبط HEAD الحالي إلى الحالة المحددة


يُستخدم الأمر 'git reset' للتراجع عن التغييرات بنقل HEAD الفرع الحالي إلى commit محدد. له ثلاثة أوضاع رئيسية: ‎--soft (يُبقي التغييرات مجهّزة)، و‎--mixed (الافتراضي - يُبقي التغييرات في مجلد العمل)، و‎--hard (يتخلّص من كل التغييرات). هذا الأمر أساسي للتراجع عن الـ commits وإلغاء تجهيز الملفات وإدارة التاريخ. احذر من 'git reset --hard' لأنه يتخلّص من التغييرات نهائيًا.

الصيغة

git reset [-q] [<tree-ish>] [--] <pathspec>...
git reset [-q] [--pathspec-from-file=<file>] [<tree-ish>]
git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>...]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
[ ] اختياري| أو<arg> قيمة تُستبدل... قابل للتكرار--flag خيار

الخيارات

انقر على أي خيار لتوسيعه

مبتدئ (3)

يعيد ضبط HEAD على الـ commit المحدد لكنه يُبقي كل التغييرات مجهّزة. لا يتغيّر مجلد العمل ولا منطقة التجهيز. استخدمه للتراجع عن commits مع إبقاء التغييرات جاهزة لحفظها من جديد.

عند الحاجةالتراجع عن commits مع إبقاء التغييرات مجهّزة — مثلًا لإعادة التسجيل أو الضم

مثال

git reset --soft HEAD~1

الوضع الافتراضي. يعيد ضبط HEAD ومنطقة التجهيز، لكنه يُبقي التغييرات في مجلد العمل. استخدمه لإلغاء تجهيز التغييرات مع إبقائها متاحة للتعديل.

موصى بهأكثر الطرق أمانًا للتراجع عن commit محلي أو إلغاء التجهيز؛ يحتفظ بتعديلاتك

مثال

git reset HEAD~1

يعيد ضبط HEAD ومنطقة التجهيز ومجلد العمل على الـ commit المعطى. تُحذف التغييرات غير المحفوظة في الملفات المتتبَّعة، ويُكتب فوق الملفات غير المتتبَّعة التي تعترض ملفات الـ commit (ولا تُمس الملفات غير المتتبَّعة الأخرى). لا تراجع ممكن للتغييرات غير المحفوظة.

غير موصى بهيدمّر التغييرات غير المسجّلة في الملفات المتتبَّعة — خبّئها أو سجّلها أولًا

مثال

git reset --hard HEAD~1

متوسط (1)

اختر تفاعليًا الأجزاء التي تلغي تجهيزها. يتيح لك إزالة تغييرات محددة من منطقة التجهيز مع إبقاء غيرها مجهّزًا.

عند الحاجةإلغاء تجهيز أجزاء مختارة تفاعليًا

مثال

git reset -p

متقدم (2)

يعيد ضبط الفهرس ويحدّث الملفات التي تختلف بين الـ commit وHEAD، لكنه يُبقي التغييرات غير المجهّزة. وتُحذف التغييرات المجهّزة. يتوقف إن كان في ملف يجب تغييره تعديلات غير مجهّزة.

عند الحاجةيلغي الدمج؛ يتخلّص من التغييرات المجهّزة لكنه يُبقي غير المجهّزة

مثال

git reset --merge HEAD~1

يعيد ضبط الفهرس ويحدّث الملفات التي تختلف بين الـ commit وHEAD. يتوقف إن كان في أي ملف مختلف تغييرات محلية. ويحافظ على التغييرات غير المحفوظة في الملفات التي لا تتغيّر بين الـ commitين.

عند الحاجةأكثر أمانًا من ‎--hard للعودة: يرفض الكتابة فوق التعديلات المحلية

مثال

git reset --keep HEAD~1

اختيار الخيار المناسب

أوضاع reset: ما الذي يبقى؟

فهم الأوضاع الثلاثة الرئيسية لـ reset وما يحدث لتغييراتك

الأمريتحرك HEADمنطقة التجهيزمجلد العملاستخدمه حين
--softنعميبقى (مجهَّزًا)محفوظالتراجع عن commit لإعادته مع تغييرات
--mixed (default)نعميُفرَّغ (غير مجهَّز)محفوظالتراجع عن commit للتعديل قبل التجهيز
--hardنعممُفرَّغتضيع تعديلات الملفات المتتبَّعة (وتبقى غير المتتبَّعة)التخلّص تمامًا من الـ commit وكل التغييرات

Reset مقابل Revert مقابل Checkout

اختيار أمر التراجع المناسب لحالتك

الأمريعدّل التاريخ؟آمن للـ commits المدفوعة؟الأنسب لـ
git resetنعم (ينقل الفرع)لا - يسبب مشكلاتالتراجع عن commits محلية لم تُدفع بعد
git revertلا (يضيف commit جديدًا)نعم - آمن للفروع المشتركةالتراجع عن commits مدفوعة على فروع مشتركة
git checkout -- fileNoنعمالتخلّص من التغييرات غير المحفوظة في ملفات محددة

إلغاء التجهيز: reset مقابل restore

يقدّم Git الحديث git restore بديلًا لـ reset لإلغاء التجهيز

الأمرالغرضيؤثر في الـ commits؟موصى به
git reset HEAD fileإلغاء تجهيز ملفNoالطريقة التقليدية
git restore --staged fileإلغاء تجهيز ملفNoالطريقة الحديثة (Git 2.23+)
git resetإلغاء تجهيز كل الملفاتNoيعمل جيدًا
git restore --staged .إلغاء تجهيز كل الملفاتNoنية أوضح

أوضاع reset متقدمة

متى تستخدم ‎--merge و‎--keep بدل ‎--hard

الأمريحافظ على التغييرات المحلية؟يتوقف عند التعارض؟حالة الاستخدام
--hardلا - يدمّر كل شيءNoإعادة ضبط كاملة، والتغييرات لا تهم
--mergeالتغييرات غير المجهّزة فقط (وتضيع المجهّزة)نعمإلغاء دمج مع إبقاء العمل غير المرتبط به
--keepنعم (في الملفات التي لا يمسها reset)نعمالتراجع عن commit مع إبقاء تعديلات محلية غير مرتبطة

أمثلة

التراجع عن آخر commit مع إبقاء التغييرات مجهّزة

git reset --soft HEAD~1

يُرجع HEAD بـ commit واحد. تبقى تغييرات ذلك الـ commit مجهّزة، جاهزة لحفظها من جديد.


التراجع عن آخر commit مع إبقاء التغييرات في مجلد العمل

git reset HEAD~1

الوضع الافتراضي (‎--mixed). يُرجع HEAD بـ commit واحد. تبقى التغييرات لكنها غير مجهّزة.


التخلّص تمامًا من آخر commit والتغييرات

git reset --hard HEAD~1

يُرجع HEAD بـ commit واحد ويتخلّص من كل التغييرات غير المحفوظة في الملفات المتتبَّعة. استخدمه بحذر - العمل غير المحفوظ الضائع لا يُستعاد (أما الـ commit نفسه فيبقى في git reflog).


إلغاء تجهيز ملف محدد

git reset HEAD file.js

يزيل file.js من منطقة التجهيز دون التخلّص من التغييرات. يبقى الملف معدّلًا في مجلد العمل.

أمثلة على سير العمل

1
git log --oneline -3

اعرض الـ commits الأخيرة للتأكد من الـ commit المراد التراجع عنه

2
git reset --soft HEAD~1

تراجع عن الـ commit وأبقِ التغييرات مجهّزة

3
git status

تحقّق أن التغييرات مجهّزة

4
git commit -m "Better message"

احفظ من جديد برسالة جديدة

1
git status

اعرض ما هو مجهَّز حاليًا

2
git reset HEAD unwanted-file.js

ألغِ تجهيز ملف أو أكثر

3
git status

تأكد أن الملف لم يعد مجهّزًا

4
git commit

احفظ الملفات التي تريدها فقط

1
git status

راجع ما سيضيع

2
git stash

(اختياري) خبّئ التغييرات احتياطًا

3
git reset --hard HEAD~1

تخلّص من آخر commit ومن كل التغييرات المتتبَّعة (تبقى الملفات غير المتتبَّعة)

4
git status

تأكد أن مجلد العمل نظيف

1
git reflog

اعثر على hash الـ commit الذي كان قبل reset

2
git reset --hard abc1234

أعد الضبط إلى ذلك الـ hash

3
git log --oneline

تحقّق من استعادة الـ commits

حل المشكلات

fatal: ambiguous argument 'HEAD~1': unknown revision

السبب: أنت على الـ commit الأول - لا يوجد commit سابق تعود إليه

راجع git log. إن لم يكن هناك إلا commit واحد، فلا يمكنك الرجوع أكثر. استخدم git update-ref -d HEAD للبدء من جديد تمامًا.

error: Entry 'app.js' not uptodate. Cannot merge.

السبب: ملف يحتاج ‎--merge أو ‎--keep إلى تغييره فيه تعديلات محلية غير محفوظة، فيُلغى الـ reset

احفظ تغييراتك في commit أو خبّئها أولًا، أو استخدم ‎--hard إن أردت التخلّص منها

استخدمت ‎--hard بالخطأ وفقدت تغييرات

السبب: يتخلّص reset الصارم من كل العمل غير المحفوظ نهائيًا

إن كانت التغييرات محفوظة في commit سابقًا: git reflog لإيجاد الـ commit، ثم git reset --hard <hash>. وإن لم تُحفظ قط: فالأرجح أنها ضاعت إلى الأبد.

نجح reset لكن زميلًا يقول إن التاريخ تعطّل

السبب: أعدت ضبط commits كانت مدفوعة أصلًا إلى فرع مشترك

للفروع المشتركة استخدم git revert. وللإصلاح: git reflog، واعثر على الـ commit الأصلي، ونفّذ reset إليه، ثم ادفع بالإجبار (بالتنسيق مع الفريق).

fatal: ambiguous argument 'HEAD' عند تشغيل git reset HEAD file

السبب: لا commits في المستودع بعد، فـ HEAD غير موجود (أو المسار خاطئ)

احذف HEAD: ‏git reset file.js (أو git rm --cached file.js). تحقّق من المسار الدقيق بـ git status.

نصائح وأخطاء شائعة

أفضل الممارسات

  • ✓لا تستخدم git reset أبدًا على commits دُفعت إلى فروع مشتركة - استخدم git revert بدلًا منه
  • ✓شغّل دائمًا git status قبل reset لتفهم ما الذي سيتأثر
  • ✓فضّل ‎--soft حين تريد إعادة commit مع تعديلات
  • ✓استخدم git stash قبل reset --hard إن كنت قد تريد استعادة تغييراتك
  • ✓تذكّر أن git reflog يستطيع إصلاح معظم أخطاء reset (للتغييرات المحفوظة في commits)
  • ✓استخدم git reset HEAD <file> لإلغاء تجهيز الملفات بدل إعادة ضبط commits كاملة
  • ✓فكّر في git restore --staged كبديل حديث لإلغاء تجهيز الملفات

أخطاء متكررة

  • ✗استخدام 'git reset --hard' دون إدراك أنه يحذف التغييرات غير المحفوظة نهائيًا. تحقّق دائمًا مرتين قبل استخدام ‎--hard.
  • ✗إعادة ضبط commits دُفعت أصلًا إلى مستودع بعيد مشترك. يعيد هذا كتابة التاريخ ويسبب مشكلات للمتعاونين. استخدم 'git revert' بدلًا منه.
  • ✗الخلط بين 'git reset' و'git revert'. ينقل reset مؤشر الفرع إلى الخلف؛ وينشئ revert ‏commit جديدًا يلغي التغييرات.
  • ✗عدم معرفة أنه يمكنك التعافي من reset سيئ باستخدام 'git reflog' لإيجاد hash الـ commit السابق.
  • ✗استخدام 'git reset --hard HEAD' للتخلّص من تغييرات العمل بينما 'git checkout -- .' أو 'git restore .' أنسب.

الأسئلة الشائعة

A:

الناعم يُبقي التغييرات مجهّزة. والمختلط (الافتراضي) يُبقيها في مجلد العمل لكن غير مجهّزة. والصارم يتخلّص من كل شيء. فكّر فيها هكذا: soft = التراجع عن الـ commit فقط، mixed = التراجع عن الـ commit + إلغاء التجهيز، hard = التراجع عن كل شيء.

A:

للتغييرات المحفوظة في commits: نعم، استخدم git reflog لإيجاد hash الـ commit الأصلي ثم نفّذ reset إليه. أما التغييرات غير المحفوظة التي ضاعت بـ ‎--hard: فغالبًا لا، فقد ذهبت نهائيًا.

A:

HEAD~1 يعني «commit واحد قبل HEAD». وHEAD~2 يعني commitين إلى الخلف، وهكذا. ويمكنك أيضًا استخدام hashes الـ commits مباشرة مثل git reset abc1234.

A:

reset للـ commits المحلية التي لم تُدفع بعد - يعيد كتابة التاريخ بنظافة. وrevert للـ commits المدفوعة على الفروع المشتركة - ينشئ commit جديدًا يلغي التغييرات دون إعادة كتابة التاريخ.

A:

استخدم git reset HEAD filename لإلغاء تجهيز ملف محدد. لا يتحرك HEAD ولا يتأثر أي commit، بل يُزال الملف من منطقة التجهيز فقط.

A:

يحذف التغييرات غير المحفوظة نهائيًا. بخلاف التغييرات المحفوظة في commits (القابلة للاستعادة عبر الـ reflog)، لا يمكن استعادة عمل لم يُحفظ قط بعد reset صارم.