Mwongozo

git rebase: jinsi inavyofanya kazi, hali ya mwingiliano na kuunganisha commits

Imesasishwa: · Skillaria.Top

git rebase inahamisha commits za tawi la sasa kwenye msingi mpya: Git inaondoa commits zako kwa muda, inasogeza tawi hadi mwisho wa lile lililoteuliwa na kuzitumia tena kama commits mpya. Hivyo unapata historia ya mstari bila commits za merge, na kwa git rebase -i commits zinaweza kuunganishwa (squash), kubadilishwa jina au kufutwa; kuandika upya historia ni salama tu kwa commits ambazo bado hazijachapishwa kwa wengine.

Git rebase inafanya nini

git rebase «inahamisha» tawi lako hadi sehemu nyingine ya historia. Tuseme uliitoa feature kutoka main wiki iliyopita, na tangu hapo main imesonga mbele. Baada ya rebase tawi lako linaonekana kana kwamba umeanza kazi sasa hivi — kutoka commit mpya kabisa ya main.

git switch feature
git fetch origin
git rebase origin/main

Ndani kuna hatua tatu. Git inapata babu wa pamoja wa matawi mawili, inahifadhi mabadiliko ya kila commit yako baada yake kwa zamu, inasogeza tawi hadi origin/main, na kisha inatumia tena mabadiliko yale yaliyohifadhiwa, moja baada ya jingine. Matokeo ni commits mpya zenye maudhui na ujumbe ule ule, lakini hash tofauti.

Kabla:   A---B---C---F---G   main
                  \
                   D---E     feature

Baada:   A---B---C---F---G   main
                          \
                           D'---E'   feature

Alama ya kistari kwenye D' na E' si pambo. Hizi ni vitu vingine vyenye hash tofauti, na vina mzazi tofauti. Kutoka hapo kunatokea kanuni kuu ya rebase, ambayo iko hapa chini.

Kanuni ya dhahabu: usiweke upya kilichochapishwa

Rebase inaandika upya historia. Ikiwa commits ni zako pekee, hilo ni salama. Lakini ukiwa tawi limepakuliwa na wenzako, baada ya rebase watakuwa na D na E za zamani, wewe una D' na E' mpya, na pull ijayo itafanya historia kurudiwa mara mbili, na conflicts zitatatuliwa tena.

Kanuni ya vitendo: rebase inatumika kwenye matawi yako ya ndani na kwenye matawi binafsi ya feature ambayo mtu mmoja anafanyia kazi. Matawi ya pamoja — main, develop, na matawi ya release — hayawekwi upya kamwe.

Jinsi ya kutuma tawi baada ya rebase

Ikiwa tawi tayari lilikuwa kwenye seva, push ya kawaida itakataliwa: historia ya ndani haiendelei tena ile ya mbali. Unahitaji force push, na toleo lake salama:

git push --force-with-lease

Tofauti na --force, bendera --force-with-lease inakataa kuandika juu ya tawi ikiwa kwenye seva kuna commits ambazo hukuziona. Kwa njia hii hutafuta kazi ya mtu mwingine kwa bahati mbaya.

Conflicts wakati wa rebase

Kwa kuwa commits zinatumika moja moja, conflict inaweza kutokea kwenye commit yoyote — na hata mara kadhaa mfululizo. Git inasimama na kukujulisha ni commit ipi imeshindwa kutumika.

$ git rebase origin/main
Auto-merging src/api.js
CONFLICT (content): Merge conflict in src/api.js
error: could not apply 4e1f9a2... Ongeza akiba ya maombi
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".

Hatua za kufuata:

  1. Fungua faili lenye conflict, chagua toleo sahihi, na ondoa alama <<<<<<<, =======, >>>>>>>.
  2. Weka alama kwamba faili limetatuliwa: git add src/api.js. Hakuna haja ya commit.
  3. Endelea: git rebase --continue. Git itatumia commit inayofuata.

Amri nyingine za kudhibiti mchakato:

AmriInafanya nini
git rebase --continueKuendelea baada ya kutatua conflict
git rebase --skipKuruka commit ya sasa kabisa (mabadiliko yake yanapotea)
git rebase --abortKusimamisha rebase na kurudisha tawi kwenye hali yake ya awali

Angalia mchanganyiko wa upande «wetu» na «wao». Wakati wa rebase, HEAD ni msingi ambao unahamishia tawi, na mabadiliko «yanayoingia» ni commits zako mwenyewe. Kwa hiyo git checkout --ours wakati wa rebase inachukua toleo kutoka main, na --theirs — lako. Kwenye merge ni kinyume.

Conflicts zinazojirudia: rerere

Ukiweka upya tawi refu mara kwa mara na kutatua conflict ile ile tena na tena, washa git config --global rerere.enabled true. Git itakumbuka jinsi ulivyoitatua, na mara nyingine itatumia suluhisho lile yenyewe.

Rebase shirikishi: kupanga historia kabla ya kuchapisha

Kitu chenye thamani zaidi katika rebase ni hali ya mwingiliano. Inakuwezesha kupanga commits zako kabla ya kuziweka mbele ya wakaguzi: kuunganisha «fix», «fix typo», «fix zaidi» kuwa commit moja yenye maana, kuandika upya ujumbe, kubadilisha mpangilio, au kutupa kisichohitajika.

git rebase -i HEAD~4        # commits 4 za mwisho
git rebase -i origin/main   # commits zote za tawi ambazo hazipo kwenye main

Git itafungua kihariri chenye orodha ya commits — kutoka za zamani hadi mpya (tofauti na git log):

pick 1a2b3c4 Ongeza fomu ya kuingia
pick 5d6e7f8 fix
pick 9a0b1c2 Uthibitishaji wa barua pepe
pick 3d4e5f6 kosa la kuandika katika uthibitishaji

# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash" but keep only the previous commit's log message
# d, drop = remove commit

Badilisha neno mwanzoni mwa mstari, hifadhi na funga kihariri — Git itatekeleza mpango kutoka juu kwenda chini.

AmriAthari
pickKuacha commit kama ilivyo
rewordKuacha mabadiliko, lakini kuandika upya ujumbe
editKusimama kwenye commit ili kubadilisha yaliyomo (git commit --amend) au kuigawa kwa commits kadhaa
squashKuiingiza kwenye commit iliyotangulia, ujumbe wao unaunganishwa na kuhaririwa
fixupKuiingiza kwenye commit iliyotangulia, ujumbe wa commit hii unatupwa
dropKufuta commit pamoja na mabadiliko yake

Kubadilisha mpangilio wa mistari kunabadilisha mpangilio wa commits, na kufuta mstari kunalingana na drop.

Git squash: kuunganisha commits kuwa moja

Hakuna amri tofauti ya git squash kwenye Git. Kuunganisha commits (squash) kunawezekana kwa njia tatu, na rebase shirikishi ndiyo yenye unyumbufu zaidi.

Njia ya 1. Rebase shirikishi

Kwa mfano hapo juu, tugeuze commits nne kuwa mbili nadhifu:

pick 1a2b3c4 Ongeza fomu ya kuingia
fixup 5d6e7f8 fix
pick 9a0b1c2 Uthibitishaji wa barua pepe
fixup 3d4e5f6 kosa la kuandika katika uthibitishaji

Commit ya kwanza katika kundi lazima ibaki pick: squash na fixup zinaingiza commit kwenye iliyotangulia, na ya kwanza kabisa haina iliyotangulia ya kuingizwa.

Njia ya 2. fixup-commits na autosquash

Ikiwa tayari unajua commit gani unarekebisha, unda marekebisho yakiwa yamewekwa alama tangu mwanzo:

git commit --fixup=1a2b3c4
git rebase -i --autosquash origin/main

Git itaweka fixup-commit chini ya ile sahihi na kuiweka alama kama fixup — unabaki tu kuhifadhi mpango. Tabia hii unaweza kuiwasha kwa chaguo-msingi kwa git config --global rebase.autoSquash true.

Njia ya 3. Kubana tawi zima kuwa commit moja

git reset --soft $(git merge-base HEAD origin/main)
git commit -m "Kuingia kwa barua pepe na uthibitishaji"

reset --soft inarudisha kielekezi cha tawi hadi mahali pa kutengana, lakini inabakiza mabadiliko yote kwenye index — unabaki kufanya commit moja. Chaguo jingine ni git merge --squash wakati wa kuunganisha kwenye tawi kuu, au kitufe «Squash and merge» kwenye pull request.

Chaguo muhimu za rebase

git pull --rebase

Pull ya kawaida inaunganisha tawi la mbali kwenye lako na kuunda commit ya merge ikiwa ulikuwa unafanya commits sambamba na wenzako. git pull --rebase badala yake inapanga upya commits zako za ndani juu ya zile mpya kutoka mbali. Kuiweka kama tabia ya chaguo-msingi: git config --global pull.rebase true. Huu ndio ukanda salama wa rebase — commits zako za ndani bado hazijaonwa na mtu yeyote.

--onto: kuhamisha sehemu ya tawi

Uliitoa feature-b kutoka feature-a, na sasa unataka feature-b itoke moja kwa moja kwenye main, bila commits za feature-a:

git rebase --onto main feature-a feature-b

Inasomeka hivi: chukua commits za feature-b ambazo hazipo kwenye feature-a, na uzipandikize kwenye main.

--exec: kukagua kila commit

git rebase -i --exec "npm test" origin/main

Baada ya kila commit kutumika, majaribio yanaendeshwa; yakianguka, rebase inasimama kwenye commit yenye tatizo. Ni muhimu pale ambapo kila commit ya historia inapaswa kujengwa.

--update-refs: rundo la matawi yanayotegemeana

Ukiwa na mnyororo wa matawi yanayotegemeana, bendera --update-refs (Git 2.38+) inapohamisha tawi la juu inasogeza pia la kati.

Jinsi ya kughairi rebase

Ikiwa mchakato bado unaendelea — git rebase --abort. Rebase ikishakamilika na matokeo hayakufurahisha, commits za zamani hazijapotea: zinakumbukwa na jarida la marejeo.

$ git reflog
e5f6a7b HEAD@{0}: rebase (finish): returning to refs/heads/feature
e5f6a7b HEAD@{1}: rebase (pick): Uthibitishaji wa barua pepe
...
c3d4e5f HEAD@{5}: commit: kosa la kuandika katika uthibitishaji

$ git reset --hard HEAD@{5}

Tafuta kwenye git reflog kiingilio kilichotangulia mwanzo wa rebase, kisha weka upya tawi kwake. Mara baada ya rebase pia kuna njia fupi: git reset --hard ORIG_HEAD. Reflog inahifadhiwa kwenye kompyuta yako na kwa chaguo-msingi inashikilia takriban siku 90, kwa hiyo hakuna haja ya kuogopa baada ya rebase iliyoshindwa.

Makosa ya kawaida

  • Umeweka upya tawi la pamoja na kufanya force push — historia ya wenzako imevurugika. Suluhisho: kukubaliana, kurejesha tawi kutoka reflog ya mtu aliye na toleo sahihi, na kuzuia force push kwenye matawi yaliyolindwa kwenye seva.
  • Kutumia --force badala ya --force-with-lease — na kufuta commit ambayo mwenzako alikuwa ameitumia kwenye tawi hilo hilo.
  • Squash kwenye mstari wa kwanza wa mpango wa mwingiliano — Git itajibu kwa hitilafu «cannot 'squash' without a previous commit».
  • Kuanza rebase ukiwa na saraka chafu. Git itakataa kuanza. Weka commit kwa mabadiliko yako, yaweke kwenye git stash, au tumia git rebase --autostash.
  • Kutatua conflict kisha kufanya git commit badala ya git rebase --continue. Itatokea commit ya ziada; baada ya --continue unaweza kuiondoa kwa rebase shirikishi nyingine.

Muhtasari

git rebase inahamisha commits zako kwenye msingi mpya na kuziunda upya, hivyo historia inabaki mstari mmoja na safi. Hali ya mwingiliano inageuza rasimu kuwa historia nadhifu: squash na fixup zinaunganisha marekebisho, reword inarekebisha ujumbe, drop inaondoa kisichohitajika. Kanuni kuu ni moja — weka upya tu kile ambacho bado hujakichapisha kwa wengine, na baada ya kuweka upya tawi lako la mbali litume kwa --force-with-lease. Kazi na rebase na usafishaji wa historia ya commits vinafanyiwa mazoezi ya vitendo katika kozi ya Git.

Maswali ya mara kwa mara

Je, git rebase inabadilisha maudhui ya msimbo?

Ikiwa hakuna conflicts, maudhui ya mwisho ya faili yatakuwa sawa na ya merge, lakini commits zenyewe zinaundwa upya na hash mpya na wazazi wapya. Ikiwa wakati wa conflict ulichagua chaguo tofauti, commits za kati zitatofautiana na za asili.

Nawezaje kuweka upya tawi juu ya commit ya kwanza kabisa ya hifadhi?

Tumia git rebase -i --root: mpango utajumuisha commits zote, pamoja na ile ya mizizi. Hili linahitajika mara chache, kwa mfano kubadilisha ujumbe wa commit ya kwanza kabisa.

Je, rebase inahifadhi mwandishi na tarehe za commits?

Mwandishi na tarehe ya uandishi vinabaki, lakini committer na tarehe ya commit zinabadilika kuwa za sasa. Bendera --committer-date-is-author-date inaweka tarehe ya commit sawa na tarehe ya uandishi.

Je, inawezekana kuweka upya commits za merge?

Kwa chaguo-msingi rebase inanyoosha historia na kuondoa commits za merge. Ili kuhifadhi muundo wa muunganisho, tumia git rebase --rebase-merges.

Nitajuaje kwamba rebase inaendelea sasa hivi?

git status itaonyesha mstari interactive rebase in progress au You are currently rebasing, na kueleza amri zinazopatikana. Shell nyingi na IDE pia zinaonyesha hali hii kwenye kidokezo.

Jifunze mada hii kwa video

Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.

Nenda kwenye kozi