git fetch na git pull: tofauti yake ni nini na nini cha kuchagua
git fetch hupakua commits mpya kutoka seva na kusasisha marejeo ya matawi ya mbali kama origin/main, bila kugusa tawi lako au faili zako. git pull hufanya hivyo hivyo na kisha mara moja huunganisha vilivyopakuliwa kwenye tawi la sasa kwa merge au rebase. Fetch ni salama kila wakati; pull ni rahisi unapokuwa tayari kupokea mabadiliko ya wengine mara moja.
Jibu fupi
git fetch hupakua commits mpya kutoka seva na kusasisha marejeo ya matawi ya mbali (origin/main, origin/feature-x), lakini haibadilishi tawi lako la sasa wala faili kwenye saraka ya kazi. git pull ni git fetch pamoja na kuunganisha mara moja kilichopakuliwa kwenye tawi la sasa: kwa merge (kwa chaguo-msingi) au kwa rebase.
Kutokana na hilo kanuni ya vitendo ni: fetch unaweza kuiendesha wakati wowote, haivunji kitu. Pull hubadilisha tawi lako na inaweza kuishia kwa conflict, kwa hiyo ni bora kuiendesha ukiwa na saraka ya kazi safi na ukijua kinachokuja.
Matawi ya mbali yanaishi wapi
Ili tofauti ionekane wazi, ni lazima kuelewa kwamba kwenye hifadhi ya ndani kuna aina mbili za matawi. Za ndani — main, feature-x — unazisogeza kwa commits zako. Matawi ya mbali yanayofuatiliwa — origin/main — ni alama za «seva ilivyoonekana wakati wa usawazishaji wa mwisho». Huwezi kuyasogeza kwa mkono; yanasasishwa tu kwa mawasiliano na seva: fetch, pull na push.
git branch -a
* main
remotes/origin/HEAD -> origin/main
remotes/origin/main
remotes/origin/feature-x
git status inalinganisha tawi lako na alama ya origin/main, si na seva iliyo hai. Kwa hiyo ujumbe «Your branch is up to date with 'origin/main'» unaweza kudanganya: ikiwa hujafanya fetch kwa muda mrefu, Git haijui kuhusu commits mpya za wenzako.
Git fetch inafanya nini
$ git fetch
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
Unpacking objects: 100% (4/4), done.
From github.com:team/project
3f2a1c9..8b7d4e2 main -> origin/main
Mstari wa mwisho unasema jambo kuu: rejeo origin/main limesogea kutoka 3f2a1c9 hadi 8b7d4e2. main yako imebaki pale pale. Sasa unaweza kuangalia kilichofika kwa utulivu:
git status # Your branch is behind 'origin/main' by 2 commits
git log main..origin/main --oneline # commits ambazo huna
git diff main origin/main # kitakachobadilika kwenye faili
Chaguo muhimu za fetch:
git fetch --all— chukua mabadiliko kutoka remote zote (muhimu ikiwa unaoriginnaupstreamkwenye fork);git fetch --prune(-p) — futa alama za matawi ya ndani ambayo hayapo tena kwenye seva;git fetch origin main— chukua tawi moja tu;git fetch --tags— chukua pia tagi zote.
Ili kupogoa (pruning) ifanyike kila wakati, iwashe mara moja: git config --global fetch.prune true.
Git pull inafanya nini
git pull inafanya hatua mbili mfululizo. Kwanza fetch kwa upstream ya tawi la sasa, kisha kuunganisha origin/<tawi> na tawi lako. Kwa maneno mengine ni sawa na:
git fetch origin
git merge origin/main # au git rebase origin/main ukiwa na pull --rebase
Matokeo ya kuunganisha yanategemea jinsi historia zilivyotengana:
- huna commits mpya — kunatokea fast-forward, tawi linasogezwa mbele tu;
- commits mpya zipo kwako na kwenye seva — kwa merge kinaundwa commit ya kuunganisha, kwa rebase commits zako zinapangwa upya juu ya zile za seva;
- mistari ile ile ilibadilishwa pande zote mbili — conflict, inayohitaji kusuluhishwa kwa mkono.
Ulinganisho wa git fetch na git pull
| git fetch | git pull | |
|---|---|---|
| Hupakua commits | Ndiyo | Ndiyo |
| Husasisha origin/* | Ndiyo | Ndiyo |
| Hubadilisha tawi la sasa | Hapana | Ndiyo |
| Hubadilisha faili kwenye saraka ya kazi | Hapana | Ndiyo |
| Inaweza kusababisha conflict | Hapana | Ndiyo |
| Inahitaji saraka ya kazi safi | Hapana | Inapendekezwa |
| Inagusa matawi mengine | Husasisha alama zote za matawi yanayofuatiliwa | Huunganisha kwenye la sasa tu |
| Lini kutumia | Kuona kilichobadilika; kabla ya rebase; kwenye scripts | Kupata seva haraka kwenye tawi lako |
git pull: merge au rebase
Kuanzia Git 2.27, historia inapotengana bila mpangilio wazi, pull inaonya, na katika matoleo mapya badala ya merge kimya kimya inasimama na hitilafu «Need to specify how to reconcile divergent branches». Git inataka uchague mkakati mara moja:
git config --global pull.rebase false # merge (tabia ya awali ya chaguo-msingi)
git config --global pull.rebase true # rebase
git config --global pull.ff only # fast-forward tu, vinginevyo kukataa
Merge inahifadhi historia kama ilivyokuwa na kuongeza commit «Merge branch 'main' of github.com:...». Ukifanya pull kila siku kwenye tawi lenye commits zako za ndani, historia inajaa muunganisho huu wa kiufundi.
Rebase inapanga upya commits zako ambazo hazijatumwa juu ya zile mpya za seva. Historia inabaki mstari mmoja, na conflicts zinasuluhishwa commit moja baada ya nyingine. Kwa commits za ndani ambazo hazijachapishwa, hii kwa kawaida ndiyo chaguo bora. Rebase ni hatari tu kwa commits zilizotumwa ambazo wengine wanajengea kazi yao.
ff only ndiyo hali kali zaidi: pull inafanya kazi tu wakati huna commits zako. Historia ikitengana, unaamua wazi cha kufanya. Wasanidi wengi wenye uzoefu wanaweka hii kwa matawi makuu.
Ikiwa kuna mabadiliko ambayo hayajawekwa commit kwenye saraka ya kazi, na pull inahitajika sasa hivi, git pull --rebase --autostash inasaidia: Git itaficha mabadiliko, kufanya rebase, kisha kuyarudisha.
Mfano wa kawaida: fetch, angalia, unganisha
Mbinu ya «kwanza fetch» inakupa udhibiti wa kile kinachoingia kwenye tawi lako. Ni muhimu hasa kabla ya kutuma pull request na baada ya mapumziko marefu.
git fetch
git log --oneline --graph HEAD origin/main # matawi yalivyotengana
git rebase origin/main # au git merge origin/main
git push
Hali nyingine ya kawaida ni kusasisha tawi lako la feature kwa main mpya bila kuhamia kwake:
git switch feature-x
git fetch
git rebase origin/main
Hapa pull haifai: git pull kwenye tawi la feature itavuta mabadiliko ya upstream yake yenyewe (origin/feature-x), si ya tawi kuu. Unaweza kuandika git pull --rebase origin main, lakini njia ya fetch ni wazi zaidi.
Kusawazisha na seva: jinsi ya kuweka tawi likiwa la sasa
Ombi la «git sync» kwa kawaida linamaanisha mzunguko wa «chukua cha wengine — tuma changu». Kwenye Git safi hakuna amri ya sync (kitufe cha Sync kipo kwenye IDE na GUI, na ndani yake kinafanya pull kisha push). Kwa mkono, mzunguko wa kuaminika ni huu:
git status— hakikisha kila kitu kimewekwa commit au kimefichwa kwagit stash;git pull --rebase— chukua mabadiliko na upange upya commits zako juu;- suluhisha conflicts ikiwa zipo: rekebisha faili,
git add,git rebase --continue; - endesha majaribio;
git push.
Kusawazisha fork na hifadhi ya asili kunafanyika hivi:
git remote add upstream https://github.com/original/project.git
git fetch upstream
git switch main
git merge --ff-only upstream/main
git push origin main
Matatizo ya kawaida ya git pull
Your local changes would be overwritten by merge
Pull inataka kubadilisha faili ulizoziandika lakini hujazi-commit. Chaguo: weka commit, ficha (git stash, kisha pull na git stash pop) au tumia --autostash. Usifute mabadiliko ili tu pull ifanye kazi.
Conflict baada ya pull
Git itasimama na kuonyesha faili zenye conflict kwenye git status. Zifungue, chagua toleo sahihi kati ya alama <<<<<<< na >>>>>>>, kisha git add na git commit (kwa merge) au git rebase --continue (kwa rebase). Ukibadili nia — git merge --abort au git rebase --abort zitarudisha kila kitu kama kilivyokuwa kabla ya pull.
There is no tracking information for the current branch
Tawi halina upstream, na Git haijui pa kuvuta kutoka. Taja wazi: git pull origin main, au weka uhusiano mara moja: git branch --set-upstream-to=origin/main.
refusing to merge unrelated histories
Hifadhi ya ndani na ya mbali ziliundwa kwa kujitegemea — kwa mfano kwenye seva uliongeza README wakati wa kuunda hifadhi. Ikiwa una uhakika zinapaswa kuunganishwa: git pull origin main --allow-unrelated-histories.
Pull iliyoharibika: jinsi ya kurudi nyuma
Ikiwa merge baada ya pull imekamilika lakini matokeo hayakufai, rudisha tawi kwenye hali ya kabla yake: git reset --hard ORIG_HEAD. Amri hii inafuta mabadiliko ambayo hayajawekwa commit, kwa hiyo kwanza angalia git status. Kama suluhisho la mwisho, nafasi ya awali ya tawi itapatikana kwenye git reflog.
Cha kuchagua
- Unataka kujua kuna nini kipya bila kubadilisha chochote —
git fetch. - Unafanya kazi kwenye tawi lako na unataka kupata seva tu —
git pull --rebase(au pull ukiwa napull.rebase true). - Unasasisha tawi kuu lisilo na commits zako —
git pull --ff-only. - Unataka kuingiza
mainkwenye tawi la feature —git fetch, kishagit rebase origin/mainaugit merge origin/main. - Unaandika script au CI — fetch na amri wazi, bila pull.
Jinsi hili linavyoonekana kwenye grafu ya commits
Fikiria wewe na mwenzako mlianza kutoka commit C. Wewe ulifanya commit D kwenye kompyuta yako, na mwenzako alituma E kwenye seva. Baada ya git fetch, hifadhi yako inajua mistari yote miwili: main inaelekeza D, origin/main — E, na wana babu wa pamoja C.
D <- main (HEAD)
/
A---B---C
\
E <- origin/main
Kisha mbinu ya kuunganisha ndiyo inayoamua. git merge origin/main itaunda commit M yenye wazazi wawili, D na E. git rebase origin/main itanakili D juu ya E kama commit mpya D' yenye hash tofauti, na historia inakuwa mstari mmoja moja kwa moja. git pull hufanya hatua hizi zile zile kiotomatiki, bila pause kati yake. Hiyo pause — fursa ya kuangalia grafu kabla ya kuunganisha — ndiyo thamani kuu ya fetch ya pekee.
Fetch na pull kwenye IDE
Kwenye VS Code, IntelliJ IDEA na wahariri wengine vitufe vinaitwa tofauti, lakini chini yake ni amri zile zile. «Fetch» ni git fetch, «Pull» au «Update Project» ni pull yenye mkakati uliochaguliwa kwenye mipangilio (merge au rebase), «Sync Changes» ni pull kisha push. Kabla ya kubonyeza Sync kwenye tawi la pamoja, ni vizuri kujua mkakati uliochaguliwa, vinginevyo commits za kuunganisha zitaonekana ghafla kwenye historia. IDE nyingi pia hufanya fetch chinichini mara kwa mara, kwa hiyo hesabu ya commits zinazoingia kwenye upau wa hali kwa kawaida ni ya sasa.
Muhtasari
git fetch husasisha kile unachojua kuhusu seva, git pull pia inatumia maarifa hayo kwenye tawi la sasa. Fetch ni salama wakati wowote, pull ni rahisi lakini hubadilisha tawi na inaweza kuleta conflict, kwa hiyo sanidi mkakati wake mara moja na weka saraka ya kazi safi. Tofauti kati ya push, pull na fetch, kazi na remote na GitHub zimefafanuliwa kwa vitendo katika kozi ya Git.
Maswali ya mara kwa mara
Je, ni lazima kufanya git fetch kabla ya git pull?
Hapana, pull yenyewe inafanya fetch kama hatua yake ya kwanza. Fetch tofauti inahitajika ukitaka kwanza kuona mabadiliko kisha uamue jinsi ya kuyaingiza.
Je, git fetch inaweza kufuta mabadiliko yangu?
Hapana. Fetch inabadilisha marejeo ya mbali kama origin/main tu, na haigusi matawi ya ndani, index wala saraka ya kazi.
Je, git pull husasisha matawi yote?
Hapana, pull inaunganisha mabadiliko kwenye tawi la sasa pekee. Alama za origin/* za matawi mengine zinasasishwa kupitia fetch, lakini matawi ya ndani yanabaki pale yalipo.
Ninapaswa kufanya git fetch mara ngapi?
Kabla ya kuanza kazi, kabla ya kuunda pull request, na kabla ya push. IDE nyingi hufanya fetch chinichini kiotomatiki, na hilo ni salama.
FETCH_HEAD ni nini?
Ni rejeo la ndani ambalo fetch huandika ndani yake kilichopakuliwa mwisho. Kwa mfano, baada ya git fetch origin main unaweza kutekeleza git merge FETCH_HEAD.
Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.
Nenda kwenye kozi