إذا كان هناك إيداع قديم يحتوي على تغيير غير مرغوب فيه لملف واحد، فيمكنك التراجع عن تغيير ذلك الملف مقارنة بفرعك الحالي وحفظ النتيجة في إيداع جديد. يحافظ هذا على الإيداعات اللاحقة في مكانها ويبقي على تعديلاتها عندما تكون رقعة التراجع متوافقة. على نظام macOS، استخدم Terminal من داخل المستودع؛ راجع الرقعة أولاً، خاصةً إذا كان العمل اللاحق قد مسّ الأسطر نفسها.

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

يضيف هذا الإجراء إيداعاً يلغي تغيير الإيداع المستهدف لمسار واحد. ولا يحذف ذلك الملف من الإيداع القديم، وبالتالي تظل النسخة القديمة في السجل. يتجنب هذا النهج إعادة كتابة سجل الفرع، وعادة ما يكون مناسباً عندما يكون الإيداع قد تمت مشاركته بالفعل أو تعتمد عليه إيداعات لاحقة. يصف Git الأمر git revert بأنه تسجيل لإيداع جديد يعكس إيداعاً سابقاً، لكنه لا يوفر خياراً مدمجاً للتراجع عن مسار واحد فقط من إيداع موجود. بدلاً من ذلك، تنشئ الخطوات أدناه رقعة (patch) لذلك المسار وتطبقها بشكل عكسي. Git: وثائق git-revert

إذا كان لابد من إزالة تغيير الملف من الإيداع التاريخي نفسه، فهذه مهمة إعادة كتابة للسجل، وتتم معالجتها عادةً باستخدام إعادة بناء تفاعلية (interactive rebase). تؤدي إعادة الكتابة إلى تغيير هويات الإيداعات (commit identities) ويمكن أن تعطل المتعاونين الذين بنوا أعمالهم على الإيداعات القديمة. يغطي هذا الدليل النهج الأكثر أماناً القائم على الإضافة.

التراجع عن تغيير الإيداع المستهدف لملف واحد

افتح Terminal، وانتقل إلى المستودع، وتحقق من شجرة العمل (working tree) قبل تغيير أي شيء. استبدل TARGET بمعرّف الإيداع (commit ID) وpath/to/file بالمسار النسبي لجذر المستودع. يستخدم المثال ملف رقعة مؤقتاً في دليل /tmp على macOS؛ اختر اسماً مؤقتاً مختلفاً إذا كان هذا الملف موجوداً بالفعل.

git status --short
git show --stat --oneline TARGET
git diff TARGET^ TARGET -- "path/to/file" > /tmp/remove-file-change.patch

يقارن أمر diff الإيداع المستهدف مع أصله الأول (first parent) ويحصر النتيجة في المسار المحدد. بالنسبة للإيداع العادي غير الناتج عن دمج، يمثل هذا تغيير ذلك الإيداع على الملف. تأكد من أن الملخص يحدد الإيداع المقصود وأن الرقعة ليست فارغة. يمكنك فحصها باستخدام less /tmp/remove-file-change.patch؛ اضغط على q للخروج. توثق Git مقارنات diff من إيداع إلى إيداع مع تحديد مسار اختياري. Git: وثائق git-diff

قبل تطبيقها، تأكد من عدم وجود تعديلات غير ذات صلة مدرجة في مساحة التجهيز (staged) أو غير مدرجة (unstaged) في الملف المستهدف. تُغيّر الرقعة العكسية نسخة العمل، لذا فإن شجرة العمل النظيفة هي أبسط نقطة بداية. إذا كان لديك عمل محلي مفيد، فقم بإيداعه أو عزله بأمان أولاً؛ لا تقم بالكتابة فوقه باستخدام أمر استعادة (restore).

تحقق مما إذا كانت الرقعة العكسية تتطابق، ثم طبقها:

git apply --reverse --check /tmp/remove-file-change.patch
git apply --reverse /tmp/remove-file-change.patch

يطبق الخيار --reverse الفروقات بشكل عكسي، بينما يتحقق --check مما إذا كانت الرقعة تُطبّق دون تغيير الملفات. بشكل افتراضي، يفشل git apply في تطبيق الرقعة بأكملها إذا لم تتطابق بعض الأجزاء (hunks)، بدلاً من تطبيق الأجزاء المتطابقة فقط. إذا فشل الفحص، فتوقف وافحص الملف والرقعة. قد تتداخل التعديلات اللاحقة مع التغيير المستهدف، لذا لا يمكن لـ Git تحديد ما يجب إزالته بأمان. قم بحل المحتوى المقصود يدوياً، أو استخدم سير عمل إعادة كتابة السجل إذا كان الحفاظ على تسلسل تاريخي معدل بدقة أمراً ضرورياً. لا تضف --reject دون تأنٍ: فقد يطبق الأجزاء المتطابقة فقط ويترك الأجزاء المرفوضة وراءه. Git: وثائق git-apply

مراجعة النتيجة وإيداعها

افحص بدقة ما تغير قبل الإدراج في مساحة التجهيز. يعرض git diff تعديلات شجرة العمل؛ استخدم المسار مرة أخرى لتركيز المراجعة. إذا كانت النتيجة صحيحة، فأدرج ذلك الملف وتحقق من الفروقات المجهزة قبل إنشاء إيداع جديد.

git diff -- "path/to/file"
git add -- "path/to/file"
git diff --cached -- "path/to/file"
git status --short
git commit -m "Remove file change from earlier commit"

تحمي علامات الاقتباس المسار من تفسير سطر الأوامر (shell)، وتحدد -- نهاية الخيارات. وهي مفيدة بشكل خاص للأسماء التي تحتوي على مسافات أو محارف سطر الأوامر الخاصة. يسجل الإيداع الفهرس المجهز؛ وتؤكد مراجعة git diff --cached المحتوى الدقيق الذي على وشك أن يتم إيداعه. Git: وثائق git-commit

بعد الإيداع، تحقق من git status --short وافحص الإيداع الجديد باستخدام git show --stat --oneline HEAD. إذا كان الإيداع الأصلي قد أضاف الملف، فإن عكس رقعته قد يؤدي إلى حذفه — وهذا متوقع إذا لم تكن هناك حاجة لبقاء أي محتوى لاحق. إذا كانت الإيداعات اللاحقة قد أضافت محتوى مفيداً إلى ذلك الملف، فيجب أن تظل تلك الإضافات موجودة عند تطبيق الرقعة العكسية بشكل نظيف؛ راجع الملف النهائي والفروقات للتأكيد.

حالات تتطلب عناية إضافية

يحتوي إيداع الدمج (merge commit) على أصول متعددة، ويعتمد تغييره على الأصل الذي تقارن به. تعني TARGET^ الأصل الأول؛ وقد لا يمثل التغيير الذي كنت تنوي إزالته. حدد الأصل الصحيح وقارن به صراحة قبل تطبيق أي شيء. قد تؤدي عمليات إعادة التسمية والملفات الثنائية والملفات التي تم نقلها لاحقاً أيضاً إلى جعل الرقعة المحددة بمسار غير مناسبة؛ تحقق من الـ diff وتوقف إذا لم يكن يصف التغيير المقصود للملف. بالنسبة لحالات التراجع الخاصة بعمليات الدمج، تشرح وثائق git revert اختيار الأصل الرئيسي (mainline parent) وتبعاته. Git: وثائق git-revert

نقطة التحقق الموثوقة هي الرقعة بعد مراجعتها: يجب أن تُظهر فقط تغيير الإيداع المستهدف للمسار المقصود. إذا لم تتمكن من تطبيقها بشكل نظيف على ملف اليوم، فلا تجبرها. أعد بناء الملف الحالي المطلوب بعناية، ثم أدرجه وقم بإيداعه فقط بعد مراجعة النتيجة الكاملة.

المصادر