Undo کردن کامیت گیت به صورت لوکال یا ریموت | به زبان ساده

گیت رایجترین سیستم کنترل نسخه (VCS) در جهان برای ردگیری تغییرات فایل به صورت متنی است. به لطف دستورهای گیت ما میتوانیم تغییرهای لوکال خود را با یک پیام لاگ ذخیره کنیم که امکان ارسال آن را به ریپازیتوری ریموت و یا بازگشت به آن حالت را در هر زمانی در آینده فراهم میسازد. در این مقاله با روش Undo کردن کامیت گیت به صورت لوکال یا ریموت آشنا خواهیم شد.
گاهی اوقات ما نیز مانند هر انسان دیگری ممکن است دچار اشتباه شویم. برای نمونه ممکن است فایلهای اشتباهی را در کامیت قرار دهیم، ممکن است در پیام کامیت، غلط املایی داشته باشیم و یا از یکی از کامیتهای جدید خود ناخرسند باشیم و بخواهیم آن را از ریپازیتوری لوکال یا ریموت پاک کنیم. در ادامه این مقاله با روش انجام این کار آشنا خواهیم شد.
حالتهای Undo کردن کامیت گیت
سادهترین حالت Undo کردن کامیت گیت آن است که شما هنوز آن را به ریپازیتوری ریموت پوش نکرده باشید. شما میتوانید هر کاری را در ریپازیتوری گیت لوکال خود انجام دهید، چون هنوز از سوی همکارانتان مورد استفاده قرار نگرفته است.
اما اگر میخواهید یک کامیت یا سابقه گیت را که به ریپازیتوری ریموت پوش شده است و به طور عمومی مورد استفاده قرار میگیرد را ویرایش کنید، باید مراقبت زیادی به خرج بدهید. چون این کار به آن معنی است که با تغییر دادن آن چیزی که از قبل در سابقه گیت وجود دارد، کار افراد دیگر را به خطر میاندازید.
به همین جهت است که باید این حالتها را به دو دسته اصلی به صورت Undo کردن کامیت گیت به صورت لوکال یا ریموت تقسیم کنیم.
Undo کردن کامیت گیت به صورت لوکال
Undo کردن کامیت گیت به صورت لوکال خود چند حالت دارد که در ادامه آنها را یک به یک بررسی میکنیم.
حالت اول لوکال: Stage کردن فایلهای نامربوط
فرض کنید میخواهید یک کامیت در ریپازیتوری لوکال ایجاد کنید و به صورت پیشفرض به صورت زیر عمل میکنید:
git add.
یا
git add –all
این دستورها به منظور حرکت سریع طراحی شدهاند. اما این به آن معنی است که همه تغییرهای همه فایلها به ناحیه staging در آن ریپازیتوری اضافه میشوند. برخی اوقات ممکن است فراموش کنیم که برخی تغییرها به آن کامیت مربوط نیستند و باید آن فایلها را نیز در کامیت بگنجانیم. اما هیچ مشکلی وجود ندارد کافی است دستور git reset را با فایلی که نمیخواهد stage شود به صورت زیر اجرا کنید:
git reset unwanted_file
با استفاده از دستور فوق، میتوانیم فایل تغییر یافته را از ناحیه staging به دایرکتوری کاری انتقال دهیم.
حالت دوم لوکال: پیام نادرست کامیت
فرض کنید یک کامیت به ریپازیتوری لوکال انجام دادهاید، اما متوجه میشوید که آخرین کامیت شما دارای یک غلط املایی است. همچنان جای نگرانی وجود ندارد. با استفاده از دستور git commit با فلگ amend میتوانید این مشکل را رفع کنید:
git commit –amend
این دستور ادیتور ترمینال پیشفرض را باز میکند و میتوانید پیام کامیت آخر را به دلخواه خود به صورت زیر ویرایش کنید:
اگر نمیخواهید با ادیتور سروکله بزنید، میتوانید از فرم مختصر این دستور نیز به صورت زیر استفاده کنید:
git commit --amend -m "my updated commit message"
با استفاده از دستور commit به همراه فلگ amend در واقع کامیت کنونی را بازنویسی میکنیم که یک عملیات تخریبی است. اما اگر این کامیت را قبلاً پوش کرده باشیم، همکاران ما که بر اساس این کامیت تغییراتی در پروژه ایجاد کردهاند، همچنان از نسخه قبلی استفاده خواهند کرد. از این رو یک «تداخل گیت» (git conflict) رخ میدهد که باید حل شود.
حالت سوم لوکال: افزودن تغییرهای اضافی به کامیت آخر
فرض کنید یک کامیت داشتهاید که هنوز پوش نشده است و همچنین متوجه میشوید که تغییرهای اضافی برای این کامیت مورد نیاز هستند. به عنوان یک راهحل ابتدا باید فایلهای تغییر یافته را با استفاده از دستور add گیت به ناحیه staging اضافه کنید.
git add forgotten-file.js
سپس باید از دستور git commit مجدد استفاده کنیم، اما این بار از فلگهای amend و no-edit استفاده میکنیم که به صورت خودکار تغییرهای آخرین موارد stage شده را به آخرین کامیت اضافه میکند.
git commit --amend --no-edit
با استفاده از دستور فوق ما صرفاً محتوای کامیت جاری خود را بهروزرسانی میکنیم. این کار نیز یک عملیات امن در ریپازیتوری لوکال محسوب میشود.
Undo کردن کامیت گیت به صورت ریموت
در این بخش حالتهای مختلف که در زمان Undo کردن کامیت گیت به صورت ریموت ممکن است پیش بیایید بررسی میکنیم.
حالت اول ریموت: Undo کردن کامیت قبلاً پوش شده
فرض کنید چند تغییر در ریپازیتوری لوکال خود ایجاد میکنید که ضروری نیستند و با این حال آن را به یک کامیت در ریپازیتوری ریموت پوش میکنید. اکنون باید برخی چیزها تغییر یابند، زیرا کاربران ریپازیتوری ریموت دیگر نیز ممکن است آخرین تغییرها را دریافت کرده و از آن به این صورت استفاده کنند که گویی سابقه گیت تغییر نیافته است.
امنترین و بهترین رویکرد این است که اشتباه را بپذیریم و یک کامیت اضافی ایجاد کنیم تا تغییرها را بازگردانیم. با انجام این کار این سابقه گیت همچنان پایدار خواهد ماند و مورد اشتباه تا همیشه آنجا باقی خواهد ماند.
به این منظور ابتدا باید ببینیم کامیتهای گیت شما با دستور git log به چه صورت است:
git log –oneline
در تصویر فوق میبینیم که در ابتدای هر ردیف یک رشته وجود دارد که شناسه کامیت است و هش کامیت گیت نامیده میشود و سپس اطلاعات برنچ را میبینید که پیام کامیت را نیز شامل میشود.
برای خروج از این صفحه گیت لاگ کافی است کلید q را بزنید. شاید بدانید که در گیت HEAD به معنی جدیدترین کامیت شما در شاخه جاری است. بنابراین میتوانیم از دستور git revert روی جدیدترین کامیت به صورت زیر استفاده کنیم:
git revert HEAD
به این ترتیب ادیتور متن پیشفرض شما باز میشود و پیام کامیت پیشفرض نیز ظاهر میشود که میتوانید آن را ویرایش کنید:
پس از آن که پیام کامیت خود را ذخیره کردید در ادیتور vi کافی است عبارت wq: را وارد کنید. اینتر را که زدید، خروجی دستور git revert را به صورت زیر میبینید:
اکنون میتوانید سابقه گیت را با دستور git log بررسی کنید:
چنان که میبینید اکنون یک کامیت git revert اضافی داریم که تغییرات قبلی را در کامیت my feature implementation بازگردانی کرده است و تداخلی نیز در سابقه گیت ایجاد نمیکند. این یک عملیات امن است و در اغلب موارد باید به این صورت رفتار شود.
حالت دوم ریموت: Undo کردن چند کامیت
فرض کنید مشغول کار روی یک شاخه هستید که برای هیچ کس مهم نیست. شما یک سری قابلیتهای آزمایشی را پیادهسازی میکنید. سپس زمانی فرا میرسد که باید یک درخواست pull با شاخه فیچر خود ارسال کنید. اما توجه میشوید که کامیتهای زیادی وجود دارند که ربط چندانی به فیچر ندارند و موجب شلوغ شدن فیچر میشوند.
در این موقعیت ابتدا با استفاده از دستور git log کامیتهای آن برنچ را بررسی میکنیم:
سپس تصمیم میگیریم که میخواهیم کامیت اول و آخر بمانند و بقیه حذف شوند. به این منظور یک دستور جالب گیت وجود دارد که interactive git rebase نام دارد. کافی است به کامیت یک شناسه بدهیم تا نقطه آغاز کامیت به آنجا تغییر یابد. در این مورد از کامیت اولیه استفاده میکنیم. بنابراین از دستور گیت زیر استفاده میکنیم:
git rebase -i 1875e2a
این دستور ادیتور ترمینال پیشفرض را باز میکند که در این مورد ادیتور vi است و همه کامیتها را پس از پیام کامیت اولیه به صورت زیر نمایش میدهد:
کافی است کامیتهایی که میخواهید نگه دارید را با عدم تغییر کلیدواژه pick انتخاب کنید. اما در خصوص موارد دیگر که نمیخواهید حفظ شوند، کافی است عبارت d یا drop را به جای pick وارد کنید:
سپس با دقت تغییرها را بررسی کرده و ادیتور را ذخیره کرده و ببندید. خروجی مانند زیر خواهد بود:
اگر میخواهید کامیتها را مجدداً بررسی کنید به صورت زیر خواهد بود:
چنان که میبینید ما از شر کامیتهایی که بین کامیت اول و آخر قرار دارند، رها شدهایم. اما فراموش نکنید که این یک عملیات تخریبی است که باید روی شاخهای اجرا شود که هیچ فرد دیگری از آن استفاده نمیکند.
سخن پایانی
امیدواریم با مطالعه این مقاله با روشهای Undo کردن کامیت گیت به صورت لوکال یا ریموت آشنا شده باشید. هر گونه سؤال یا پیشنهاد خود را در بخش نظرات این نوشته با ما و دیگر خوانندگان مجله فرادرس در میان بگذارید.