تمام VCS ها یک ویژگی برای اصلاح خطاها تا نقطهای خاص در نظر گرفتهاند git ویژگیای فراهم آورده است که با استفاده از آن میتوانیم برخی دستکاریهایمان را به حالت قبل برگردانیم.
توانایی بازگشت به حالت قبل در مواردی که کاربر بطور تصادفی برخی دستکاریها را روی انبار محلی انجام داده است، و میخواهد آنها را حذف کند، نقش کلیدی ایفا میکند.
بیایید فرض کنیم Jerry بطور تصادفی فایلی را در انبار محلی خودش دستکاری کرده است. اما او میداند که میخواهد دستکاریش را از بین ببرد. برای کنترل کردن چنین موقعیتی، ما میتوانیم از دستور git checkout استفاده کنیم. با این دستور محتوای یک فایل را میتوانیم به حالت قبل برگردانیم.
[jerry@CentOS src]$ pwd /home/jerry/jerry_repo/project/src [jerry@CentOS src]$ git status -s M string_operations.c [jerry@CentOS src]$ git checkout string_operations.c [jerry@CentOS src]$ git status –s
ما میتوانیم از دستور git checkout برای بازیابی فایلهای پاک شده از انبار محلی هم استفاده کنیم. Tom یک فایل را از انبار محلی خودش پاک کرده و حالا ما میخواهیم آن را برگردانیم. ما میتوانیم از git checkout استفاده کنیم
[tom@CentOS src]$ pwd /home/tom/top_repo/project/src [tom@CentOS src]$ ls -1 Makefile string_operations.c [tom@CentOS src]$ rm string_operations.c [tom@CentOS src]$ ls -1 Makefile [tom@CentOS src]$ git status -s D string_operations.c
Fit کاراکتر D را قبل از فایلهایی که پاک شدهاند نشان میدهد.
[tom@CentOS src]$ git checkout string_operations.c [tom@CentOS src]$ ls -1 Makefile string_operations.c [tom@CentOS src]$ git status -s
نکته: ما میتوانیم تمام این کارها را قبل از commit کردن تغییرات انجام دهیم.
دیدیم که با git add )عملیات افزودن( یک فایل از انبار محلی به staging area منتقل میشود. اگر کاربر، تصادفی فایلی را دستکاری و سپس به منتقل کرد، ولی ناگهانی متوجه شد که اشتباه کرده است و میخواهد تغییراتش را بازگرداند، در چنین حالتی میتوانیم از git checkout استفاده کنیم
در Git یک head pointer وجود دارد که همیشه روی آخرین commit )درواقع commit pointer هم هست( قرار دارد. اگر شما بخواهید که یک تغییر را از staging area بازگردانید، میتوانید از دستور git checkout استفاده کنید، اما باید یک پارامتر دیگر را هم به دستور اضافه کنید که آن head pointer است. این پارامتر اضافه باعث میشود که این دستور working tree را reset کند و تغییرات را از staging area پاک کند
حال بیایید فرض کنیم Tom یک فایل از انبار محلی را دستکاری کرده است. اگر ما وضعیت فایل را با git status واررسی کنیم، میبینیم که فایل دستکاری شده ولی هنوز به staging area افزوده)با دستور git add نشده است
tom@CentOS src]$ pwd /home/tom/top_repo/project/src # Unmodified file [tom@CentOS src]$ git status -s # Modify file and view it’s status. [tom@CentOS src]$ git status -s M string_operations.c [tom@CentOS src]$ git add string_operations.c
Git status نشان میدهد که فایل اکنون در staging area قرار دارد، حالا باgit checkout فایل را برگردانده و وضعیت آن را با git status میبینیم
[tom@CentOS src]$ git checkout HEAD -- string_operations.c [tom@CentOS src]$ git status -s
بعد از انجام چند تغییر ممکن است تصمیم بگیریم آنها را پاک 1 کنیم. دستور git reset برای reset یا پاک کردن برخی تغییرات بکار میرود. ما میتوانیم سه نوع متفاوت بازگردانی یا reset را انجام دهیم
دیاگرام زیر نمودار وضعیت head pointer را قبل و بعد از reset نمایش میدهد
هر branch یک head ponter دارد که روی آخرین commit قرار دارد. اگر از دستور git reset با -soft استفاده کنیم و در ادامهاش commit ID مورد نظر را بیاوریم head pointer, بدون اینکه چیزی را از بین ببرد reset میشود
commit ID, head pointer ها برای هر branch در آدرسی نظیر آدرس زیر که برای master branch است، ذخیره میشوند .git/refs/heads/master ما میتوانیم با استفاده از دستور git log-1 آن را بازبینی کنیم
[jerry@CentOS project]$ cat .git/refs/heads/master 577647211ed44fe2ae479427a0668a4f12ed71a1
حالا با دستور git log -2 آخرین commit ID را میبینیم که با commit ID بالا یکسان خواهد بود
[jerry@CentOS project]$ git log -2
دستورات بالا نتایج زیر را در برخواهند داشت
commit 577647211ed44fe2ae479427a0668a4f12ed71a1 Author: Tom Cat <tom@howcodex.com> Date: Wed Sep 11 10:21:20 2013 +0530 Removed executable binary commit 29af9d45947dc044e33d69b9141d8d2dad37cc62 Author: Jerry Mouse <jerry@howcodex.com> Date: Wed Sep 11 10:16:25 2013 +0530 Added compiled binary
حالا بیایید HEAD POINTER را reset کنیم
[jerry@CentOS project]$ git reset --soft HEAD~
حالا ما فقط head pointer را به اندازه یک commit, reset کردیم. بیایید محتوای git/refs/heads/master file
[jerry@CentOS project]$ cat .git/refs/heads/master 29af9d45947dc044e33d69b9141d8d2dad37cc62
commit ID تغییر کرده است، حالا بازبینی میکنیم
jerry@CentOS project]$ git log -2
دستورات بالا نتایج زیر را در برخواهند داشت:
commit 29af9d45947dc044e33d69b9141d8d2dad37cc62 Author: Jerry Mouse <jerry@howcodex.com> Date: Wed Sep 11 10:16:25 2013 +0530 Added compiled binary commit 94f7b26005f856f1a1b733ad438e97a0cd509c1a Author: Jerry Mouse <jerry@howcodex.com> Date: Wed Sep 11 10:08:01 2013 +0530 Added Makefile and renamed strings.c to string_operations.c
دستور git reset --mixed تغییراتی را از staging area باز میگرداند که هنوز commit نشده باشند. فقط تغییرات را از staging area برمیگرداند. تغییرات واقعی که در فایل داده شدهاند دست نخورده میمانند. دستور پیشفرض git reset معادل git reset --mixed است
اگر از --hard استفاده کنیم staging area پاک میشود head pointer به آخرین commit یا یک commit خاص reset شده و تمام فایلهای محلیای که تغییر کردهاند پاک خواهند شد
بیاید commit ID را چک کنیم
[jerry@CentOS src]$ pwd /home/jerry/jerry_repo/project/src [jerry@CentOS src]$ git log -1
دستورات بالا نتایج زیر را در برخواهند داشت:
commit 577647211ed44fe2ae479427a0668a4f12ed71a1 Author: Tom Cat <tom@howcodex.com> Date: Wed Sep 11 10:21:20 2013 +0530 Removed executable binary
Jerry فایل را با اضافه کردن یک خط توضیح در ابتدای فایل دستکاری میکند
[jerry@CentOS src]$ head -2 string_operations.c /* This line be removed by git reset operation */ #include <stdio.h>
او با git status بازبینی میکند:
[jerry@CentOS src]$ git status -s M string_operations.c
Jerry فایل را به staging area میافزاید و بازبینی میکند:
[jerry@CentOS src]$ git add string_operations.c [jerry@CentOS src]$ git status
دستورات بالا نتایج زیر را در برخواهند داشت:
# On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: string_operations.c #
git status نشان میدهد که فایل اکنون در staging area است. حالا دستور git reset --hard را وارد میکنیم
[jerry@CentOS src]$ git reset --hard 577647211ed44fe2ae479427a0668a4f12ed71a1 HEAD is now at 5776472 Removed executable binary
دستور با موفقیت اجرا و در نتیجه آن فایل از staging area حذف شد و همچنین تغییراتی که در انبار محلی ایجاد شده بودند پاک شدند
[jerry@CentOS src]$ git status -s
git status نشان میدهد که فایل از staging area برداشته شده است
[jerry@CentOS src]$ head -2 string_operations.c #include <stdio.h>
دستور head نیز نشان میدهد که تغییرات محلی نیز حذف شدهاند