Ulinganisho

Git merge dhidi ya rebase: kipi cha kuchagua kwa timu yako

Imesasishwa: · Skillaria.Top

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

Kigezogit mergegit rebase
Commits zilizopoHazibadilikiZinaundwa upya na hash mpya
Umbo la historiaGrafu yenye matawi na commits za mergeMstari mmoja
Usalama kwa matawi ya pamojaSalama daimaHatari kwa commits zilizotumwa
Je, force push inahitajikaHapanaNdiyo, ikiwa tawi tayari liko kwenye seva
ConflictsZinasuluhishwa mara moja, kwenye commit ya mergeZinaweza kujitokeza kwenye kila commit inayohamishwa
Muktadha wa «imetoka wapi»UnabakiUnapotea
Kughairi kipengele kizimaRevert moja ya git revert -m 1 kwenye commit ya mergeRevert ya kila commit au safu
Urahisi wa git bisect na git logGrafu ngumu zaidi kusomaRahisi zaidi: mstari mmoja
Kizingiti cha kuanziaChiniJuu zaidi, unahitaji kuelewa kuandika upya historia
Kupanga commits (squash, reword)Ni --squash ya tawi zima pekeeInanyumbulika 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 --graph inaanza 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 log inasomeka kama orodha ya mabadiliko, na git bisect inapata 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

MpangoUnavyofanya kaziUnafaa kwa nani
Merge pekeeVipengele vinaingizwa kwa --no-ff, usawazishaji kwa git merge mainWanaoanza Git, timu zinazothamini historia kamili na kughairi rahisi
Rebase + mergeTawi linapangwa upya juu ya main kabla ya kuingizwa, kisha commit ya merge yenye --no-ffTimu zinazohitaji historia nadhifu na mipaka ya vipengele pia
Rebase + fast-forwardTawi linapangwa upya na kuingizwa kwa kusogeza, historia yote ni mstariTimu ndogo zenye commits nadhifu za atomiki
Squash mergeKila pull request inageuka kuwa commit moja kwenye mainTimu 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 reflog na 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.

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