Git revert چیست؟
دستور git revert را می توان به عنوان یک دستور undo
شناخت. البته کاری که این دستور انجام می دهد یک undo
معمولی نیست. به جای حذف Commit از تاریخچه ی پروژه، این دستور، تغییرات ایجاد شده توسط Commit را بر می گرداند و محتوای نهایی را در قالب یک Commit جدید ثبت می کند. این کار جلوی از دست رفتن تاریخچه ی گیت پروژه که اهمیت بالایی دارد را می گیرد.
هنگامی باید از revert استفاده کنید که می خواهید معکوس یک Commit را در تاریخچه ی پروژه اعمال کنید. برای نمونه، این قابلیت هنگامی که باگی را دنبال می کنید و متوجه می شوید که توسط یک Commit خاص در پروژه ایجاد شده است، کاربرد دارد. به جای اینکه به صورت دستی باگ را برطرف کنید و یک Commit جدید انجام دهید می توانید از git revert استفاده کنید تا همه ی این کار ها را به صورت خودکار برای شما انجام دهد.
Git revert چگونه کار می کند؟
دستور git revert برای خنثی کردن تغییرات یک Commit در تاریخچه ی مخزن استفاده می شود. سایر دستور هایی که تغییرات را undo می کنند مانند git checkout و git reset HEAD و نشان گر مرجع شاخه را به یک Commit خاص می برند. git revert هم یک Commit خاص را در نظر می گیرد اما نشان گر مرجع را به آن نمی برد. عملیات revert آن Commit خاص را در نظر می گیرد، تغییرات آن را معکوس می کند و یک " revert Commit
" می سازد. نشانگر های مرجع پس از این عملیات به روز می شوند تا به Commit جدید اشاره کنند و آن را head branch
قرار دهند. برای درک بهتر، یک مخزن فرضی با دستورهای زیر درست می کنیم.
mkdir git_revert_test
cd git_revert_test/
git init .
touch demo_file
git add demo_file
git commit -am"initial commit"
echo "initial content" >> demo_file
git commit -am"add new content to demo file"
echo "prepended line content" >> demo_file
git commit -am"prepend content to demo file"
git log --oneline
پس از اجرای دستورهای بالا اگر دستور git log --oneline
را اجرا کنیم خروجی زیر را می بینیم.
d017c50 (HEAD -> master) prepend content to demo file
a9efd46 add new content to demo file
a4a450a initial commit
در این جا یک مخزن جدید به نام git_revert_test
ایجاد کردیم. سه Commit در مخزن انجام دادیم که فایل demo_file
را اضافه کرد و محتویات آن را دو بار تغییر داد. در انتهای فرایند از دستور git log استفاده کردیم تا تاریخچه ی Commit ها را ببینیم. با وجود مخزن در این حالت می توانیم یک git revert را آغاز کنیم. دستور زیر را اجرا می کنیم.
git revert HEAD
پاسخی مانند زیر در خروجی نشان داده می شود.
[master 89a32e6] Revert "prepend content to demo file"
1 file changed, 1 deletion(-)
دستور git revert بدون دادن یک مرجع Commit اجرا نمی شود. در این مثال ما HEAD را به عنوان مرجع داده ایم. این کار باعث می شود آخرین Commit revert شود. این کار نتیجه ای مشابه revert کردن Commit d017c50 دارد. مانند merge کردن، عملیات revert یک Commit جدید ایجاد می کند که باعث می شود ویرایش گر سیستم برای ثبت پیام Commit جدید باز شود. پس از اینکه پیام Commit جدید ثبت شد گیت عملیات را ادامه می دهد. اکنون می توانیم وضعیت مخزن را با دستور git log مشاهده کنیم و ببینیم که Commit جدید اضاف شده است.
89a32e6 (HEAD -> master) Revert "prepend content to demo file"
d017c50 prepend content to demo file
a9efd46 add new content to demo file
a4a450a initial commit
توجه کنید که Commit سوم پس از انجام revert در تاریخچه ی پروژه موجود است. git revert به جای حذف آن، یک Commit جدید که تغییرات Commit سوم را خنثی می کند، اضافه کرده است. در نتیجه ی این عملیات، Commit دوم و چهارم وضعیت یکسانی دارند و Commit سوم هم هنوز در تاریچه ی پروژه موجود است تا اگر نیاز شد بتوانیم به آن برگردیم.
گزینه های معمول
-e
--edit
این یک گزینه ی پیش فرض است و نیازی به مشخص کردن آن، هنگام اجرای دستور نیست. این گزینه ی ویرایش گر تنظیم شده در سیستم عامل را باز می کند و از شما می خواهد پیام مربوط به Commit عملیات revert را بنویسید.
--no-edit
این گزینه برعکس -e
است. با مشخص کردن این گزینه، پنجره ی ویرایش پیام Commit نشان داده نمی شود.
-n
--no-commit
مشخص کردن این گزینه باعث می شود git revert Commit جدیدی ایجاد نکند. به جای آن، گیت تغییرهای معکوس را در فهرست Staging قرار می دهد. برای اطلاعات بیشتر بخش git reset را مطالعه کنید.
Reset در مقابل Revert
این که بدانیم git revert یک Commit را خنثی می کند و با پاک کردن Commit های قبلی مخزن را به وضعیت آن Commit بر نمی گرداند، اهمیت زیادی دارد. در گیت، این کار reset کردن نام دارد و با revert متفاوت است.
revert کردن دو مزیت مهم نسبت به reset کردن دارد. اول، تاریخچه پروژه را تغییر نمی دهد که باعث می شود یک عملیات ایمن برای Commit های قبلی ثبت شده در مخزن به حساب بیاید. برای مطالعه ی جزئیات بیشتر درمورد چرایی خطرناک بودن تغییر تاریخچه ی پروژه بخش git reset را مطالعه کنید.
دوم، git revert می تواند یک Commit خاص در هر جای تاریخچه ی پروژه را مورد هدف قرار دهد. در حالی که git reset تنها می تواند به Commit های قبل تر از Commit فعلی برگردد. برای مثال اگر می خواستید یک Commit قدیمی را با git reset خنثی کنید، باید همه ی Commit هایی که بعد از Commit موردنظر ثبت شده اند را پاک کنید و پس از اتمام عملیات reset، همه ی آنها را دوباره ثبت کنید. واضح است که این، راهکار مناسبی برای خنثی کردن یک Commit نیست.
خلاصه
دستور git revert کار undo را بدون حذف تاریخچه ی پروژه انجام می دهد. به جای پاک کردن Commit ها، این دستور یک revert commit جدید ایجاد می کند که تغییرات Commit مورد نظر را خنثی می کند. git revert جایگزین ایمن تر دستور git reset است. در این مطلب از دستور های git log، git commit و git reset که هر کدام بخش های اختصاصی خود را در این دوره دارند استفاده شد.