٢، ٤، التراجع عن الأفعال

قد تحتاج في أي مرحلة إلى التراجع عن فعلٍ ما. سنرى الآن بعض الأدوات الأساسية للتراجع عن تعديلاتك. كن حذرًا، لأن بعض هذه التراجعات لا يمكن التراجع عنها فيما بعد. هذه من المناطق القليلة في جت التي يمكنك أن تفقد فيها شيئًا من عملك إذا فعلت شيئًا خطأ.

واحد من أشهر التراجعات هو عندما تودع قبل الأوان وتنسى إضافة ملفات أو تخطئ في رسالة إيداعك. إذا أردت إعادة هذا الإيداع، فقم بالتعديلات التي نسيتها، وأهّلها، ثم أودع مجددًا مع خيار التصحيح --amend:

$ git commit --amend

يأخذ هذا الأمر منطقة تأهيلك ويستعملها للإيداع. وإذا لم تعدّل ملفًا منذ إيداعك الأخير (مثلًا نفذت هذا الأمر مباشرةً بعد إيداعك السابق)، فإن لقطتك ستتطابق تمامًا بلا اختلاف، ولن تغيّر سوى رسالة الإيداع.

سيظهر لك محرر رسالة الإيداع، لكن ستجد فيه رسالة الإيداع السابقة في انتظارك لتعدّلها إن شئت أو تغيّرها تمامًا.

مثلا، إذا أودعت ثم أدركت أنك نسيت تأهيل تعديلات على ملف تريدها في هذا الإيداع، يمكنك فعل شيء مثل هذا:

$ git commit -m 'Initial commit'
$ git add forgotten_file
$ git commit --amend

ستجد في النهاية إيداعًا واحدًا؛ فالإيداع الثاني يحل محل الأول.

مهمٌ فهم أنك عندما تصحح إيداعك الأخير، فإنك لا تصلحه ولكن تبدّله برُمّتِه وتضع مكانه إيداعًا جديدًا محسَّنًا وتزيح القديم عن الطريق. في الحقيقة، هذا كأن الإيداع السابق لم يحدث من الأصل، ولن يظهر في تاريخ مستودعك.

الفائدة الواضحة لتصحيح الإيداعات هو التحسينات الطفيفة للإيداع الأخير، بغير إزحام تاريخ مستودعك برسائل إيداعات من نوعية «عذرا، نسيت إضافة ملف» أو «سحقا، خطأ مطبعي في الإيداع السابق؛ أصلحته».

لا تصحح إلا الإيدعات التي لا تزال على جهازك ولم تدفعها بعد إلى أي مكان آخر. فتصحيح إيداع قد دُفع بالفعل ثم الدفع عَنوةً (git push --force) سيسبب مشاكل للمتعاونين معك. لمعرفة ما سيحدث إن فعلت هذا وكيف تتعافي إذا كنت الطرف المتلقي، اقرأ فصل محذورات إعادة التأسيس.

إلغاء تأهيل ملف مؤهل

سيوضح الفصلان التاليان كيف تتعامل مع التعديلات في منطقة تأهيلك ومجلد عملك. الجميل أن الأمر الذي تستخدمه لمعرفة حالة إحدى هاتين المنطقتين يذكّرك أيضا بكيفية التراجع عما فيهما من تعديلات. إن كنت مثلًا قد عدّلت ملفين وأردت إيداع كلٍ منهما في إيداع منفصل، ولكنك كتبت خطأً git add * فأهّلت كليهما. كيف يمكنك إلغاء تأهيل أحدهما؟ أمر الحالة يذكّرك:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README
    modified:   CONTRIBUTING.md

مباشرةً تحت ‪“Changes to be committed”‬ («تعديلات ستُودَع») تجده يقول «استخدم git reset HEAD «ملفات» لإلغاء التأهيل». فلنعمل بهذه النصيحة إذًا، لإلغاء تأهيل ملف CONTRIBUTING.md:

$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M	CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

هذا الأمر غريب قليلًا، لكنه يعمل كما توقعنا. ملف CONTRIBUTING.md معدّل لكنه عاد من جديد غير مؤهل.

صدقًا إن git reset أمر خطِر، خصوصًا مع الخيار --hard. مع ذلك، فإن الملف الذي في مجلد عملك لم يُمس في الموقف الموضح بالأعلى، لذا فهذا الأمر آمن نسبيًّا في مثل هذا الموقف.

هذا الأمر السحري هو كل ما تحتاج معرفته الآن عن أم‍ر الإرجاع git reset. سنغوص في فصل تبديد الغموض عن أمر الإرجاع reset في تفاصيل أعمق كثيرا عن أمر الإرجاع وماذا يفعل وكيف تتقنه لتفعل أفعالا شيقة وممتعة جدا.

إعادة ملف معدل إلى حالته قبل التعديل

ماذا لو أدركت أنك لم تعد تريد تعديل ملف CONTRIBUTING.md من الأساس؟ كيف يمكنك إرجاعه إلى حالته عند الإيداع الأخير (أو الاستنساخ الأول، أو كيفما حصلت عليه في مجلد عملك)؟ لحسن الحظ، يخبرك أمر الحالة بهذا أيضا. في ناتج المثال الأخير، كان جزء التعديلات غير المؤهلة هكذا:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

فيخبرك أن تستخدم الأمر git checkout -- «ملفات» لتجاهل التعديلات التي في مجلد عملك. لنفعل ما يخبرنا به:

$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

كما ترى، أُلغيت التعديلات.

من المهم جدا فهم أن git checkout -- «ملفات» أمر خطِر؛ أي تعديلات غير مودعة، على هذا الملف، قد ضاعت، فقد أزال جت للتو هذا الملف ووضع مكانه آخِر نسخة مؤهلة أو مودعة منه. إياك أبدا أن تستعمل هذا الأمر، إلا أن تكون واعيًا أشد الوعي أنك لا تريد هذه التعديلات غير المحفوظة.

إذا أردت الإبقاء على تعديلاتك على هذا الملف لكنك لا تزال تريد إزاحته جانبًا الآن، فسنشرح التفريع في باب التفريع في جت والتخبئة بعد ذلك؛ هاتان الطريقتان أفضل عمومًا.

تذكر أن أي شيء تودعه في جت يمكن شِبه دائمًا استعادته. حتى الإيداعات في الفروع المحذوفة أو الإيداعات المبدلة بخيار التصحيح (--amend) يمكن استعادتها (انظر فصل استرجاع البيانات لاستعادة البيانات). مع ذلك، أي شيء تفقده لم يكن مودعًا، صعب أن تراه مرة أخرى.

التراجع بأمر الاستعادة git restore

أضافت النسخة 2.23.0 من جت أمرًا جديدًا: git restore. هذا في الأصل بديل لأمر الإرجاع git reset الذي ناقشناه للتو. بَدءًا من النسخة 2.23.0 من جت، سيستخدم جت أمر الاستعادة git restore بدلا من أم‍ر الإرجاع git reset في الكثير من عمليات التراجع.

لنرتد على آثارنا قَصصًا ونعيد الكرّة ونتراجع بأمر الاستعادة git restore بدلًا من أم‍ر الإرجاع git reset.

إلغاء تأهيل ملف مؤهل بأمر الاستعادة

سيوضح الفصلان التاليان كيف تتعامل مع التعديلات في منطقة تأهيلك ومجلد عملك بأمر الاستعادة git restore. الجميل أن الأمر الذي تستخدمه لمعرفة حالة إحدى هاتين المنطقتين يذكّرك أيضا بكيفية التراجع عما فيهما من تعديلات. إن كنت مثلًا قد عدّلت ملفين وأردت إيداع كلٍ منهما في إيداع منفصل، ولكنك كتبت خطأً git add * فأهّلت كليهما. كيف يمكنك إلغاء تأهيل أحدهما؟ أمر الحالة يذكّرك:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   CONTRIBUTING.md
	renamed:    README.md -> README

مباشرةً تحت ‪“Changes to be committed”‬ («تعديلات ستُودَع») تجده يقول «استخدم git restore --staged «ملفات» لإلغاء التأهيل». فلنعمل بهذه النصيحة إذًا، لإلغاء تأهيل ملف CONTRIBUTING.md:

$ git restore --staged CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    README.md -> README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   CONTRIBUTING.md

ملف CONTRIBUTING.md معدّل لكنه عاد من جديد غير مؤهل.

إعادة ملف معدل إلى حالته قبل التعديل بأمر الاستعادة

ماذا لو أدركت أنك لم تعد تريد تعديل ملف CONTRIBUTING.md من الأساس؟ كيف يمكنك إرجاعه إلى حالته عند الإيداع الأخير (أو الاستنساخ الأول، أو كيفما حصلت عليه في مجلد عملك)؟ لحسن الحظ، يخبرك أمر الحالة بهذا أيضا. في ناتج المثال الأخير، كان جزء التعديلات غير المؤهلة هكذا:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   CONTRIBUTING.md

فيخبرك أن تستخدم الأمر git restore «ملفات» لتجاهل التعديلات التي في مجلد عملك. لنفعل ما يخبرنا به:

$ git restore CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    README.md -> README

من المهم جدا فهم أن git restore «ملفات» أمر خطِر؛ أي تعديلات غير مودعة، على هذا الملف، قد ضاعت، فقد أزال جت للتو هذا الملف ووضع مكانه آخِر نسخة مؤهلة أو مودعة منه. إياك أبدًا أن تستعمل هذا الأمر، إلا أن تكون واعيًّا أشد الوعي أنك لا تريد هذه التعديلات غير المحفوظة.