Mwongozo

git merge: jinsi ya kuunganisha matawi na kusuluhisha conflicts

Imesasishwa: · Skillaria.Top

git merge inaunganisha historia ya tawi lingine na la sasa: ikiwa tawi la sasa halijasonga mbele, Git inasogeza kielekezi tu (fast-forward), vinginevyo inaunda commit ya merge yenye wazazi wawili. Hamia tawi lengwa kisha tekeleza git merge jina-la-tawi; ikitokea conflict, rekebisha faili, fanya git add na git commit, au ghairi yote kwa git merge --abort.

Git merge inafanya nini

Amri git merge inachukua mabadiliko kutoka tawi lililotajwa na kuyaingiza kwenye tawi ulilopo sasa. Jambo la kukumbuka ni mwelekeo: unaunganisha «ndani ya yenyewe». Ili kuingiza feature/login kwenye main, kwanza unahamia main, kisha unaita muunganisho.

git switch main
git pull                 # vuta main mpya kutoka seva
git merge feature/login

Git haikopi mistari moja moja «kwa mkono». Inatafuta babu wa pamoja wa matawi mawili (merge base), inalinganisha matoleo yote mawili nayo na kuweka mabadiliko pamoja. Ikiwa pande zote mbili zilibadilisha sehemu tofauti, matokeo yanapatikana kiotomatiki. Ikiwa zilibadilisha sehemu ile ile — conflict hutokea, na uamuzi ni wako.

Njia mbili: fast-forward na merge ya pande tatu

Fast-forward — wakati commit ya merge haihitajiki

Tuseme uliitoa feature kutoka main, ukafanya commits tatu, na wakati huo hakuna aliyeongeza chochote kwenye main. Basi historia ya main ni mwanzo tu wa historia ya feature. Git inasogeza kielekezi cha main mbele hadi commit ya mwisho ya feature, na hakuna commit mpya inayoundwa.

$ git merge feature
Updating 3f2a1c4..9b7e0d2
Fast-forward
 src/auth.js | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

Historia inabaki mstari mmoja, lakini ukweli kwamba «hapa kulikuwa na tawi la feature» unapotea. Wakati mwingine hilo ni zuri, wakati mwingine si — tazama hapa chini sehemu ya --no-ff.

Merge ya pande tatu na commit ya merge

Ikiwa matawi yote mawili yamesonga mbele kutoka babu wa pamoja, kusogeza kielekezi hakuwezekani tena. Git inafanya merge ya pande tatu: msingi, upande «wetu» (tawi la sasa) na upande «wao» (tawi linalounganishwa). Matokeo yanarekodiwa kwenye commit tofauti ya merge, yenye wazazi wawili.

$ git merge feature
Merge made by the 'ort' strategy.
 src/auth.js   | 42 ++++++++++++++++++++
 src/router.js |  3 +-
 2 files changed, 44 insertions(+), 1 deletion(-)

Git itafungua kihariri chenye ujumbe kama Merge branch 'feature'. Unaweza kuuacha au kuongeza sababu ya muunganisho. Ili kuona «mpasuko» uliotokea, tumia:

git log --oneline --graph --all

Mkakati ort ndio chaguo-msingi kuanzia Git 2.34; awali ulikuwa recursive. Kwa kazi ya kila siku hakuna haja ya kubadilisha mkakati.

Bendera muhimu za git merge

BenderaInafanya niniLini inasaidia
--no-ffDaima inaunda commit ya merge, hata pale fast-forward inawezekanaUnataka kuona kwenye historia commits zipi zilitoka kwenye kipengele kimoja
--ff-onlyInaunganisha kwa kusogeza tu, vinginevyo inashindwa kwa hitilafuKusasisha tawi la ndani bila commits za merge zisizo za lazima
--squashInaweka mabadiliko yote ya tawi kwenye index, lakini haifanyi commit wala kuunganisha uhusiano na tawiUnataka kugeuza kipengele kuwa commit moja nadhifu
--no-commitInatekeleza muunganisho lakini inasimama kabla ya commitUnataka kuhakiki matokeo au kuendesha majaribio kabla ya kuweka commit
-m "maandishi"Inaweka ujumbe wa commit ya mergeMuunganisho kwenye scripts bila kihariri
--abortInaghairi merge iliyoanzishwa na kurudisha hali ya kabla yakeConflicts ni nyingi mno na unataka kuanza upya
--continueInakamilisha merge baada ya kusuluhisha conflictsMbadala wa git commit katika hatua ya mwisho
-X ours / -X theirsKwenye vipande vinavyogongana, inachukua toleo letu au lao kiotomatikiUnajua hakika toleo lipi ni sahihi (kwa tahadhari!)

--no-ff: kuhifadhi mipaka ya kipengele

Timu nyingi huunganisha vipengele kwa --no-ff pekee. Hapo kwenye grafu kila kazi inaonekana kama «kiputo», na inaweza kughairiwa kwa amri moja git revert -m 1 <commit-ya-merge>. Kwa fast-forward hakuna kituo kama hicho, na kughairi kungelazimu kuondoa kila commit kivyake.

--squash: commit moja badala ya kumi

git switch main
git merge --squash feature/login
git commit -m "Kuingia kwa barua pepe na nywila"

Baada ya --squash, Git haichukulii tawi kuwa limeunganishwa: git branch -d feature/login itakataa kulifuta kwa onyo «not fully merged». Lifute kwa git branch -D ukishahakikisha kila kitu kipo. Na usiendelee kufanya kazi kwenye tawi lile lile baada ya squash — muunganisho ujao utaleta mabadiliko yaliyokwisha kuingia tena, na karibu hakika utatoa conflicts.

Conflict ya muunganisho: jinsi ya kuisuluhisha

Conflict ni hali ya kawaida ya kazi, si ajali. Maana yake ni moja: matawi mawili yamebadilisha mistari ile ile (au mmoja amefuta faili ambalo lingine lilikuwa likilibadilisha), na Git haijaribu kukisia toleo lipi ni sahihi.

$ git merge feature/login
Auto-merging src/config.js
CONFLICT (content): Merge conflict in src/config.js
Automatic merge failed; fix conflicts and then commit the result.

Hatua ya 1. Angalia kinachogongana

$ git status
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   src/config.js

Hatua ya 2. Hariri faili

Kwenye faili lenye conflict, Git inaweka alama:

<<<<<<< HEAD
const TIMEOUT = 5000;
=======
const TIMEOUT = 10000;
>>>>>>> feature/login

Sehemu ya juu ni tawi lako la sasa (HEAD), ya chini ni tawi linalounganishwa. Acha toleo sahihi (au unganisha yote mawili), ondoa mistari mitatu ya alama, kisha uhifadhi faili. Kosa la kawaida ni kusahau alama mahali fulani katikati ya faili; kabla ya commit zitafute: git diff --check itaonyesha alama zilizobaki.

Hatua ya 3. Weka alama ya suluhisho na umalize muunganisho

git add src/config.js
git commit          # au git merge --continue

Ikiwa conflict inatatuliwa kwa kuchagua upande mmoja tu, si lazima kuhariri faili kwa mkono:

git checkout --ours   src/config.js   # acha toleo la tawi la sasa
git checkout --theirs src/config.js   # chukua toleo la tawi linalounganishwa
git add src/config.js

Ni rahisi zaidi kwenye kihariri

VS Code, IDE za JetBrains na wahariri wengine wanaonyesha conflict kwa safu tatu na wana vitufe vya «kubali la sasa / linaloingia / yote mawili». Unaweza pia kuunganisha zana ya nje kupitia git mergetool. Mpangilio muhimu ni git config --global merge.conflictStyle zdiff3: kwenye alama pia itaonekana toleo la awali kutoka babu wa pamoja, na inakuwa wazi nani alibadilisha nini.

Umebadili nia — ghairi muunganisho

git merge --abort

Amri hii inarudisha saraka ya kazi na index kwenye hali ya kabla ya git merge. Kwa hiyo kabla ya kuunganisha ni vizuri kuwa na saraka ya kazi safi: weka commit au uhifadhi kazi ambayo haijakamilika kwa git stash, vinginevyo itakuwa vigumu kuitenganisha na matokeo ya muunganisho.

Jinsi ya kughairi merge iliyokwisha kufanyika

Ikiwa commit ya merge bado haijatumwa kwenye seva, njia rahisi ni kurudisha tawi nyuma:

git reset --hard ORIG_HEAD

ORIG_HEAD Git huiandika kabla ya operesheni hatari, ikiwemo merge — ni nafasi ya tawi kabla ya merge. Bendera --hard inatupa mabadiliko ambayo hayajawekwa commit, kwa hiyo angalia git status kwanza.

Ikiwa muunganisho tayari uko kwenye hifadhi ya pamoja, historia haiandikwi upya. Badala yake unaunda commit ya kinyume:

git revert -m 1 a1b2c3d

Bendera -m 1 inasema kwamba «mkuu» ni mzazi wa kwanza (tawi ambalo muunganisho ulifanyika ndani yake). Angalia mtego: baada ya revert kama hii Git inachukulia commits za kipengele tayari zimeingia. Ukitaka kuingiza kipengele kilichorekebishwa baadaye, lazima kwanza ughairi revert yenyewe.

Merge katika kazi ya timu

git pull ni fetch pamoja na merge

Kwa kawaida git pull inapakua mabadiliko na kuunganisha tawi la mbali kwenye la ndani. Ukifanya commits sambamba na mwenzako, utaona commit «Merge branch 'main' of ...». Ili kuepuka muunganisho wa kiufundi kama huo, weka git config --global pull.ff only (pull inashindwa ikiwa kusogeza hakuwezekani, na unaamua mwenyewe) au tumia git pull --rebase.

Pull request na kitufe cha Merge

Kwenye GitHub na GitLab muunganisho kwa kawaida unafanyika kupitia pull/merge request. Kitufe «Create a merge commit» kinalingana na git merge --no-ff, «Squash and merge» — muunganisho wa kubana, «Rebase and merge» — kupanga upya. Kuchagua hali ni makubaliano ya timu, lakini utaratibu wenyewe ni ule ule wa terminal.

Kuingiza main kwenye tawi lako

Tawi linaloishi muda mrefu linatofautiana na main, na conflicts zinajilimbikiza. Vuta tawi kuu kwako mara kwa mara:

git switch feature/login
git fetch origin
git merge origin/main

Hivyo conflicts zinasuluhishwa kwa vipande vidogo kadiri zinavyotokea, na muunganisho wa mwisho kwenye main unapita kwa urahisi.

Makosa ya kawaida

  • Umeunganisha upande usio sahihi. Umetekeleza git merge main ukiwa kwenye main, au umeingiza kipengele kwenye kipengele kingine. Kabla ya kuunganisha hakiki tawi la sasa kwa git branch --show-current.
  • Muunganisho na tawi lililopitwa na wakati. Uliunganisha main ya ndani iliyokaa wiki bila kusasishwa. Kwanza git pull, kisha merge.
  • «Your local changes would be overwritten by merge». Kuna mabadiliko ambayo hayajawekwa commit kwenye faili zile zile. Yawekee commit au yaweke kwenye stash.
  • «refusing to merge unrelated histories». Matawi hayana babu wa pamoja — kwa mfano hifadhi ya ndani iliundwa kwa git init, na ile ya mbali tayari ina README. Ikiwa muunganisho ni wa lazima kweli, ongeza --allow-unrelated-histories.
  • Commit iliyo na alama za conflict. Ujenzi unavunjika kwenye <<<<<<<. Tumia git diff --check na endesha majaribio kabla ya commit.

Muhtasari

git merge ni njia salama ya kuunganisha matawi: haiandiki upya commits zilizopo, inaongeza mpya tu (au inasogeza kielekezi). Unganisha kwenye tawi la sasa, weka saraka ya kazi safi, tumia --no-ff ikiwa mipaka ya vipengele ni muhimu, na --squash ikiwa unataka commit moja. Conflicts zinasuluhishwa kwa hatua tatu: kuhariri faili, git add, git commit; na git merge --abort itakurudisha kwenye mahali pa kuanzia wakati wowote. Kuunganisha matawi na kusuluhisha conflicts vinafanyiwa mazoezi ya vitendo katika kozi ya Git.

Maswali ya mara kwa mara

git merge inatofautianaje na git pull?

git pull kwanza inapakua mabadiliko kutoka seva (git fetch), kisha inaunganisha tawi la mbali kwenye la sasa kwa git merge au, ikiwa imesanidiwa hivyo, kwa rebase. git merge inafanya kazi tu na kilichopo kwenye kompyuta yako.

Je, inawezekana kuunganisha matawi kadhaa kwa mara moja?

Ndiyo, git merge feature-a feature-b inafanya muunganisho wa octopus wenye wazazi wengi, lakini tu ikiwa hakuna conflicts. Kwa vitendo matawi kwa kawaida huunganishwa moja moja.

Nawezaje kuona matawi ambayo tayari yameunganishwa kwenye la sasa?

git branch --merged inaonyesha matawi yaliyoingia kikamilifu kwenye la sasa, na git branch --no-merged — yale ambayo bado hayajaunganishwa. Matawi yaliyounganishwa yanaweza kufutwa salama kwa git branch -d.

Nawezaje kuona mapema kile ambacho muunganisho utaleta?

Tekeleza git log main..feature kuona commits zisizo kwenye main, na git diff main...feature kuona mabadiliko ya tawi kuhusiana na babu wa pamoja.

ORIG_HEAD baada ya merge ni nini?

Ni rejeo ambalo Git huihifadhi kabla ya muunganisho: linaelekeza kwenye nafasi ya tawi kabla ya merge. Kwa git reset --hard ORIG_HEAD unaweza kurudisha muunganisho wa ndani, mradi bado haujatumwa kwenye seva.

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