در هر مرحله ممکن است بخواهید کاری را بازگردانید. در اینجا، چند ابزار پایه برای بازگرداندن تغییراتی که ایجاد کردهاید مرور میکنیم. مواظب باشید، چون همیشه نمیتوانید همه این بازگردانیها را لغو کنید. این یکی از معدود موارد در گیت است که اگر اشتباه انجام شود، ممکن است بخشی از کارتان را از دست بدهید.
یکی از بازگردانیهای رایج زمانی است که خیلی زود کامیت میکنید و احتمالاً برخی فایلها را اضافه نکردهاید یا پیام کامیت خود را اشتباه نوشتهاید.
اگر میخواهید آن کامیت را اصلاح کنید، تغییرات اضافی که فراموش کردهاید را اعمال کنید، آنها را مرحلهبندی (stage) کرده و دوباره با گزینه --amend کامیت کنید:
$ git commit --amendاین دستور، منطقه آمادهسازی شما را گرفته و برای انجام کامیت استفاده میکند. اگر از آخرین کامیت خود هیچ تغییری ایجاد نکرده باشید (برای مثال، بلافاصله پس از کامیت قبلی این دستور را اجرا کنید)، اسنپشات شما دقیقاً مشابه قبلی خواهد بود و تنها چیزی که تغییر میکند، پیام کامیت شماست.
ویرایشگر پیام کامیت همانند قبل باز میشود، اما پیام کامیت قبلی شما را در خود دارد. میتوانید پیام را همانند همیشه ویرایش کنید، اما این پیام جایگزین کامیت قبلی خواهد شد.
مثلاً اگر کامیت کردید و بعد متوجه شدید تغییرات یک فایل که میخواستید به این کامیت اضافه کنید را آماده نکردهاید، میتوانید کاری مشابه این انجام دهید:
$ git commit -m 'Initial commit'
$ git add forgotten_file
$ git commit --amendدر نهایت شما یک کامیت واحد خواهید داشت — کامیت دوم جایگزین نتایج کامیت اول میشود.
|
Note
|
مهم است که بفهمید وقتی کامیت آخر خود را اصلاح میکنید، در واقع آن را صرفاً اصلاح نمیکنید بلکه کاملاً جایگزینش میکنید با یک کامیت جدید و بهبود یافته که کامیت قدیمی را کنار میزند و کامیت جدید را به جای آن قرار میدهد. در واقع، انگار کامیت قبلی هرگز اتفاق نیفتاده و در تاریخچه مخزن شما نشان داده نخواهد شد. |
|
Note
|
ارزش واضح اصلاح کامیتها این است که بتوانید بهبودهای کوچک را روی آخرین کامیت خود انجام دهید بدون اینکه تاریخچه مخزن شما با پیامهای کامیتی مانند «اوه، فراموش کردم یک فایل اضافه کنم» یا «لعنتی، دارم اشتباه تایپی در کامیت آخر را اصلاح میکنم» شلوغ شود. فقط کامیتهایی را اصلاح کنید که هنوز محلی هستند و به جایی ارسال نشدهاند. اصلاح کامیتهایی که قبلاً ارسال شدهاند و سپس ارسال اجباری شاخه باعث مشکلاتی برای همکارانتان خواهد شد. برای اطلاعات بیشتر در مورد اتفاقاتی که در این شرایط میافتد و چگونگی بازیابی در صورتی که در موقعیت دریافتکننده باشید، مطلب [_rebase_peril] را مطالعه کنید. |
دو بخش بعدی نحوه کار با ناحیه مرحلهبندی و تغییرات دایرکتوری کاری شما را نشان میدهد.
نکته خوب این است که دستوری که برای تعیین وضعیت این دو ناحیه استفاده میکنید، همچنین به شما یادآوری میکند چگونه تغییرات آنها را لغو کنید.
برای مثال، فرض کنید دو فایل را تغییر دادهاید و میخواهید آنها را بهصورت دو تغییر جداگانه کامیت کنید، اما به اشتباه دستور git add * را زده و هر دو را مرحلهبندی کردهاید.
چطور میتوانید یکی از آن دو را از مرحلهبندی خارج کنید؟
دستور git status به شما یادآوری میکند:
$ 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 <file>… برای لغو مرحلهبندی استفاده کنید.
پس بیایید از این راهنمایی استفاده کنیم و فایل 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 تغییر یافته اما دوباره از حالت استیج خارج شده است.
|
Note
|
درست است که دستور |
فعلا همین فراخوانی جادویی تمام چیزی است که باید درباره دستور git reset بدانید.
در ch07-git-tools.asc جزئیات بیشتری درباره عملکرد reset و چگونگی تسلط بر آن برای انجام کارهای جالب خواهیم گفت.
اگر متوجه شدید که نمیخواهید تغییرات فایل CONTRIBUTING.md را نگه دارید، چه میکنید؟
چطور میتوانید به سادگی آن را به حالتی برگردانید که در آخرین کامیت (یا در ابتدا هنگام کلون کردن، یا هرطور که وارد دایرکتوری کاریتان شده) بود؟
خوشبختانه، git status به شما میگوید چطور این کار را انجام دهید.
در خروجی مثال قبلی، بخش unstaged اینگونه بود:
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 -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> READMEمیبینید که تغییرات برگردانده شدهاند.
|
Important
|
مهم است بدانید که دستور |
اگر میخواهید تغییراتتان را نگه دارید ولی فعلا میخواهید آن را کنار بگذارید، در ch03-git-branching.asc درباره stash و branch صحبت خواهیم کرد؛ این روشها عموما بهتر هستند.
به یاد داشته باشید، هر چیزی که در گیت کامیت شده باشد تقریبا همیشه قابل بازیابی است.
حتی کامیتهایی که روی شاخههایی بودند که حذف شدهاند یا کامیتهایی که با --amend بازنویسی شدهاند هم قابل بازیابی هستند (برای بازیابی دادهها به ch10-git-internals.asc مراجعه کنید).
اما هر چیزی که از دست بدهید و هرگز کامیت نشده باشد، احتمالا دیگر قابل بازیابی نیست.
نسخه ۲.۲۳.۰ گیت یک دستور جدید معرفی کرد: git restore.
این در واقع جایگزینی برای git reset است که همین حالا بررسی کردیم.
از نسخه ۲.۲۳.۰ به بعد، گیت برای بسیاری از عملیات بازگردانی به جای git reset از git restore استفاده خواهد کرد.
بیایید دوباره مراحل را طی کنیم و با git restore به جای git reset عملیات بازگردانی را انجام دهیم.
دو بخش بعدی نشان میدهند چگونه با استفاده از git restore با تغییرات در منطقه استیج و دایرکتوری کاری کار کنیم.
نکته خوب این است که دستوری که برای مشاهده وضعیت این دو ناحیه استفاده میکنید، به شما یادآوری میکند چطور تغییراتشان را بازگردانید.
مثلا فرض کنید دو فایل را تغییر دادهاید و میخواهید به صورت دو تغییر جداگانه کامیت کنید، اما اشتباها git add * را زده و هر دو را استیج کردهاید.
چطور یکی از آن دو را از حالت استیج خارج کنید؟
دستور git status به شما یادآوری میکند:
$ 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 <file>… استفاده کنید.
پس بیایید طبق این راهنمایی فایل 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 تغییر یافته اما دوباره unstaged شده است.
اگر متوجه شدید که نمیخواهید تغییرات فایل CONTRIBUTING.md را نگه دارید، چطور میتوانید به سادگی آن را به حالتی برگردانید که در آخرین کامیت بود؟
خوشبختانه، git status به شما میگوید چطور این کار را انجام دهید.
در خروجی مثال قبلی، بخش unstaged اینگونه بود:
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 CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: README.md -> README|
Important
|
مهم است بدانید که دستور |