Git merge vs rebase: alin ang piliin para sa team ninyo
Pareho ang layunin ng merge at rebase na pagsamahin ang mga pagbabago ng branch, pero magkaiba ang paghawak nila sa history: pinananatili ng merge ang history gaya ng dati at nagdadagdag ng merge commit, habang muling isinusulat ng rebase ang inyong mga commit sa ibabaw ng bagong base at ginagawang tuwid ang history. Praktikal na tuntunin: rebase para ayusin ang sarili ninyong hindi pa naipapadalang commit, at merge para isama ang tapos nang trabaho sa shared branch.
Maikli: ano ang pagkakaiba ng merge at rebase
Ang debate ng "merge vs rebase" ay hindi tungkol sa kung aling command ang mas magaling, kundi kung anong history ng project ang gusto ninyong makita. Pareho silang nagbubunga ng iisang code sa huli. Ang landas na naitatala sa log ang nagkakaiba.
- Merge ay nag-uugnay ng dalawang linya ng history at tapat na nire-record na parallel ang trabaho. Hindi nagbabago ang mga umiiral na commit; nagdaragdag ito ng merge commit na may dalawang parent.
- Rebase ay muling isinusulat ang inyong mga commit na parang nagsimula kayo ng trabaho sa pinakabagong bersyon ng base branch. Tuwid ang linya ng history, pero may bagong hash ang mga commit.
Ang mekanika ng bawat command (mga flag, pag-ayos ng conflict, interactive mode) ay nasa hiwalay na mga artikulo. Dito, ang pagpili ng estratehiya lang ang tinatalakay.
Itsura ng history sa dalawang kaso
Panimulang sitwasyon: humiwalay kayo sa feature, gumawa ng dalawang commit, habang may dalawang bagong commit ng iba sa main.
D---E feature
/
A---B---C---F---G main
Pagkatapos ng git merge feature sa main:
D---E
/ \
A---B---C---F---G---M main
Pagkatapos ng git rebase main sa feature at pag-usog ng main:
A---B---C---F---G---D'---E' main
Sa unang kaso, nakikita sa history na ginawa nang parallel ang feature at kung kailan ito isinama. Sa ikalawa, binabasa ang history bilang sunod-sunod na kuwento, pero wala na ang bakas ng parallel na trabaho: ang D' at E' ay mga bagong commit na nilikha sa sandali ng rebase.
Talaan ng paghahambing ng merge vs rebase
| Pamantayan | git merge | git rebase |
|---|---|---|
| Mga umiiral na commit | Hindi nagbabago | Nilikhang muli na may bagong hash |
| Hugis ng history | Branching graph na may merge commit | Linear |
| Kaligtasan para sa shared branch | Laging ligtas | Delikado para sa nai-publish na commit |
| Kailangan ba ng force push | Hindi | Oo, kung nasa server na ang branch |
| Conflict | Inaayos nang isang beses, sa merge commit | Puwedeng lumitaw sa bawat inilipat na commit |
| Konteksto kung saan galing | Napapanatili | Nawawala |
| Pag-revert ng buong feature | Isang git revert -m 1 sa merge commit | Revert sa bawat commit o saklaw |
Kaginhawahan sa git bisect at git log | Mas mahirap basahin ang graph | Mas simple: isang tuwid na linya |
| Hadlang sa pagpasok | Mababa | Mas mataas, kailangang maintindihan ang pagsusulat muli ng history |
| Paglilinis ng commit (squash, reword) | Squash lang ng buong branch (--squash) | Flexible sa pamamagitan ng rebase -i |
Mga bentahe at disbentahe ng merge
Mga bentahe
- Hindi sinisira ang history. Nananatili ang anumang nai-publish. Hindi na kailangang ayusin ng mga katrabaho ang anuman dahil sa ginawa ninyo.
- Isang beses lang inaayos ang conflict. Kahit 30 commit ang branch, ang kinakaharap ninyo ay ang panghuling estado, hindi bawat hakbang.
- Napapanatili ang konteksto. Sa merge commit, makikita kung aling task ang pumasok sa pangunahing branch at kailan, at madali itong i-revert nang buo.
Mga disbentahe
- Maingay na graph. Kapag madalas ang synchronization, dumarami ang mga commit na "Merge branch 'main' into feature", at nagiging parang railway diagram ang
git log --graph. - Nakapapasok sa history ang mga draft na commit. Ang "wip", "fix", "isa pang fix" ay mananatili sa pangunahing branch magpakailanman, kung hindi ito na-squash.
Mga bentahe at disbentahe ng rebase
Mga bentahe
- Linear at madaling basahing history. Nasa tamang puwesto ang bawat commit, nababasa ang
git logbilang listahan ng mga pagbabago, at mas madaling mahanap nggit bisectang commit na may error. - Puwedeng ayusin ang mga commit bago ang review: pagsamahin, palitan ang pangalan, o ayusin ang pagkakasunod-sunod.
- Walang teknikal na merge commit mula sa pag-sync sa pangunahing branch.
Mga disbentahe
- Muling isinusulat ang history. Ang rebase ng nai-publish na shared branch ay sumisira sa gawa ng lahat ng nag-download nito.
- Kailangan ng force push para sa mga branch sa server, kaya kailangan ng disiplina at
--force-with-lease. - Paulit-ulit na conflict. Maaaring mag-conflict ang iisang bahagi sa maraming commit na magkakasunod.
- Maaaring hindi mag-build ang mga intermediate na commit. Pagkatapos ilipat sa bagong base, walang nagte-test ng mga lumang commit sa bagong kapaligiran.
Kailan gagamitin ang alin
Rebase para sa sarili ninyong lokal na trabaho
Ina-update ninyo ang branch bago ipadala: git pull --rebase. Inihahanda ang branch para sa review at gusto ninyong alisin ang mga draft na commit: git rebase -i. Nahuli sa main ang personal ninyong feature branch: git rebase origin/main. Sa lahat ng ito, binabago ang mga commit na ang nakakita lang ay kayo (o pag-aari ninyo lang).
Merge para sa shared branch at integration
Ang tapos nang feature ay isinasama sa main o develop. Maraming tao ang nagtatrabaho sa branch. Kailangang isama ang release branch pabalik sa pangunahing branch. Dito, mahalagang huwag galawin ang mga nai-publish na commit, at ang merge lang ang tamang opsyon.
Simpleng tuntunin sa pagpili
Kung kayo lang ang may hawak ng commit, puwede ang rebase. Kung may nakadownload na nito, merge lang.
Handang daloy ng trabaho para sa team
| Daloy | Paano gumagana | Para kanino |
|---|---|---|
| Merge lang | Ang mga feature ay isinasama gamit ang --no-ff, at ang sync ay git merge main | Mga baguhan sa Git, team na mahalaga ang buong chronology at simpleng pag-rollback |
| Rebase + merge | Nire-rebase ang branch sa main bago isama, tapos merge commit na may --no-ff | Team na kailangan ang malinis na history at hangganan ng feature |
| Rebase + fast-forward | Nire-rebase ang branch at isinasama sa pamamagitan ng fast-forward; ganap na linear ang history | Maliliit na team na may maayos na atomic commit |
| Squash merge | Bawat pull request ay nagiging iisang commit sa main | Mga team na may maiikling task, kung saan hindi kailangan ang detalyadong history ng branch |
Sa GitHub at GitLab, tumutugma ang mga daloy na ito sa mga button na "Create a merge commit", "Rebase and merge", at "Squash and merge". Mainam na payagan sa settings ng repository ang iisang napiling opsyon, para hindi maging halo-halo ang istilo ng history.
Mga setting na nagpapatibay ng pagpili
# pull nang walang dagdag na merge commit
git config --global pull.rebase true
# o: pull na fast-forward lang, kung hindi, error, kayo ang magdedesisyon
git config --global pull.ff only
# laging merge commit kapag nagsasama ng feature
git config --global merge.ff false
Mag-ingat sa merge.ff false: nakakaapekto rin ito sa git pull sa merge mode. Maraming gumagamit ang hindi ito ginagawang global, at sa halip ay tahasang nagta-type ng --no-ff kapag nagsasama ng feature.
Halimbawa: isang task sa dalawang istilo
Ilarawan natin ang totoong sitwasyon. Tatlong araw na ninyong ginagawa ang feature ng payment sa feature/payment, at sa panahong iyon, limang gawain ng iba ang naisama na sa main. Bago ang pull request, kailangang kunin ang bagong main at tiyaking gumagana ang lahat.
Bersyon ng merge
git switch feature/payment
git fetch origin
git merge origin/main
# inayos ang conflict nang isang beses, git add, git commit
git push
Nakakuha ang branch ng commit na "Merge remote-tracking branch 'origin/main' into feature/payment". Normal ang push, at hindi mapapansin ng mga katrabahong nakatingin sa branch ang anuman. Kung ganito kayo mag-sync araw-araw, tatlong ganitong commit ang nasa branch, at mapupunta ang mga ito sa main kasama ng feature kung walang squash.
Bersyon ng rebase
git switch feature/payment
git fetch origin
git rebase origin/main
# inaayos ang conflict habang nagpapatuloy, sa bawat commit: git add, git rebase --continue
git rebase -i origin/main # opsyonal: pagsamahin ang mga draft na commit
git push --force-with-lease
Mukhang nagsimula ang branch kaninang umaga mula sa sariwang main, walang dagdag na commit, at mas madaling basahin ng reviewer ang mga pagbabago nang hakbang-hakbang. Ang kapalit: force push, at kailangang tiyakin na walang ibang nagko-commit sa branch na ito.
Ano ang makikita ng main sa dulo
Sa pagsasama sa pamamagitan ng pull request, mananatili ang pagkakaiba. Ang estilo ng merge ay magbibigay ng graph na may mga sanga at sync merge; ang estilo ng rebase ay magbibigay ng maayos na kadena ng mga commit ng feature, na puwedeng isama sa pamamagitan ng fast-forward o isang merge commit. Pareho ang code sa dulo, basta magkapareho ang pag-ayos ng conflict.
Paano magdesisyon bilang team
Sagutin ang ilang tanong. May ilang taong nagtatrabaho sa iisang branch? Kung oo, hindi puwede ang rebase sa branch na iyon. Gaano kaexperyensado ang team sa Git? Kung madalas ang mga baguhan, magsimula sa merge at squash merge; pinapatawad nila ang mga pagkakamali. Kailangan ba ng buong chronology para sa audit at pagsusuri ng insidente? Kung oo, kapaki-pakinabang ang mga merge commit ng feature. Mahalaga ba ang mababasang git log at madalas na git bisect? Kung oo, pumanig sa rebase at linear na history.
Itala ang desisyon sa CONTRIBUTING o README ng repository, at i-enable ang proteksyon ng pangunahing branch: bawal ang force push, kailangan ng pull request, at nakatakda ang pinapayagang paraan ng merge. Mas maaasahan ang tuntuning nakatali sa settings kaysa sa kasunduang pasalita lang.
Mga karaniwang maling akala
- "Advanced ang rebase, para sa baguhan ang merge." Hindi: magkaiba ang kasangkapan para sa magkaibang gawain. Gumagamit ng pareho ang mga beteranong developer.
- "Basura ang merge commit." Ang mga sync merge, oo, kadalasang ingay. Pero ang merge commit ng pagsasama ng feature ay mahalagang punto: dito makikita at maibabalik ang buong task.
- "Kapag rebase, mas kaunti ang conflict." Pareho ang conflict, dahil pareho ang mga linyang nagbabago. Hinahati lang ng rebase ang mga ito ayon sa commit, samantalang inaayos ng merge ang lahat nang sabay.
- "Nawawala ang mga commit sa rebase." Nananatili ang mga lumang commit sa
git reflogat mababawi ang mga ito, hangga't hindi sila nabubura ng garbage collection.
Buod
Ang pagpili sa pagitan ng merge at rebase ay pagpili sa pagitan ng tapat na chronology at mabasang linear na history. Ligtas ang merge at pinananatili ang konteksto; nagbibigay ang rebase ng kalinisan, pero muling isinusulat ang mga commit. Ang pinakamaaasahang gawi ay pagsamahin ang dalawa: i-rebase at linisin ang sarili ninyong branch habang kayo pa lang ang may hawak nito, at isama ang tapos nang trabaho sa shared branch gamit ang merge o squash ayon sa tuntunin ng team. Ang pinakamahalaga ay magkasundo sa isang daloy at itatak ito sa settings ng repository. Ang dalawang estratehiya at ang pagtutulungan sa branch ay itinuturo nang praktikal sa kursong Git namin.
Mga madalas itanong
Alin ang gagamitin sa git pull, merge o rebase?
Para sa pag-update ng lokal na branch, mas maginhawa ang rebase: mailalagay ang inyong hindi pa naipapadalang commit sa ibabaw ng bagong remote nang walang dagdag na merge commit. Ina-enable gamit ang git config --global pull.rebase true.
Puwede bang paghaluin ang merge at rebase sa iisang project?
Oo, at ito ang pinakakaraniwang paraan: rebase para sa sarili ninyong branch, merge para sa shared. Ang mahalaga ay alam ng buong team ang tuntunin.
Ano ang dapat piliin ng baguhan?
Magsimula sa merge: hindi nito binabago ang history, kaya mahirap masira ang anuman. Pag-aralan ang rebase sa sarili ninyong lokal na branch kapag nakilala na ninyo ang reflog at force push.
Naaapektuhan ba ng pagpili ng estratehiya ang code sa dulo?
Hindi, kapag magkapareho ang pag-ayos ng conflict, magkapareho ang panghuling estado ng mga file. Ang pagkakaiba lang ay ang naitalang history ng commit.
Ano ang pagkakaiba ng squash merge at rebase?
Pinagsasama ng squash merge ang buong branch sa iisang bagong commit sa pangunahing branch, habang inililipat ng rebase ang bawat commit nang hiwalay. Pareho silang nagbibigay ng linear na history, pero nawawala ang detalye ng bawat hakbang sa squash.
Detalyadong tinatalakay ang paksang ito, may praktis, sa kursong “Git с нуля до уверенного разработчика”.
- Git-процессы в реальных командах: какой workflow выбрать
- Продвинутые инструменты: rebase, stash, cherry-pick и теги