git reflog: jinsi ya kurejesha commits na matawi yaliyopotea
git reflog ni jarida la ndani ambapo Git inarekodi kila mwendo wa HEAD na matawi: commits, reset, checkout, rebase, merge. Tafuta kwenye git reflog ingizo kabla ya kosa, kwa mfano HEAD@{2}, kisha rudisha hali kwa git reset --hard HEAD@{2} au tengeneza tawi git branch rescue HEAD@{2}.
git reflog ni jarida la marejeo (reference log): Git inaandika ndani yake kila mwendo wa HEAD na ncha za matawi. Umefanya commit, umebadili tawi, umetekeleza reset, rebase au merge — kwenye reflog kunaongezwa mstari wenye hash ya commit ambayo kielekezi kilielekeza baada ya operesheni. Kwa hiyo hata commit ambayo hakuna tawi linayoielekeza tena inaweza kupatikana na kurejeshwa.
Jambo kuu la kujua: reflog ni ya ndani. Ipo tu kwenye clone yako, haitumwi kwenye seva wala haiji wakati wa git clone. Lakini kwenye hifadhi yako inaokoa karibu kila kosa linalohusu historia.
Jinsi ya kusoma matokeo ya git reflog
git reflog
3c4d5e6 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~2
9a8b7c6 HEAD@{1}: commit: Ongeza uthibitishaji wa barua pepe
1f2e3d4 HEAD@{2}: commit: Hamisha usanidi kwenye faili tofauti
3c4d5e6 (HEAD -> main) HEAD@{3}: checkout: moving from feature to main
7b6a5c4 (feature) HEAD@{4}: commit: Rasimu ya fomu ya kuingia
Kila mstari ni hali moja ya HEAD, ya hivi karibuni juu kabisa:
- hash — commit ambayo HEAD ilielekeza baada ya operesheni;
- HEAD@{n} — «HEAD ilikuwa wapi miendo n nyuma»; ni rejeo kamili, na unaweza kulipitisha kwenye amri yoyote;
- maelezo — aina ya operesheni (commit, reset, checkout, rebase, merge, pull, cherry-pick, commit (amend)) na maelezo yake.
Mfano unaonyesha: commits mbili — «Hamisha usanidi» na «Ongeza uthibitishaji» — zilifanywa, kisha reset HEAD~2 ilirudisha tawi nyuma. Kwenye git log hazipo tena, lakini kwenye reflog zipo.
Reflog ya tawi fulani
Kila tawi lina jarida lake. Ni fupi na lenye manufaa zaidi unapokuwa umebadilisha matawi mara nyingi:
git reflog show feature
git reflog show origin/main # tawi la mbali lilivyobadilika wakati wa fetch
Rejeo kwa muda
Badala ya namba unaweza kutaja wakati — Git itapata ilipoelekeza rejeo wakati huo:
git show main@{yesterday}
git diff main@{"2 hours ago"} main
git log -g --since="1 day ago" --oneline
Bendera -g (--walk-reflogs) ya git log inapitia reflog badala ya uhusiano wa wazazi, na inaruhusu muundo na vichujio vilevile. Kuonyesha tarehe, tumia git reflog --date=iso.
Jinsi ya kurejesha commits baada ya git reset --hard
Hali ya kawaida zaidi: umetekeleza git reset --hard kwenye commit isiyo sahihi, na kazi «imepotea». Commits hazijaenda popote — hazionekani tu kutoka kwenye matawi.
- Fungua jarida:
git reflog. - Tafuta mstari ulio juu kabisa ya
reset: moving to ...— hiyo ndiyo hali kabla ya kosa. Kwenye mfano hapo juu niHEAD@{1}yenye hash9a8b7c6. - Hakiki kwamba ndiyo sahihi:
git log --oneline -5 HEAD@{1}. - Rudisha tawi:
git reset --hard HEAD@{1}.
git reset --hard HEAD@{1}
HEAD is now at 9a8b7c6 Ongeza uthibitishaji wa barua pepe
Kuwa makini: baada ya kila operesheni namba zinasogea. Kile kilichokuwa HEAD@{1} kitakuwa HEAD@{2} baada ya reset. Kwa hiyo ni salama zaidi kunakili hash badala ya namba.
Kikwazo muhimu: reflog inahifadhi tu yaliyowekwa commit. Mabadiliko ambayo hayajawekwa commit, yaliyofutwa na reset --hard au git checkout -- faili, hayawezi kurejeshwa kupitia reflog. Bado kuna matumaini kidogo ikiwa faili yaliongezwa kwenye index — tazama hapa chini.
Jinsi ya kurejesha tawi lililofutwa
Umefuta tawi kwa git branch -D feature, na lilikuwa na commits ambazo hazijatumwa. Jarida la tawi lenyewe linafutwa pamoja nalo, lakini jarida la HEAD linabaki — na HEAD ilikuwa juu ya commits zake ulipokuwa ukifanya kazi humo.
git reflog | grep feature
7b6a5c4 HEAD@{4}: commit: Rasimu ya fomu ya kuingia
3c4d5e6 HEAD@{3}: checkout: moving from feature to main
# Commit ya mwisho ya tawi — ile ambayo ulihama kutoka kwake
git branch feature 7b6a5c4
Tafuta mstari wa checkout: moving from feature to ...: hash ya ingizo lililo chini yake (la zamani zaidi) ndiyo hali ya mwisho ya tawi. Kwa njia, Git inapofuta tawi inachapisha hash yenyewe: Deleted branch feature (was 7b6a5c4). — ikiwa terminal bado iko wazi, inatosha kuinakili.
Jinsi ya kughairi rebase iliyoshindwa
Rebase inaandika upya commits, na ikiwa wakati wa mchakato utasuluhisha conflicts vibaya, matokeo yanaweza kuwa mabaya kuliko ya awali. Reflog inahifadhi hali kabla ya rebase kuanza.
git reflog
e1f2a3b HEAD@{0}: rebase (finish): returning to refs/heads/feature
e1f2a3b HEAD@{1}: rebase (pick): Rasimu ya fomu ya kuingia
c4d5e6f HEAD@{2}: rebase (start): checkout main
7b6a5c4 HEAD@{3}: commit: Rasimu ya fomu ya kuingia
git reset --hard HEAD@{3}
Unahitaji ingizo lililotangulia rebase (start). Kuna pia njia fupi: kabla ya operesheni hatari (rebase, merge, reset) Git inahifadhi nafasi ya awali kwenye rejeo ORIG_HEAD, kwa hiyo mara baada ya rebase git reset --hard ORIG_HEAD itafanya kazi. Lakini ORIG_HEAD inaandikwa upya na operesheni ijayo ya aina hiyo, wakati reflog inahifadhi historia nzima.
Jinsi ya kurudisha commit kabla ya git commit --amend
--amend haibadilishi commit, bali inaunda mpya mahali pake. Ya zamani inabaki kwenye reflog:
git reflog
5a6b7c8 HEAD@{0}: commit (amend): Ongeza uthibitishaji wa barua pepe
9a8b7c6 HEAD@{1}: commit: Ongeza uthibitishaji wa barua pepe
git diff HEAD@{1} HEAD # amend ilibadilisha nini
git reset --soft HEAD@{1} # rudisha commit ya zamani, mabadiliko ya amend yanabaki kwenye index
Urejeshaji salama: tawi badala ya reset
Usipokuwa na uhakika ni commit ipi unayohitaji, usifanye reset --hard kipofu. Tengeneza tawi la uokoaji — halivunji chochote na linalinda commit uliyoipata isifutwe:
git branch rescue HEAD@{5}
git log --oneline rescue
git switch rescue
Baadaye commits za rescue unaweza kuzihamisha kwa cherry-pick au kuziunganisha, na kufuta tawi hilo mara kila kitu kitakapokuwa mahali pake.
Reflog inahifadhiwa kwa muda gani
Ingizo za reflog si za milele. Zinasafishwa na git gc, ambayo Git huiendesha yenyewe mara kwa mara. Muda unawekwa na mipangilio:
| Mpangilio | Chaguo-msingi | Maana yake |
|---|---|---|
gc.reflogExpire | siku 90 | Muda wa ingizo zenye commits zinazofikiwa kutoka matawi ya sasa |
gc.reflogExpireUnreachable | siku 30 | Muda wa ingizo zenye commits zisizofikiwa kutoka tawi lolote — yaani zile «zilizopotea» |
gc.pruneExpire | wiki 2 | Baada ya muda gani vitu visivyofikika ambavyo hakuna kinachoviashiria tena vinafutwa |
Hitimisho la vitendo: commit iliyopotea inapatikana kwa uhakika kupitia reflog kwa karibu mwezi mmoja. Usicheleweshe urejeshaji wala usiendeshe kwa mkono git gc --prune=now au git reflog expire --expire=now --all kabla hujarudisha kile unachohitaji.
Reflog isipoweza kusaidia: git fsck
Kuna hali ambapo commit haipo kwenye reflog: kwa mfano iliundwa na git stash, kisha stash ikafutwa kwa git stash drop, au mabadiliko yalikuwa kwenye index tu. Basi tafuta vitu «vinavyoelea» (dangling):
git fsck --lost-found
dangling commit 2b3c4d5e6f...
dangling blob 8e9f0a1b2c...
git show 2b3c4d5e6f # angalia yaliyomo
git branch recovered 2b3c4d5e6f
Commits zinazoelea kutoka stash iliyofutwa zina ujumbe «WIP on ...». Blobs zinazoelea ni yaliyomo ya faili ambayo zamani yaliongezwa kwa git add, lakini hayakuwekwa commit. Hazina jina la faili, kwa hiyo utatambua kwa yaliyomo, lakini kwa njia hii wakati mwingine unaweza kuokoa kazi baada ya reset --hard. Kwa bendera --lost-found Git pia inavinakili kwenye .git/lost-found/.
Ambacho reflog haiwezi kufanya
- Haifanyi kazi kati ya kompyuta. Mwenzako akifanya force push na kufuta commits zako kwenye seva, zitafute kwenye reflog ya aliyekuwa nazo kwenye kompyuta yake — kwa mfano
git reflog show origin/mainkwa yeyote aliyefanya fetch kabla ya kufutwa. - Haioni yasiyowekwa commit. Kwa hiyo bima bora kabla ya operesheni hatari ni commit au
git stash. - Haihifadhi historia milele. Muda ni kama ulivyoelezwa hapo juu, na clone mpya inaanza na jarida tupu.
Mazoezi: bima kabla ya operesheni hatari
Reflog inaokoa, lakini kurejesha kwa njia hiyo kunahitaji umakini: lazima upate ingizo sahihi kati ya dazeni za zinazofanana. Ni rahisi zaidi kuweka alama mapema. Kabla ya rebase, reset kubwa au majaribio ya historia, tengeneza tawi la muda au tagi:
git branch backup/before-rebase
git rebase -i main
# kuna kitu kilienda vibaya
git reset --hard backup/before-rebase
# kila kitu kimefanikiwa
git branch -D backup/before-rebase
Hii inachukua amri moja na inaokoa kutafuta hash. Reflog inabaki kama mpango wa akiba kwa wakati ambapo tulikumbuka bima hiyo kuchelewa.
Jinsi ya kupata ingizo sahihi kwa haraka
Kwenye jarida refu, uchujaji unasaidia. Tafuta kwa aina ya operesheni au kwa maandishi ya ujumbe wa commit, na pale ambapo una shaka angalia yaliyomo:
git reflog | grep -E "reset|rebase \(start\)"
git log -g --grep="uthibitish" --oneline
git show --stat HEAD@{7}
git log -g pamoja na --grep inatafuta kwenye ujumbe wa commits kutoka reflog, na git show --stat inaonyesha mafaili yaliyoathiriwa — kwa hayo ni rahisi kutambua commit sahihi, hata kama ujumbe wake haukuwa wa maana kama «wip».
Muhtasari
git reflog ndiyo wavu wa usalama wa Git: kila kitu kilichowekwa commit kwenye hifadhi yako katika wiki chache zilizopita kinaweza kupatikana na kurejeshwa. Mpangilio wa vitendo ni uleule kila wakati: fungua jarida, tafuta ingizo kabla ya kosa, hakiki kwa git log au git show, kisha tengeneza tawi au fanya reset --hard. Kazi na restore, reset, revert na urejeshaji baada ya makosa vinafanyiwa mazoezi ya vitendo katika kozi ya Git.
Maswali ya mara kwa mara
git reflog inatofautianaje na git log?
git log inafuata uhusiano wa wazazi wa commits na inaonyesha historia ya tawi. git reflog inaonyesha mahali HEAD na matawi yalipohamia kwenye hifadhi yako, ikijumuisha commits ambazo hazipo tena kwenye historia ya matawi.
Je, reflog inaingia kwenye GitHub au GitLab?
Hapana, reflog inahifadhiwa kwenye folda ya ndani .git/logs tu, na haitumwi wakati wa push wala clone.
Je, inawezekana kufuta reflog?
Ndiyo, kwa amri git reflog expire --expire=now --all ikifuatiwa na git gc --prune=now, lakini baada ya hapo commits zilizopotea haziwezi kurejeshwa tena.
Reflog iko wapi kimwili?
Kwenye faili za maandishi .git/logs/HEAD na .git/logs/refs/heads/jina-la-tawi, mstari mmoja kwa kila mwendo.
Je, reflog inafanya kazi kwenye hifadhi tupu (bare) ya seva?
Kwa chaguo-msingi reflog imezimwa kwenye hifadhi tupu (core.logAllRefUpdates), kwa hiyo haipaswi kutegemewa kwenye seva.
Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.
Nenda kwenye kozi