در این بخش از آموزش، بحث مفصلی درباره دستور git reflog ارائه شده است. Git با استفاده از مکانیزمی به نام reference logs
یا "reflogs
"، به روزرسانی های شاخه ها را پیگیری می کند. بسیاری از دستورهای Git، پارامتری را برای تعیین یک منبع یا "ref"، که نشانگر یک commit است، می پذیرند. نمونه های متداول عبارتند از:
- git checkout
- git reset
- git merge
reflog ها هنگام به روزرسانی منابع Git، در مخزن محلی ردیابی می شوند. افزون بر reflog های شاخه ها، یک reflog ویژه، برای Git stash (git stash دستوری برای ذخیره ی موقتی تغییرها) نگهداری می شود. reflog ها در دایرکتوری های زیر مخزن محلی دایرکتوری .git ذخیره می شوند. اگر git stash در مخزن استفاده شده باشد، دایرکتوری های git reflog را می توان در .git/logs/refs/heads/.
، .git/logs/HEAD
و همچنین .git / logs / refs / stash
یافت.
در مورد git reflog در سطح بالاتری در Rewriting History Page صحبت کرده ایم. این آموزش شامل موارد زیر است:
- گزینه های پیکربندی git reflog
- موارد استفاده معمول و مشکلات git reflog
- نحوه لغو تغییرها در git reflog
- و برخی موارد دیگر
کاربرد اصلی
ابتدایی ترین کاربرد reflog به صورت زیر است:
git reflog
که یک میان بر است برای:
git reflog show HEAD
با این کار، HEAD مربوط به reflog مشاهده می شود. باید خروجی مشابه زیر را ببینید:
eff544f HEAD@{0}: commit: migrate existing content
bf871fd HEAD@{1}: commit: Add Git Reflog outline
9a4491f HEAD@{2}: checkout: moving from master to git_reflog
9a4491f HEAD@{3}: checkout: moving from Git_Config to master
39b159a HEAD@{4}: commit: expand on git context
9b3aa71 HEAD@{5}: commit: more color clarification
f34388b HEAD@{6}: commit: expand on color support
9962aed HEAD@{7}: commit: a git editor -> the Git editor
برای دیدن مثال دیگری از دسترسی مشترک به reflog، از Rewriting History Page دیدن کنید.
Reflog منابع
به صورت پیش فرض، git reflog، reflog منابع HEAD را به عنوان خروجی، نمایش می دهد. HEAD اشاره ای نمادین به شاخه ی جاری فعال است. reflog ها برای سایر منابع نیز موجود هستند. Syntax دسترسی به git ref، به صورت name@{qualifier} است. افزون بر منابع HEAD، سایر شاخه ها، برچسب ها، remote ها و stash Git نیز، می توانند منبع دهی شوند.
با انجام موارد زیر می توانید از همه منابع، دوباره یک reflog کامل بگیرید:
git reflog show --all
برای مشاهده ی reflog یک شاخه ی خاص، نام شاخه را در ادامه ی دستور git reflog show بیاورید:
git reflog show otherbranch 9a4491f otherbranch@{0}: commit: seperate articles into branch PRs 35aee4a otherbranch{1}: commit (initial): initial commit add git-init and setting-up-a-repo docs
اجرای این مثال، یک reflog برای شاخه ی otherbranch
را نشان می دهد. مثال زیر فرض می کند که شما قبلا با استفاده از دستور git stash برخی از تغییرها را ذخیره کرده اید.
git reflog stash 0d44de3 stash@{0}: WIP on git_reflog: c492574 flesh out intro
با این کار برای stash Git یک reflog در خروجی نشان داده می شود.
Reflog های زمان دار
به هر reflog وارد شده به سیستم، یک timestamp
متصل است. این timestamp
ها می توانند به عنوان Syntax ای برای توصیف Git ref استفاده شوند. بنابراین امکان فیلتر reflog های Git بر اساس زمان را فراهم می کند. در زیر چند نمونه توصیف کننده ی زمان، قابل استفاده در git reflog را مشاهده می کنید:
- 1.minute.ago
- 1.hour.ago
- 1.day.ago
- yesterday
- 1.week.ago
- 1.month.ago
- 1.year.ago
- 2011-05-17.09:00:00
توصیف کننده ی زمان را می توان ترکیب کرد (برای مثال 1.day.2.hours.ago)، افزون بر این، به شکل جمع نیز، می توان استفاده کرد. (برای مثال 5.minutes.ago).
ref های تعیین کننده ی زمان را می توان با سایر دستورهای git استفاده کرد.
git diff master@{0} master@{1.day.ago}
این مثال تفاوت شاخه ی master کنونی با master یک روز پیش، را مشخص می کند. اگر می خواهید تغییرهایی را که در یک بازه ی زمانی رخ داده است بدانید، این مثال بسیار مفید است.
subcommand ها و گزینه های پیکربندی
git reflog، چند ورودی اضافی را که subcommand
محسوب می شوند، می پذیرد.
Show: git reflog show
show به طور پیش فرض در دستور reflog اجرا می شود. برای مثال، دو دستور زیر با هم برابرند:
git reflog master@{0}
و
git reflog show master@{0}
افزون بر این، git reflog show نام مستعاری برای git log -g --abbrev-commit --pretty=oneline است. اجرای git reflog show، log گذشته را نشان می دهد.
Expire: git reflog expire
دستور expire ورودی های reflogقدیمی یا غیرقابل دسترس را پاک می کند. با اجرای دستور expire احتمال از دست رفتن اطلاعات وجود دارد. کاربرهای نهایی به طور معمول از این دستور استفاده نمی کنند، اما git به صورت داخلی از آن استفاده می کند. قرار دادن گزینه ی -n یا --dry-run با git reflog expire ، یک "dry run" اجرا می کند که ورودی هایی را که برای هرس مشخص شده اند، نشان می دهد؛ اما آن ها را هرس نمی کند.
به طور پیش فرض، تاریخ انقضای reflog، ۹۰ روز تنظیم شده است. زمان انقضا را می توان با قرار دادن یک ورودی expire=time--
به git reflog expire یا با تنظیم gc.reflogExpire
، در پیکربندی git تعیین کرد.
Delete: git reflog delete
دستور delete به خودی خود توضیح داده شده است و ورودی منتقل شده در reflog را حذف می کند. مانند expire، با اجرای دستور delete نیز امکان از دست رفتن داده ها وجود دارد و معمولا کاربرهای نهایی آن را فراخوانی نمی کنند.
بازیابی commit های از دست رفته
Git هرگز چیزی را از دست نمی دهد، حتی هنگام انجام کارهای بازنویسی تاریخچه، مانند rebasing
یا commit amending
. برای مثال بعدی بیایید فرض کنیم که تغییرهای جدیدی در مخزن خود ایجاد کرده ایم. git log --pretty=oneline
به صورت زیر است:
338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content 1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content c49257493a95185997c87e0bc3a9481715270086 flesh out intro eff544f986d270d7f97c77618314a06f024c7916 migrate existing content bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs
سپس تغییرهایی را commit کرده و دستور زیر را اجرا می کنیم:
#make changes to HEAD git commit -am "some WIP changes"
با اضافه کردن commit جدید، log به شکل زیر خواهد بود:
37656e19d4e4f1a9b419f57850c8f1974f871b07 some WIP changes 338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content 1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content c49257493a95185997c87e0bc3a9481715270086 flesh out intro eff544f986d270d7f97c77618314a06f024c7916 migrate existing content bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs
در این مرحله یک rebase با شاخه master به صورت زیر اجرا خواهیم کرد:
git rebase -i origin/master
هنگام اجرای rebase با وارد کردن s
(که یک subcommand برای rebase است)، commit ها را برای یکی کردن، علامت گذاری کردیم. در حین rebase، تعدادی از commit ها را با آخرین commit (با پیام “some WIP changes”)، یکی کردیم.
از آنجایی که commit ها یکی شدند، خروجی git log به صورت زیر خواهد بود:
40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs some WIP changes 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs
اگر git log را در این مرحله بررسی کنیم، به نظر می رسد که commit هایی که برای یکی کردن، علامت گذاری کردیم را دیگر نداریم.
اگر بخواهیم روی یکی از commit هایی که یکی کرده ایم، کار کنیم، چه می کنیم؟ مثلا بخواهیم تغییرهای آن را از تاریخچه حذف کنیم! وقت به کار بردن reflog است.
git reflog 37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog 37656e1 HEAD@{1}: rebase -i (start): checkout origin/master 37656e1 HEAD@{2}: commit: some WIP changes
reflog های ثبت شده برای شروع و پایان rebase را می توانیم ببینیم و قبل از آن ها، commit با پیام “some WIP changes
” وجود دارد. می توانیم منبع reflog را با git reset بیاوریم و به commit ای که قبل از rebase بود، reset کنیم.
git reset HEAD@{2}
اجرای این دستور reset، HEAD را به commit با پیام “some WIP changes
” جا به جا می کند. در اصل بقیه commit های یکی شده را بازیابی می کند.
خلاصه
در این بخش از آموزش، ما درباره دستور git reflog بحث کردیم. برخی از نکات کلیدی بیان شده عبارت اند از:
- شیوه ی مشاهده reflog برای شاخه های خاص
- شیوه ی لغو git rebase با استفاده از reflog
- شیوه ی مشخص کردن و مشاهده ی ورودی های reflog مبتنی بر زمان
به طور خلاصه اشاره کردیم که git reflog را می توان با سایر دستورهای git مانند git checkout ، git reset و git merge استفاده کرد. برای بحث بیشتر در مورد refs و reflog ، می توانید از اینجا بیشتر بیاموزید.
منبع
https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog