Ulinganisho

git fetch na git pull: tofauti yake ni nini na nini cha kuchagua

Imesasishwa: · Skillaria.Top

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 una origin na upstream kwenye 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 fetchgit pull
Hupakua commitsNdiyoNdiyo
Husasisha origin/*NdiyoNdiyo
Hubadilisha tawi la sasaHapanaNdiyo
Hubadilisha faili kwenye saraka ya kaziHapanaNdiyo
Inaweza kusababisha conflictHapanaNdiyo
Inahitaji saraka ya kazi safiHapanaInapendekezwa
Inagusa matawi mengineHusasisha alama zote za matawi yanayofuatiliwaHuunganisha kwenye la sasa tu
Lini kutumiaKuona kilichobadilika; kabla ya rebase; kwenye scriptsKupata 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:

  1. git status — hakikisha kila kitu kimewekwa commit au kimefichwa kwa git stash;
  2. git pull --rebase — chukua mabadiliko na upange upya commits zako juu;
  3. suluhisha conflicts ikiwa zipo: rekebisha faili, git add, git rebase --continue;
  4. endesha majaribio;
  5. 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 na pull.rebase true).
  • Unasasisha tawi kuu lisilo na commits zako — git pull --ff-only.
  • Unataka kuingiza main kwenye tawi la feature — git fetch, kisha git rebase origin/main au git 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.

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