git reset na git revert: jinsi ya kughairi commit bila kuvunja historia ya timu
git reset husogeza kielekezi cha tawi hadi commit nyingine na kuandika upya historia, kwa hiyo inafaa tu kwa commit za ndani ambazo bado hazijatumwa. git revert huunda commit mpya yenye mabadiliko ya kinyume na haigusi historia, kwa hiyo ndiyo njia salama ya kughairi commit ambayo tayari iko kwenye seva.
Kwa ufupi: git reset hurudisha tawi nyuma na kufanya ionekane kana kwamba commit za ziada hazikuwepo. git revert huacha historia kama ilivyo na kuongeza commit mpya inayoghairi mabadiliko ya ile ya zamani. Ya kwanza inafaa kwa kazi ya ndani, ya pili kwa kila kitu ambacho tayari kimefika kwenye hifadhi ya pamoja. Ukikumbuka kanuni hii moja tu, utaepuka ajali nyingi za Git.
Hapa chini tunaeleza jinsi amri zote mbili zinavyofanya kazi, tofauti za hali za reset, jinsi ya kughairi commit baada ya push, jinsi ya kurudisha commit zilizopotea, na nafasi ya git clean.
Sehemu tatu zinazobadilisha amri za kughairi
Ili kuelewa tofauti, kumbuka sehemu tatu za Git: folda ya kazi (faili kwenye diski), index (staging area, yaani kile kitakachoingia kwenye commit ijayo) na historia (commit ambazo tawi na HEAD vinaelekeza). Kila amri ya kughairi hufanya kazi na mchanganyiko wake wa sehemu hizi.
| Amri | Historia | Index | Folda ya kazi | Salama kwa tawi la pamoja |
|---|---|---|---|---|
git restore faili | hapana | hapana | ndiyo | ndiyo |
git restore --staged faili | hapana | ndiyo | hapana | ndiyo |
git reset --soft | ndiyo | hapana | hapana | hapana |
git reset --mixed (chaguo-msingi) | ndiyo | ndiyo | hapana | hapana |
git reset --hard | ndiyo | ndiyo | ndiyo | hapana |
git revert | huongeza commit | — | — | ndiyo |
git clean | hapana | hapana | hufuta faili zisizofuatiliwa | ndiyo, lakini hairudishiki |
Jinsi git reset inavyofanya kazi
Amri git reset <commit> husogeza kielekezi cha tawi la sasa (na HEAD pamoja nayo) hadi commit uliyoitaja. Commit zilizo "baada" yake hazifutwi kimwili, lakini hazionekani tena kwenye tawi. Hali (mode) ndiyo inayoamua kinachotokea kwenye index na faili.
git reset --soft: kughairi commit na kubaki na mabadiliko kwenye index
Tawi linasogea, lakini index na faili zinabaki zilivyo. Mabadiliko yote ya commit zilizoghairiwa yanakuwa tayari kwa commit. Hii ndiyo njia nzuri ya kuandika upya ujumbe wa commit au kuunganisha commit kadhaa za mwisho kuwa moja.
git reset --soft HEAD~3
git commit -m "feat: fomu ya usajili"
Commit tatu za mwisho zimekuwa moja, maudhui ya faili hayajabadilika.
git reset --mixed: kughairi commit na index
Hali ya chaguo-msingi: git reset HEAD~1 ni sawa na git reset --mixed HEAD~1. Tawi linasogea, index inasafishwa, lakini mabadiliko yanabaki kwenye folda ya kazi kama ambayo hayajaandaliwa. Ni rahisi unapokuwa umecommit kitu kisichohitajika na unataka kuamua upya ni nini na kwa vipande gani kiongezwe.
git reset HEAD~1
git status
# Changes not staged for commit:
# modified: app.py
# modified: config.yml
git reset --hard: kurudi kikamilifu
Tawi, index na folda ya kazi vinarudishwa kwenye hali ya commit uliyoitaja. Mabadiliko yote ambayo hayajacommitiwa kwenye faili zinazofuatiliwa yanapotea bila onyo. Hii ndiyo hali pekee ya reset inayoweza kweli kuharibu kazi yako.
git reset --hard HEAD~1 # tupa commit ya mwisho na marekebisho yote
git reset --hard origin/main # rudisha tawi kwenye hali ya seva
Kabla ya --hard, ni vizuri kutekeleza git status na git stash ikiwa kuna kitu cha thamani. Kilichocommitiwa kinaweza kurudishwa (tazama hapa chini), lakini kisichocommitiwa hakiwezi.
git reset kwa faili moja
Ukiweka njia ya faili, reset haisogezi tawi bali inabadilisha index tu: git reset app.py huondoa faili kwenye zilizoandaliwa. Mbadala wa kisasa ni git restore --staged app.py, ambao ni wazi zaidi. Bendera --soft na --hard hazifanyi kazi pamoja na njia za faili.
Jinsi git revert inavyofanya kazi
git revert <commit> hukokotoa mabadiliko ya commit uliyoitaja, huyatumia kinyume, na kuunda commit mpya. Mistari iliyoongezwa inafutwa, iliyofutwa inarudishwa. Historia inakua mbele, hakuna kilichoandikwa upya, kwa hiyo wenzako hawana haja ya kurekebisha chochote kwao.
git log --oneline
# a3f9c21 (HEAD -> main) docs: README
# 7be41d0 feat: kuhifadhi majibu kwenye cache
# 1c02e8f fix: muda wa ombi kuisha
git revert 7be41d0
# [main 5d8e2aa] Revert "feat: kuhifadhi majibu kwenye cache"
# 2 files changed, 3 insertions(+), 41 deletions(-)
Git itafungua kihariri chenye ujumbe wa aina ya Revert "..." na mstari This reverts commit 7be41d0.... Ni desturi nzuri kuongeza sababu ya kughairi.
Bendera muhimu za revert
--no-edit— kukubali ujumbe wa kawaida bila kufungua kihariri.-n(--no-commit) — kutumia mabadiliko ya kinyume kwenye index bila kuunda commit. Hivyo unaweza kughairi commit kadhaa kwa commit moja.git revert A..B— kughairi safu ya commit (kila moja kwa revert yake, kuanzia mpya hadi ya zamani).-m 1— ni lazima kwa merge commit: inaonyesha ni mzazi gani ahesabiwe kama mstari mkuu.
git revert --no-commit HEAD~3..HEAD
git commit -m "Revert: kughairi commit tatu za jaribio"
Kughairi merge commit
Muunganiko una wazazi wawili, na Git haijui ni kinyume cha upande gani cha kuhesabu, kwa hiyo bila -m itatoa kosa is a merge but no -m option was given. Kwa kawaida tawi kuu ni mzazi wa kwanza:
git revert -m 1 9f1e2ab
Tahadhari: baadaye ukitaka kuunganisha tawi lilelile tena, Git itaona commit zake tayari zimeunganishwa na haitaleta mabadiliko. Suluhisho ni kwanza kughairi revert yenyewe, kisha kuongeza marekebisho mapya.
git reset dhidi ya git revert: ipi ichague
| Kigezo | git reset | git revert |
|---|---|---|
| Inafanya nini na historia | inaiandika upya (commit zinatoweka kwenye tawi) | inaongeza commit mpya |
| Commit tayari imetumwa | inahitaji push --force, inavunja kazi ya wenzako | ni git push ya kawaida |
| Kughairi commit katikati ya historia | tu pamoja na zote zinazofuata | inawezekana kwa usahihi |
| Alama kwenye historia | hakuna inayobaki | inabaki, inaonekana nani alighairi na kwa nini |
| Hali ya kawaida | kusafisha commit za ndani kabla ya push | kughairi commit iliyovunja main |
Kanuni rahisi: ikiwa commit imeonekana na mtu mwingine zaidi yako, tumia revert; ikiwa haijaonekana, tumia reset. Kipekee ni tawi lako binafsi la feature ambalo hakuna mtu mwingine anaelitumia: humo kuandika upya historia na git push --force-with-lease kunaruhusiwa.
Kwa nini reset --hard kwenye tawi la pamoja si wazo zuri
Fikiria: umefanya git reset --hard HEAD~2 kwenye main kisha git push --force. Kwa wenzako commit hizo mbili bado zipo. Wakati wa git pull ijayo, Git itajaribu kuunganisha tawi lao na lako, na commit "zilizofutwa" zitarudi, sasa pamoja na merge commit isiyo na maana. Mbaya zaidi, ikiwa mtu alishasukuma commit zake juu yako, force push itazifuta.
Kwa hiyo kwenye matawi yaliyolindwa (main, release) force push kwa kawaida inazuiwa na mipangilio ya hifadhi. Ikiwa haiwezekani kuepuka kuandika upya, tumia git push --force-with-lease: itakataa ikiwa seva ina commit ambazo hujaziona.
Hali za kawaida za kughairi
Jinsi ya kughairi commit ya mwisho ambayo haijatumwa
git reset --soft HEAD~1 # mabadiliko yako kwenye index, unaweza kucommit upya
git reset HEAD~1 # mabadiliko kwenye faili, index tupu
git reset --hard HEAD~1 # mabadiliko yametupwa
Ikiwa unataka tu kurekebisha ujumbe au kuongeza faili uliyosahau, reset haihitajiki: tumia git add faili-uliyosahau.txt kisha git commit --amend.
Jinsi ya kughairi commit baada ya push
git revert <hash>
git push
Hili ndilo jibu la swali la kawaida "git reverse commit": hakuna amri tofauti ya git reverse kwenye Git. Commit ya "kinyume" inaundwa na git revert.
Jinsi ya kurudisha tawi kwenye hali ya seva
git fetch origin
git reset --hard origin/main
Ni muhimu tawi lako la ndani linapochanganyikiwa baada ya rebase iliyoshindikana au majaribio. Commit zote za ndani ambazo hazipo kwenye seva zitatoweka kwenye tawi.
Jinsi ya kurejesha commit baada ya reset iliyoshindikana
Git inarekodi kila mabadiliko ya HEAD kwenye jarida la reflog. Commit baada ya reset zinabaki kwenye hifadhidata ya Git angalau wiki kadhaa (kwa chaguo-msingi, ingizo lisilofikika la reflog huhifadhiwa siku 30).
git reflog
# 1c02e8f HEAD@{0}: reset: moving to HEAD~2
# a3f9c21 HEAD@{1}: commit: docs: README
# 7be41d0 HEAD@{2}: commit: feat: kuhifadhi majibu kwenye cache
git reset --hard a3f9c21 # au HEAD@{1}
Reflog ni ya ndani: inapatikana tu kwenye nakala yako ya repo na haipelekwi kwenye seva.
git clean: kufuta faili zisizofuatiliwa
git reset --hard haigusi faili ambazo Git haizifuatilii: faili mpya ambazo hazijaongezwa kwenye index, matokeo ya kujenga (build), kumbukumbu za logi. Kwa hizo kuna git clean. Amri hii hairudishiki: faili zilizofutwa nayo hazipatikani kwenye reflog wala kwenye tupio.
git clean -n # jaribio kavu: onyesha kitakachofutwa
git clean -f # futa faili zisizofuatiliwa
git clean -fd # pamoja na folda zisizofuatiliwa
git clean -fdx # pamoja na faili zilizopuuzwa (.gitignore): node_modules, dist
git clean -i # chagua kwa mkono
Bila -f, Git kwa chaguo-msingi inakataa kufanya kazi (mpangilio clean.requireForce). Anza kila mara na -n, hasa na -x: itafuta pia .env yako ya ndani ikiwa iko kwenye orodha ya kupuuzwa.
Mchanganyiko wa kusafisha kabisa hadi commit ya mwisho: git reset --hard && git clean -fd.
Makosa ya kawaida
- reset --hard badala ya --soft. Kilichocommitiwa kinaokolewa na reflog, kisichocommitiwa kimepotea. Tabia ya kufanya
git stashkabla ya majaribio inatatua tatizo. - revert bila kuelewa utegemezi. Ikiwa commit za baadaye zilibadilisha mistari ileile, revert italeta mgongano. Uhariri wake kama mgongano wa kawaida: rekebisha faili,
git add, kishagit revert --continue; ukibadili mawazo,git revert --abort. - Kuchanganya restore na reset. Ili kurudisha mabadiliko ya faili moja, hauhitaji reset ya tawi zima: tumia
git restore faili. - force push kwenye main. Ni bora revert na push ya kawaida, hata historia ikiwa ndefu kidogo.
Hitimisho
git reset ni zana ya historia yako binafsi ambayo bado haijachapishwa: --soft huhifadhi mabadiliko kwenye index, --mixed kwenye faili, --hard hutupa yote. git revert ni kughairi salama kwenye matawi ya pamoja, inayoacha alama ya kweli kwenye historia. git clean husafisha faili zisizofuatiliwa, lakini inafanya kazi bila nafasi ya kosa. Mazoezi ya kughairi kwa restore, reset na revert yanafundishwa kwa vitendo katika kozi ya Git.
Maswali ya mara kwa mara
Je, git reset hufuta commit milele?
Hapana, commit zinabaki kwenye hifadhidata ya vitu na zinapatikana kupitia git reflog, hadi mkusanyaji wa takataka (garbage collector) azifute, kwa chaguo-msingi baada ya siku 30 kwa ingizo lisilofikika.
Je, inawezekana kughairi git revert?
Ndiyo. Commit ya revert ni commit ya kawaida, unaweza kuighairi kwa git revert nyingine, au ikiwa haijatumwa, kuiondoa kwa git reset.
git reset inatofautianaje na git checkout?
git reset husogeza kielekezi cha tawi la sasa, wakati git checkout (au git switch) hubadilisha HEAD kuelekea tawi au commit nyingine bila kubadilisha tawi lenyewe.
HEAD~1 na HEAD^ zinamaanisha nini?
Zote zinamaanisha mzazi wa commit ya sasa; HEAD~3 ni babu wa tatu kupitia wazazi wa kwanza, na HEAD^2 ni mzazi wa pili wa merge commit.
Je, kughairi git clean kunawezekana?
Si kwa zana za Git: faili zisizofuatiliwa zilizofutwa hazikuwa kwenye hifadhi, kwa hiyo daima endesha <code>git clean -n</code> kwanza.
Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.
Nenda kwenye kozi