مقدمه

در درس‌های گذشته با دستورات git reset و git commit --amend برای لغو تغییرات آشنا شدیم و تاکید کردیم که این دستورات تاریخچه را بازنویسی می‌کنند و بنابراین برای کامیت‌های عمومی و اشتراک‌گذاشته‌شده خطرناک هستند. حال سوال این است: روش امن برای لغو کردن یک کامیت که قبلاً push شده چیست؟

پاسخ، دستور git revert است. این دستور به شما اجازه می‌دهد تا اثرات یک کامیت خاص را خنثی کنید، بدون اینکه تاریخچه پروژه را تغییر دهید یا حذف کنید. این روش، استاندارد طلایی برای اصلاح اشتباهات در یک محیط تیمی است.

Revert دقیقاً چگونه کار می‌کند؟

برخلاف تصور اولیه، git revert تاریخچه را به عقب برنمی‌گرداند یا کامیتی را حذف نمی‌کند. در عوض، این دستور یک کامیت جدید ایجاد می‌کند که تغییرات آن دقیقاً معکوس تغییرات کامیتی است که شما قصد خنثی کردن آن را دارید.

برای مثال، اگر کامیت شماره X یک خط کد به فایل A اضافه کرده باشد، اجرای دستور git revert X یک کامیت جدید (مثلاً Y) ایجاد می‌کند که تنها کار آن، حذف کردن همان خط کد از فایل A است. به این ترتیب، هر دو کامیت در تاریخچه باقی می‌مانند و کاملاً شفاف است که یک تغییر ابتدا اعمال و سپس خنثی شده است.

یک مثال عملی

فرض کنید تاریخچه ما با git log --oneline به این صورت است و متوجه شده‌ایم که کامیت دوم (a1b2c3d) یک باگ را وارد سیستم کرده و باید حذف شود:

f4d5e6f (HEAD -> main) Add footer
a1b2c3d Add buggy feature
1a2b3c4 Initial commit

برای خنثی کردن این کامیت، دستور زیر را اجرا می‌کنیم:

git revert a1b2c3d

با اجرای این دستور، گیت ویرایشگر متن شما را باز می‌کند تا پیام کامیت جدید (کامیتِ خنثی‌کننده) را وارد کنید. گیت به صورت پیش‌فرض یک پیام گویا تولید می‌کند:

Revert "Add buggy feature"

This reverts commit a1b2c3d...

شما می‌توانید این پیام را ذخیره کرده و از ویرایشگر خارج شوید. اکنون اگر دوباره تاریخچه را مشاهده کنید، خواهید دید که یک کامیت جدید اضافه شده است:

e5f6g7h (HEAD -> main) Revert "Add buggy feature"
f4d5e6f Add footer
a1b2c3d Add buggy feature
1a2b3c4 Initial commit

تاریخچه دست‌نخورده باقی مانده، اما وضعیت فعلی کد شما (HEAD) دیگر شامل تغییرات ناخواسته کامیت a1b2c3d نیست.

چرا Revert برای کار تیمی امن است؟

دلیل اصلی امنیت revert این است که تاریخچه را بازنویسی نمی‌کند و فقط به آن اضافه می‌کند. وقتی شما یک کامیت را reset می‌کنید، آن کامیت از تاریخچه حذف می‌شود. اگر همکاران شما قبلاً آن کامیت را pull کرده باشند، تاریخچه آن‌ها با تاریخچه جدید شما ناهماهنگ (divergent) می‌شود و هنگام push/pull بعدی دچار مشکلات پیچیده‌ای خواهند شد.

اما وقتی شما از revert استفاده می‌کنید، کامیت قدیمی سر جای خود باقی می‌ماند و فقط یک کامیت جدید به انتهای تاریخچه اضافه می‌شود. همکاران شما می‌توانند به سادگی با اجرای git pull، این کامیت جدید را دریافت کرده و مخزن خود را بدون هیچ مشکلی به‌روز کنند. این روش یک تاریخچه صادقانه و قابل ردیابی از تمام اتفاقات پروژه را حفظ می‌کند.