Git merge dhidi ya rebase: kipi cha kuchagua kwa timu yako
Merge na rebase zote zinaunganisha mabadiliko ya matawi, lakini zinatofautiana katika kushughulikia historia: merge inaihifadhi kama ilivyo na kuongeza commit ya muunganisho, rebase inaandika upya commits zako juu ya msingi mpya na kufanya historia kuwa mstari mmoja. Kanuni ya vitendo: rebase kwa kupanga commits zako ambazo hazijatumwa, merge kwa kuingiza kazi iliyokamilika kwenye matawi ya pamoja.
Kwa ufupi: tofauti kati ya merge na rebase
Mjadala wa «merge vs rebase» kwa kweli si kuhusu amri ipi ni bora, bali ni historia gani ya mradi unataka kuiona. Amri zote mbili zinafikia msimbo uleule mwishoni. Tofauti iko kwenye njia inayoandikwa kwenye jarida.
- Merge inaunganisha mistari miwili ya historia na kurekodi kwa uaminifu kwamba kazi ilifanyika sambamba. Commits zilizopo hazibadiliki, na commit mpya ya muunganisho yenye wazazi wawili inaongezwa.
- Rebase inaandika upya commits zako kana kwamba ulianza kazi kutoka toleo jipya kabisa la tawi la msingi. Historia inaonekana kama mstari ulionyooka, lakini commits zinapata hash mpya.
Mbinu ya kila amri — bendera, usuluhishaji wa conflicts, hali ya mwingiliano — tumeifafanua katika makala tofauti. Hapa ni uchaguzi wa mkakati tu.
Historia inaonekanaje katika hali zote mbili
Hali ya kuanzia: uliitoa feature, ukafanya commits mbili, na kwenye main zimeongezwa commits mbili za wengine.
D---E feature
/
A---B---C---F---G main
Baada ya git merge feature kwenye main:
D---E
/ \
A---B---C---F---G---M main
Baada ya git rebase main kwenye feature na kusogeza main:
A---B---C---F---G---D'---E' main
Katika kesi ya kwanza historia inaonyesha kwamba kipengele kilitengenezwa sambamba na lini kiliingizwa. Katika ya pili historia inasomeka kama simulizi la mfululizo, lakini ukweli wa kazi sambamba haupo tena: D' na E' ni commits mpya zilizoundwa wakati wa rebase.
Jedwali la ulinganisho wa merge na rebase
| Kigezo | git merge | git rebase |
|---|---|---|
| Commits zilizopo | Hazibadiliki | Zinaundwa upya na hash mpya |
| Umbo la historia | Grafu yenye matawi na commits za merge | Mstari mmoja |
| Usalama kwa matawi ya pamoja | Salama daima | Hatari kwa commits zilizotumwa |
| Je, force push inahitajika | Hapana | Ndiyo, ikiwa tawi tayari liko kwenye seva |
| Conflicts | Zinasuluhishwa mara moja, kwenye commit ya merge | Zinaweza kujitokeza kwenye kila commit inayohamishwa |
| Muktadha wa «imetoka wapi» | Unabaki | Unapotea |
| Kughairi kipengele kizima | Revert moja ya git revert -m 1 kwenye commit ya merge | Revert ya kila commit au safu |
Urahisi wa git bisect na git log | Grafu ngumu zaidi kusoma | Rahisi zaidi: mstari mmoja |
| Kizingiti cha kuanzia | Chini | Juu zaidi, unahitaji kuelewa kuandika upya historia |
| Kupanga commits (squash, reword) | Ni --squash ya tawi zima pekee | Inanyumbulika kupitia rebase -i |
Faida na hasara za merge
Faida
- Haivunji historia. Kila kilichochapishwa kinabaki pale kilipo. Wenzako hawalazimiki kurekebisha chochote baada ya kitendo chako.
- Conflict inasuluhishwa mara moja. Hata kama tawi lina commits 30, unashughulika na hali ya mwisho, si kila hatua.
- Muktadha unahifadhiwa. Kwa commit ya merge unaona kazi gani iliingia kwenye tawi kuu lini, na unaweza kuiondoa yote kwa mara moja.
Hasara
- Grafu yenye kelele. Kwa usawazishaji wa mara kwa mara historia inajaa commits za «Merge branch 'main' into feature», na
git log --graphinaanza kufanana na ramani ya reli. - Commits za rasimu zinaingia kwenye historia. «wip», «fix», «fix zaidi» zinabaki milele kwenye tawi kuu usipozibana.
Faida na hasara za rebase
Faida
- Historia ya mstari, inayosomeka. Kila commit iko mahali pake,
git loginasomeka kama orodha ya mabadiliko, nagit bisectinapata commit yenye hitilafu kwa urahisi zaidi. - Uwezo wa kupanga commits kabla ya ukaguzi: kuziunganisha, kubadilisha majina, kuzipanga upya.
- Hakuna commits za merge za kiufundi kutokana na usawazishaji na tawi kuu.
Hasara
- Inaandika upya historia. Rebase ya tawi la pamoja lililochapishwa inavunja kazi ya kila aliyeliclone.
- Inahitaji force push kwa matawi kwenye seva, kwa hiyo unahitaji nidhamu na
--force-with-lease. - Conflicts zinazojirudia. Eneo lile lile linaweza kugongana kwenye commits kadhaa mfululizo.
- Commits za kati zinaweza zisijengwe. Baada ya kuhamishwa kwenye msingi mpya, hakuna aliyezijaribu katika mazingira hayo mapya.
Lini kutumia nini
Rebase — kwa kazi yako ya ndani
Unasasisha tawi lako kabla ya kulituma — git pull --rebase. Unaandaa tawi kwa ukaguzi na unataka kuondoa commits za rasimu — git rebase -i. Tawi lako binafsi la feature limepitwa na main — git rebase origin/main. Katika hali zote hizi zinaandikwa upya commits ambazo ni wewe pekee uliziona (au ni zako pekee).
Merge — kwa matawi ya pamoja na kuunganisha
Kipengele kilichokamilika kinaingizwa kwenye main au develop. Tawi linafanyiwa kazi na watu kadhaa. Tawi la release linarudishwa kwenye tawi kuu. Hapa jambo muhimu ni kutogusa commits zilizochapishwa, na merge ndiyo chaguo sahihi pekee.
Kanuni rahisi ya kuchagua
Ikiwa commits ni zako pekee — unaweza rebase. Ikiwa mtu tayari amezipakua — merge pekee.
Mipango ya kawaida kwa timu
| Mpango | Unavyofanya kazi | Unafaa kwa nani |
|---|---|---|
| Merge pekee | Vipengele vinaingizwa kwa --no-ff, usawazishaji kwa git merge main | Wanaoanza Git, timu zinazothamini historia kamili na kughairi rahisi |
| Rebase + merge | Tawi linapangwa upya juu ya main kabla ya kuingizwa, kisha commit ya merge yenye --no-ff | Timu zinazohitaji historia nadhifu na mipaka ya vipengele pia |
| Rebase + fast-forward | Tawi linapangwa upya na kuingizwa kwa kusogeza, historia yote ni mstari | Timu ndogo zenye commits nadhifu za atomiki |
| Squash merge | Kila pull request inageuka kuwa commit moja kwenye main | Timu zenye kazi fupi ambapo historia ya kina ya tawi haihitajiki |
Kwenye GitHub na GitLab mipango hii inalingana na vitufe «Create a merge commit», «Rebase and merge» na «Squash and merge». Ni vizuri kuruhusu chaguo moja tu kwenye mipangilio ya hifadhi, ili historia isigeuke mchanganyiko wa mitindo.
Mipangilio inayolinda chaguo lako
# pull bila commits za merge zisizo za lazima
git config --global pull.rebase true
# au: pull kwa kusogeza tu, vinginevyo hitilafu — unaamua mwenyewe
git config --global pull.ff only
# daima commit ya merge wakati wa kuunganisha vipengele
git config --global merge.ff false
Kuwa makini na merge.ff false: inaathiri pia git pull katika hali ya merge. Wengi hawaiweki kimataifa, badala yake wanaandika --no-ff waziwazi wanapounganisha kipengele.
Mfano: kazi moja kwa mitindo miwili
Hebu tuchukue hali halisi. Kwa siku tatu unafanya kazi ya malipo kwenye tawi feature/payment, na wakati huo kwenye main zimeunganishwa kazi tano za wengine. Kabla ya pull request unahitaji kuvuta main mpya na kuhakiki kwamba kila kitu kinafanya kazi.
Chaguo la merge
git switch feature/payment
git fetch origin
git merge origin/main
# suluhisha conflicts mara moja, git add, git commit
git push
Tawi linapata commit «Merge remote-tracking branch 'origin/main' into feature/payment». Push inapita kawaida, na wenzako waliokuwa wakiangalia tawi hawaoni tofauti yoyote. Ukijisawazisha hivi kila siku, tawi litakuwa na commits tatu za aina hiyo, na zitaingia kwenye main pamoja na kipengele, ikiwa unaunganisha bila squash.
Chaguo la rebase
git switch feature/payment
git fetch origin
git rebase origin/main
# conflicts zinasuluhishwa njiani, kwenye kila commit: git add, git rebase --continue
git rebase -i origin/main # kwa hiari: kuunganisha commits za rasimu
git push --force-with-lease
Tawi linaonekana kana kwamba limeanzishwa asubuhi ya leo kutoka main mpya, hakuna commits za ziada, na mkaguzi anasoma mabadiliko hatua kwa hatua kwa urahisi zaidi. Gharama yake ni force push, na kuhakikisha hakuna mtu mwingine anayeongeza commits kwenye tawi hilo.
Main itaona nini hatimaye
Pull request inapoingizwa, tofauti inabaki. Mtindo wa merge unatoa grafu yenye matawi na muunganisho wa usawazishaji, na mtindo wa rebase unatoa mnyororo nadhifu wa commits za kipengele, ambao unaweza kuingizwa kwa kusogeza au kwa commit moja ya merge. Msimbo utakuwa uleule ikiwa conflicts zimesuluhishwa kwa njia ile ile.
Jinsi ya kufanya uamuzi kwenye timu
Jibu maswali machache. Je, watu kadhaa wanafanya kazi kwenye tawi moja? Ikiwa ndiyo, rebase kwa tawi hilo imeondolewa. Timu ina uzoefu kiasi gani na Git? Ikiwa wanaoanza ni wengi, anza na merge na squash merge — zinasamehe makosa. Je, historia kamili inahitajika kwa ukaguzi na uchambuzi wa matukio? Basi commits za merge za vipengele zina manufaa. Je, git log inayosomeka na git bisect ya mara kwa mara ni muhimu? Basi upande wa rebase na historia ya mstari ni bora.
Andika uamuzi kwenye CONTRIBUTING au README ya hifadhi, na washa ulinzi wa tawi kuu: marufuku ya force push, pull request ya lazima, njia iliyoruhusiwa ya kuunganisha. Kanuni iliyowekwa kwenye mipangilio inafanya kazi kwa uhakika zaidi kuliko makubaliano ya maneno.
Dhana potofu za kawaida
- «Rebase ni ya hali ya juu, merge ni kwa wanaoanza». Hapana: ni zana tofauti kwa kazi tofauti. Wasanidi wenye uzoefu wanatumia zote mbili.
- «Commits za merge ni takataka». Za usawazishaji — ndiyo, mara nyingi ni kelele. Lakini commit ya merge ya kuingiza kipengele ni alama muhimu: kwayo kazi nzima inaonekana na inaweza kughairiwa.
- «Baada ya rebase conflicts ni chache». Conflicts ni zile zile, kwa sababu mistari ile ile inabadilika. Rebase inazigawanya kwa commits, merge inazitatua mara moja.
- «Rebase inapoteza commits». Commits za zamani zinabaki kwenye
git reflogna zinaweza kurejeshwa, hadi zitakapofutwa na garbage collection.
Muhtasari
Kuchagua kati ya merge na rebase ni kuchagua kati ya historia ya uaminifu na historia ya mstari inayosomeka. Merge ni salama na inahifadhi muktadha, rebase inatoa usafi lakini inaandika upya commits. Mazoezi yenye uhakika zaidi ni kuchanganya: panga na safisha tawi lako wakati bado ni lako, na ingiza kazi iliyokamilika kwenye matawi ya pamoja kwa merge au squash kulingana na kanuni za timu. Jambo kuu ni kukubaliana juu ya mpango na kuufunga kwenye mipangilio ya hifadhi. Mikakati yote miwili na kazi ya matawi kwenye timu vinafanyiwa mazoezi ya vitendo katika kozi ya Git.
Maswali ya mara kwa mara
Je, kwa git pull ni bora merge au rebase?
Kwa kusasisha tawi la ndani, rebase ni rahisi zaidi: commits zako ambazo hazijachapishwa zinakaa juu ya zile mpya kutoka seva bila commit ya ziada ya merge. Inawezeshwa kwa git config --global pull.rebase true.
Je, inaruhusiwa kuchanganya merge na rebase kwenye mradi mmoja?
Ndiyo, na hii ndiyo njia inayotumika zaidi: rebase kwa matawi yako, merge kwa yale ya pamoja. Jambo muhimu ni kwamba kanuni ijulikane kwa timu nzima.
Mwanzoni nichague nini?
Anza na merge: haiandiki upya historia, na ni vigumu zaidi kuvunja kitu. Jifunze rebase kwenye matawi yako ya ndani, pale utakapoelewa reflog na force push.
Je, mkakati unaathiri msimbo wa mwisho?
Hapana, kwa utatuzi uleule wa conflicts hali ya mwisho ya faili ni sawa. Kinachotofautiana ni historia ya commits iliyoandikwa.
Squash merge inatofautianaje na rebase?
Squash merge inabana tawi zima kuwa commit mpya moja kwenye tawi kuu, wakati rebase inahamisha kila commit kivyake. Zote mbili zinatoa historia ya mstari, lakini squash inapoteza maelezo ya kila hatua.
Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.
- Michakato ya Git katika Timu za Kweli: Njia gani ya kuchagua
- Zana za Kina: Rebase, Stash, Cherry-Pick na Lebo