- Binibigyang-daan ka ng Git rebase na isulat muli ang base ng isang branch upang makamit ang mga linear histories nang walang hindi kinakailangang merge commits.
- Mga interactive na alok sa rebase comandos tulad ng squash, fixup, edit o reword upang pinuhin at isaayos ang mga commit.
- Ang muling pagsusulat ng nailathalang kasaysayan ay nangangailangan ng matinding pag-iingat at koordinasyon, gamit ang push --force-with-lease kung kinakailangan.
- Ang pag-alam kung paano lutasin ang mga hindi pagkakasundo at ihinto o ibalik ang isang rebase ay susi sa ligtas na paggamit ng tool na ito.
Kung matagal ka nang gumagamit ng Git sa Visual Studio , malamang ay narinig mo na ang mga bagay tulad ng "gumawa ng rebase bago buksan ang pull request" o "huwag mag-rebase sa isang remote," at marahil ay medyo naguguluhan ka pa rin, hindi lubos na sigurado kung ano ang nangyayari sa kasaysayan. Ang Git rebase ay kilala sa pagiging makapangyarihan, ngunit mapanganib din, at ang paggalang na iyon ay kadalasang nagmumula sa hindi lubos na pag-unawa sa ginagawa nito sa ilalim ng hood.
Sa gabay na ito, mahinahon nating ipapaliwanag kung ano ang rebase, paano ito naiiba sa merge, kailan mo dapat gamitin ang rebase at kailan pinakamahusay na iwasan ito , paano gumagana ang interactive rebase, ang mga panganib ng pag-overwrite ng history, at kung paano i-recover kung may magkamali. Ang lahat ay ipinaliwanag sa karaniwang Espanyol (mula sa Espanya), na may mga praktikal na halimbawa at walang mga pagpapalagay.
Ano ang Git rebase?
Ang Git rebase ay isang utos na nagbibigay-daan sa iyong "ilipat" ang isang serye ng mga commit sa isang bagong base sa loob ng graph ng kasaysayan ng Git. Sa halip na pagsamahin ang dalawang sangay sa pamamagitan ng paglikha ng isang merge commit, ang rebase ay "muling naglalapat" ng mga commit ng isang sangay nang paisa-isa sa isa pang punto sa kasaysayan, na bumubuo ng mga bagong commit ID at nag-iiwan ng mas malinis at mas linear na timeline.
Isipin na mayroon kang master branch , at simula sa commit A, gagawa ka ng feature branch . Sa branch na ito, gagawa ka ng ilang commit habang patuloy na umuusad ang mga pagbabago sa master. Ang rebasing ay nagbibigay-daan sa iyong sabihin sa Git: "kunin ang aking mga feature commit at isulat muli ang mga ito na parang ginawa ko ang mga ito nang direkta sa ibabaw ng mga pinakabagong pagbabago sa master ," na nagreresulta sa isang mas organisadong kasaysayan nang walang intermediate merge commits.
Ang operasyong ito ay nangangahulugan na muling isinusulat ng Git ang kasaysayan ng sangay na iyong nire-rebase . Hindi lamang ito isang visual na muling pagsasaayos: ang mga bagong commit ay nililikha gamit ang mga bagong hash, at ang mga luma ay hindi na nire-refer (bagaman maaaring manatili ang mga ito sa reflog nang ilang sandali). Kaya naman ang rebasing ay sinasabing parehong makapangyarihan at maselan.
Ang isang paraan upang maunawaan ito ay isipin ito tulad ng sumusunod: habang ang merging ay nag-uugnay sa dalawang linya ng trabaho na may iisang punto ng pagtatagpo, ang rebasing ay "nag-aangat" sa iyong branch, kinokopya ang mga commit nito, at ipini-paste ang mga ito sa isa pang branch, na parang doon sila nagmula noon pa man. Ang resulta ay karaniwang isang mas malinis na kasaysayan, ngunit ang presyo ay nagbabago sa aktwal na pagkakasunud-sunod kung paano ginawa ang mga pagbabago.
Rebase laban sa merge: parehong layunin, magkaibang landas
Ang pangunahing konteksto para sa paggamit ng rebase ay kapag gusto mong i-integrate ang mga pagbabago mula sa isang branch patungo sa isa pa . Nag-aalok ang Git ng dalawang opsyon: merge at rebase. Pareho nilang inililipat ang code sa iisang lugar, ngunit ang bakas na iniiwan nila sa history ay ibang-iba.
Sa `git merge` , isinasama ng iyong kasalukuyang branch ang mga commit mula sa ibang branch, at isang karagdagang merge commit ang nabubuo (maliban sa mga kaso ng fast-forwarding). Pinapanatili nitong buo ang orihinal na kasaysayan ng commit, ngunit kung maraming merge, ang commit graph ay maaaring magmukhang isang plato ng spaghetti. Ang bentahe ay wala kang kailangang i-overwrite ; idadagdag mo lang.
Sa `git rebase` , sa halip na gumawa ng merge commit, kukunin mo ang iyong mga commit at ilalagay ang mga ito sa ibabaw ng isa pang branch, na parang naroon na ang mga ito noon pa man. Ang resulta ay isang linear na history kung saan malinaw kung "kung ano" ang pinagbatayan ng bawat pagbabago. Ang downside ay ang mga commit hash ay binabago , at kung ang mga commit na iyon ay naibahagi na, maaari mong seryosong gawing kumplikado ang remote repository at ang sa iyong mga kasamahan.
Sa malalaking pangkat, karaniwan na pagsamahin ang parehong estratehiya: ang rebase ay ginagamit sa mga lokal na sangay o bago ang pagsasama upang linisin ang kasaysayan ng isang tampok, at pagkatapos ay isinasama ito sa pangunahing sangay na may merge (minsan ay walang fast-forward) upang mapanatili ang isang malinaw na punto ng pagsasama.
Ang susi ay ang pag-unawa na hindi ang pagsasama o ang muling pagbabase ang likas na "mas mabuti"; magkaibang kagamitan ang mga ito. Mas ligtas at mas malinaw ang pagsasama; mas elegante ang muling pagbabase sa mga tuntunin ng kasaysayan ngunit may kasamang responsibilidad kapag muling pagsusulat ng mga commit.
Pangunahing paggamit ng Git rebase

Ang pinakakaraniwang gamit ng rebase ay kapag nagtatrabaho ka sa isang feature branch at gustong dalhin ang mga pinakabagong pagbabago mula sa pangunahing branch (halimbawa, master o develop) nang hindi lumilikha ng karagdagang merge commit. Ang klasikong workflow ay magmumukhang ganito:
Halimbawa, nasa larangan ka ng trabaho feature/login, at ang sangay Umunlad na ang Master na may mga bagong commit simula nang buksan mo ang feature. Para makahabol sa linear na paraan, gagawin mo ang mga sumusunod:
git checkout feature/login
git fetch origin
git rebase origin/master
Gamit ang utos na ito, kinukuha ng Git ang iyong mga commit mula sa feature/login at muling inilalapat ang mga ito sa pinakabagong commit sa origin/master . Kung walang mga conflict, magkakaroon ka ng history kung saan lumalabas na ang iyong mga pagbabago ay palaging ginawa sa pinakabagong bersyon ng master.
Maaari ka ring mag-rebase mula sa target na branch, halimbawa:
git checkout feature/login
git rebase master
Ipinapalagay nito na napapanahon ang iyong lokal na master directory. Pareho ang resulta: ang iyong mga feature commit ay napapatungan ng master . Sa parehong kaso, ang bawat commit ay nirereplay, at kung may mga conflict, ipapakita ang mga ito sa iyo nang isa-isa para malutas mo.
Isa pang karaniwang pamamaraan ay ang pag-overwrite ng isang branch na orihinal na nakabatay sa isa pang intermediate branch. Halimbawa, mayroon kang feature branch na siya namang nagsisilbing batayan para sa isang branch . Kung sakaling magpasya kang ang branch ay dapat direktang naka-link sa master sa halip na feature, maaari mong i-push ang:
git checkout branch
git rebase master
Ang epekto ay ang branch ay "lumilipat" mula sa lumang base (feature) patungo sa bagong base (master) , pinapanatili ang mga pagbabago nito ngunit umaasa sa ibang punto sa commit graph.
Huwag muling ayusin ang pampublikong talaan
Napakalinaw ng pangunahing babala sa seguridad sa rebasing: huwag isulat muli ang mga commit na naibahagi na nang malayuan at kung saan maaaring pinagbabatayan ng ibang tao ang kanilang trabaho. Ito ay lalong mahalaga sa mga branch tulad ng master, develop, o anumang collaborative branch.
Kapag lumampas ka sa isang sanga at pagkatapos ay ikaw git push -f o git push --force-with-leaseAng sinasabi mo ay: "ang bersyon ko ng history ay nag-o-override sa nasa server." Kung may gumawa ng mga commit sa remote branch na iyon pagkatapos mong i-clone o i-drop ito, Ang mga commit na ito ay maaaring mawala o makabuo ng mga kumplikadong divergence. para ayusin.
Isipin ang senaryo na ito: dalawang tao ang nag-clone ng isang repository, bawat isa ay nagtatrabaho sa kanilang lokal na branch batay sa parehong remote branch, at ang isa sa kanila ay nagpasya na i-rebase at pilitin ang isang push. Ang isa naman ay patuloy na nagtatrabaho gamit ang lumang bersyon. Sa sandaling makuha o subukang i-push ang kanilang mga pagbabago, matutukoy ng Git na ang kanilang base ay hindi tumutugma sa remote , at magsisimula ang sakit ng ulo.
Kaya naman karaniwang inirerekomenda na gumamit ng rebase sa mga lokal na branch o feature branch na hindi pa nako-commit . Kung kailangan mong linisin ang mga commit bago i-push ang mga ito sa unang pagkakataon, perpekto. Kung ang branch ay nasa remote server na at may ibang taong nagtatrabaho dito, pinakamahusay na mag-isip nang mabuti, makipag-ugnayan sa team, at, kung magpasya kang magsulat muli, malinaw na ianunsyo ito.
Ang ginintuang tuntunin na madalas na inuulit ay: huwag baguhin ang mga commit na hindi lamang sa iyo . Kung ikaw lang ang taong nakahawak sa mga commit na iyon at alam mo ang iyong ginagawa, sige lang; kung hindi, mas mabuting pagsamahin ang mga ito o magbukas ng ibang branch para muling isaayos.
Karaniwang Git rebase kumpara sa interactive na Git rebase
Kapag pinag-uusapan natin ang tungkol sa rebasing, dalawang uri talaga ang pinag-uusapan natin: "normal" (hindi interactive) na rebasing at interactive na rebasing . Ang una ay inililipat lamang ang iyong mga commit mula sa isang base patungo sa isa pa; ang pangalawa ay nagbibigay-daan sa iyong i-edit, muling ayusin, pagsamahin, o tanggalin ang mga commit habang isinasagawa ang proseso.
Ginagamit mo ang karaniwang rebase, halimbawa, gamit ang git rebase master o git rebase origin/developDito, mekanikal na inilalapat ng Git ang bawat commit mula sa iyong branch patungo sa bagong base at humihinto lamang kung may mga conflict, kung saan sa puntong iyon ay mamamagitan ka upang malutas ang mga ito at magpatuloy. git rebase --continue.
Ang interactive rebasing ay pinapagana gamit ang opsyong -i , na karaniwang tumutukoy sa isang hanay ng mga commit mula sa dulo ng branch pabalik. Halimbawa:
git rebase -i HEAD~5
Sinasabi nito sa Git na gusto mong "maglaro" gamit ang huling limang commit. Ang iyong text editor na naka-configure para sa Git (karaniwan ay vim o nano bilang default) ay magbubukas na may listahan ng mga commit na iyon, na ang bawat isa ay may salitang ` pick` na sinusundan . Dito mo maaaring palitan ang `pick` ng iba pang mga tagubilin upang muling isulat ang history ayon sa gusto mo.
Ang interaktibong pamamaraang ito ay dinisenyo upang pakinisin ang isang serye ng mga commit bago ibahagi ang mga ito: pagsasama-sama ng mga maliliit na pagbabago, pagwawasto ng mga mensahe, paghahati ng mga napakalaking commit, o direktang pag-aalis ng mga commit na hindi dapat umabot sa malayong repositoryo.
Mga karagdagang utos sa muling pagsasaayos sa interactive na rebase
Sa file na bubukas git rebase -i Makakakita ka ng ganito:
pick 1fc6c95 Patch A
pick 6b2481b Patch B
pick dd1475d something I want to split
pick c619268 A fix for Patch B
pick fa39187 something to add to patch A
pick 4ca2acc i cant' typ goods
pick 7b36971 something to move before patch B
Ang ideya ay maaari mong palitan ang `pick` ng iba pang mga utos upang baguhin kung paano pinangangasiwaan ang bawat commit habang isinasagawa ang rebase. Ang mga pinakakaraniwan ay:
- pumili (p)Gamitin ang commit kung ano ito.
- muling salita (r): Ilapat ang commit ngunit huminto upang baguhin ang mensahe.
- baguhin (e)Ilapat ang commit at stop para mabago mo ang mga nilalaman nito (halimbawa, pagdaragdag o pag-alis ng mga file) gamit ang
git commit --amend. - kalabasa: pinagsasama ang commit na ito sa nauna at pinapayagan ang pag-edit ng pinagsamang mensahe.
- pag-aayos (f): katulad ng squash, ngunit itinatapon ang mensahe mula sa commit na ito at pinapanatili ang isa mula sa nauna.
- patak (d): tinatanggal ang commit na ito mula sa history.
Sa halimbawa sa itaas, maaari mong, halimbawa, pagsamahin ang isang commit na nagtatama sa nauna , ilipat ang isa pataas, hatiin ang isang malaki, at itama ang isang mensaheng mali ang baybay. Ang na-edit na file ay maaaring magmukhang ganito:
pick 1fc6c95 Patch A
squash fa39187 something to add to patch A
pick 7b36971 something to move before patch B
pick 6b2481b Patch B
fixup c619268 A fix for Patch B
edit dd1475d something I want to split
reword 4ca2acc i cant' typ goods
Kapag na-save at isinara mo ang editor, sisimulan ng Git na isagawa ang mga utos na ito nang sunod-sunod, at hihinto kapag kailangan nito ng iyong interbensyon (halimbawa, para kumpirmahin ang mensaheng nagreresulta mula sa isang kalabasa(para makagawa ka ng mga pagbabago sa pamamagitan ng pag-edit o muling pagsulat ng mensahe sa reword). Ipinapakita ka ng bawat hintuan sa pandulo kung ano ang dapat mong gawin at ipaalala sa iyo na, kapag tapos ka na, dapat kang tumakbo git rebase --continue.
Sa isang punto, magbubukas ang Git ng isang file na may nilalamang katulad ng:
# This is a combination of two commits.
# The first commit's message is:
Patch A
# This is the 2nd commit message:
something to add to patch A
Maaari mong iwanang walang pagbabago ang pinagsamang mensahe o i-edit ito upang mas maipakita ang pinagsamang pagbabago . Muli, i-save, isara ang editor, at magpapatuloy ang rebase hanggang sa maproseso ang lahat ng command.
Buod ng Daloy ng Interactive Rebase
Ang kumpletong proseso ng isang interactive rebase ay karaniwang sumusunod sa ganitong pattern: una, pipiliin mo ang commit range (halimbawa , HEAD~7 ), bubuksan ng Git ang file na naglalaman ng listahan ng mga commit, at ie-edit mo ang mga command at line order upang tumugma sa history na gusto mong makamit. Pagkatapos i-save, uulitin ng Git ang bawat instruksyon, hihinto kung saan kinakailangan, at kapag naabot mo na ang dulo nang walang mga error , ang iyong branch ay magkakaroon ng ganap na binagong history.
Sa tuwing humihinto ito, maging para sa isang i-edit o dahil sa isang conflict sa merge, maaari mong baguhin ang mga file, gamitin git add, gumawa ng git commit --amend Kung naaangkop, at kapag nasiyahan ka na sa kondisyon, ibalik sa git rebase --continueKung nakagawa ka ng isang malubhang pagkakamali o napagtanto mong nagulo ang iyong sarili, maaari kang magpalaglag anumang oras gamit ang git rebase --abort bumalik sa estado bago simulan ang maniobra ng pag-overtake.
Ang karaniwang resulta ng matalinong paggamit ng interactive rebasing ay isang mas lohikal at nababasang serye ng mga commit: mas kaunting ingay, mas kaunting "mga typo na naayos," mas kaunting paulit-ulit na commit , at mas malinaw na mga mensahe. Ginagawa nitong mas madali ang pagsusuri sa history, pag-unawa sa kung ano ang binago at bakit, at pagsasagawa ng bisecting o debugging sa hinaharap.
Mga kapaki-pakinabang na opsyon sa pag-configure para sa rebase
Ang Git ay may ilang mga opsyon sa pag-configure na nakakaapekto sa pag-uugali ng rebase at maaaring gawing mas madali ang iyong buhay kung regular mo itong gagamitin. Isa sa mga pinakakilala ay ang nagpapahintulot sa `git pull` na gamitin ang rebase sa halip na merge bilang default:
git config --global pull.rebase true
Gamit ito, sa tuwing gagawin mo git pullSusubukan ng Git na i-overwrite ang iyong mga lokal na pagbabago gamit ang mga bagong commit mula sa remote sa halip na lumikha ng isang merge commit. Ito ay isang maginhawang paraan upang mapanatili isang linear na lokal na kasaysayan nang hindi kinakailangang tandaan na laging magsulat git pull --rebase.
Maaari mo ring isaayos ang editor para sa interactive mode, i-configure ang mga alias para sa mahahabang rebase command, o i-activate ang mga opsyon tulad ng autostash sa ilang partikular na stream, bagama't ipinapayong gamitin ang mga ito nang maingat upang hindi makalimutan ang ginagawa ng Git sa iyong mga hindi naka-commit na pagbabago.
Aplikasyon para sa advanced na reorganisasyon
Kapag na-master mo na ang basic at interactive rebasing, maaari mo na itong simulang gamitin sa mas advanced na mga senaryo, tulad ng kapag mayroon kang ilang dependent branch at gusto mong i-rebase ang mga ito nang hindi nakakaabala sa master branch. Halimbawa, maaaring mayroon kang client branch at server branch na umaasa sa isa't isa, at pagkatapos ng ilang pagbabago, gusto mong pareho itong nakabatay sa isang master branch na nagsasama na ng ilang partikular na refactoring.
Sa ganitong sitwasyon, maaari mo munang i-overwrite ang client sa master, i-advance ang master gamit ang fast-forward, at pagkatapos ay i-overwrite ang server sa bagong master . Tinitiyak ng ganitong uri ng maniobra na malinaw na ipinapakita ng history kung aling mga pagbabago ang nabibilang sa bawat branch at sa anong lohikal na pagkakasunud-sunod ang mga ito ay inilapat, nang walang kadena ng mga cross-merge.
Posible ring "muling ayusin ang isang reorganisasyon": kung may isang taong nag-overwrite sa isang branch at kailangan mong i-overwrite ang muling isinulat na history gamit ang sarili mong gawa, pinapayagan ka ng Git na gawin ito, bagama't pinapataas nito ang posibilidad ng mga conflict at kalituhan . Sa mga collaborative environment, ipinapayong planuhin nang mabuti ang mga operasyong ito at, kung kinakailangan, gumamit ng mga history diagram upang maiwasan ang pagkaligaw.
Pag-unawa sa mga panganib ng muling pagsasaayos
Ang pinakamalaking panganib ng rebasing ay nakasalalay sa mismong kabutihan nito: binabago nito ang kasaysayan . Mahusay iyan para sa pagpapaganda ng mga bagay-bagay, ngunit para itong tabak na may dalawang talim kung ang mga commit ay nailathala na o kung maraming tao ang umaasa sa mga ito para sa kanilang pang-araw-araw na gawain.
Isipin mong nag-clone ka ng isang repository at nagsimulang magtrabaho sa iyong lokal na branch habang ang ibang mga kasamahan ay patuloy na nagpo-push ng mga pagbabago sa pangunahing branch. Kung ang isa sa kanila ay magdesisyong i-rebase ang pangunahing branch na iyon at pilitin ang isang push, ang mga commit na iyong ginagamit bilang base ay maaaring mawala mula sa remote repository o mabago ang kanilang mga hash. Mula sa iyong lokal na pananaw, ang iyong kwento ay nagsasabi ng isang kwento; mula sa remote repository, ito ay nagsasabi ng isa pa.
Kapag sinubukan mong magsagawa ng pull o push, mapipilitan ang Git na pagtugmain ang dalawang hindi magkatugmang history at maaaring humantong sa paglikha ng kakaibang merge o pagtanggi sa push. Madalas kang magkakaroon ng mga duplicate na commit, na may parehong nilalaman ngunit magkakaibang hash, at mas masalimuot na history kaysa sa iyong sinimulan.
Isa pang panganib ay iyon pagkawala ng impormasyon dahil sa isang walang ingat na sapilitang pagtulakKung, habang isinusulat mo muli ang kasaysayan, may ibang taong gumawa ng mga lehitimong commit sa remote machine, git push --force Maaari mo lang i-overwrite ang mga pagbabagong iyon at alisin ang mga ito. Ang pagbawi sa mga ito ay maaaring mangailangan ng maraming oras at kaalaman sa mga reflog, maliban na lang kung masyadong matagal na ang lumipas.
Dahil sa lahat ng mga kadahilanang ito, ang rebalancing ay itinuturing na isang "kamangha-manghang" kasangkapan, ngunit isa na dapat gamitin nang matalino. Sa indibidwal na antas, pinapayagan ka nitong mapanatili ang isang malinis na rekord; sa antas ng pangkat, kung gagamitin nang mali, maaari nitong magambala ang pagtutulungan ng magkakasama at lumikha ng mga mahirap lutasin na alitan.
Pagbangon mula sa isang mas mataas na antas ng reorganisasyon
Kung ang isang rebase ay lumala, ang unang dapat gawin ay huwag mag-panic. Ang Git ay nagtatago ng isang log na tinatawag na reflog na nag-iimbak ng mga nakaraang posisyon ng mga sanggunian (tulad ng HEAD) nang ilang sandali. Nangangahulugan ito na kahit na na-overwrite mo na ang mga commit, maaari mo pa ring ma-access ang mga ito at maibalik ang dating estado.
Sa kalagitnaan ng isang maling maniobra sa pag-overtake, ang pinakamabilis na gawin ay karaniwang:
git rebase --abort
Gamit ito, susubukan ng Git na ibalik ka sa eksaktong punto kung saan mo sinimulan ang operasyon ng rebase, na parang hindi mo pa nasimulan. Ito ay mainam kapag, halimbawa, nasumpungan mo ang iyong sarili sa isang walang katapusang kadena ng mga tunggalian at napagpasyahan mong hindi na sulit na ipagpatuloy ang landas na iyon.
Kung ang problema ay natapos mo na ang rebase at nagsagawa ka pa ng forced push, mas magiging kumplikado ang mga bagay-bagay. Sa lokal, maaari mong gamitin ang git reflog para mahanap ang hash ng commit na kinaroroonan mo bago ang rebase at, kapag nakuha mo na ito, gawin ang isang git reset --hard hanggang sa puntong iyon. Gayunpaman, kung na-overwrite mo na ang remote at ang iba pang mga clone ay na-update na, Ang pagbabalik ay nangangailangan ng koordinasyon mula sa buong pangkat at, sa ilang mga kaso, tanggapin na ang bahagi ng akda ay "nawala" sa diwa na hindi na ito bahagi ng opisyal na kasaysayan.
Kapag ang isang error sa rebase ay nakakaapekto sa maraming tao, ang praktikal na solusyon ay karaniwang kinabibilangan ng pagsang-ayon sa isang bagong panimulang punto sa isang branch (halimbawa, paglikha ng isang bagong branch mula sa isang malusog na commit) at pagkuha ng mga pagbabago mula sa mga apektadong branch , alinman sa pamamagitan ng pagpili ng mga opsyon o paglalapat ng mga patch. Ito ay isang abala, ngunit sa pangkalahatan ay mas mainam ito kaysa sa pagtatangkang "mahiwagang i-undo" ang isang ibinahaging kasaysayan na nabago na nang ilang beses.
Pagsamahin ang mga conflict sa rebase
Ang mga conflict sa merge habang nasa rebase ay gumagana nang katulad ng sa mga nasa normal na merge, maliban sa lumalabas na commit by commit ang mga ito. Sa tuwing susubukan ng Git na mag-apply ng commit at matutukoy na ang parehong fragment ng isang file ay nagbago sa isang hindi tugmang paraan sa base, mamarkahan nito ang conflict sa mga file.
Sa loob ng file, makakakita ka ng mga delimiter tulad ng:
<<<<<<< HEAD
contenido de tu rama actual
=======
contenido de la rama rebasada
>>>>>>> updated_address
Sa pagitan ng <<<<<<< HEAD at ======= mayroon kang nilalaman ng isang bersyon, at sa pagitan ng ======= at >>>>>>> ang isa pa. Ang iyong gawain ay i-edit ang file, pinapanatili lamang ang kumbinasyon na akma para sa proyekto at inaalis ang mga linya ng bookmark na iyon.
Kapag naayos na ang nilalaman sa lahat ng apektadong file, gagamitin mo ang git add <archivo> para markahan ang mga salungatan bilang nalutas na. Pagkatapos ay patakbuhin mo git rebase --continue para makapunta ang Git sa susunod na commit sa serye. Kung makatagpo ka ng conflict na hindi na kailangang lutasin para sa partikular na commit na iyon, mayroon ka ring mga opsyon tulad ng git rebase --skip laktawan ito, bagama't ipinahihiwatig nito ganap na alisin ang commit na iyon ng nagresultang kasaysayan.
Dahil ang rebasing ay naglalapat ng mga commit nang sunud-sunod, sa mga branch na may maraming pagbabago at malalaking pagkakaiba mula sa base, maaari itong maging nakakapagod: ang bawat commit na dumadampi sa parehong magkasalungat na piraso ng code ay pipilitin kang ayusin ito. Sa ganitong mga kaso, ang isang normal na pagsasama o muling pagsasaayos ng mga pagbabago upang mabawasan ang conflict surface ay maaaring maging mas mahusay.
I-rebase ang Git, i-push –force at i-push –force-with-lease
Sa tuwing isusulat mo muli ang kasaysayan ng isang sangay at ang sangay na iyon ay konektado sa isang remote, makakaranas ka ng mga security check ng Git: kung ang remote ay may ibang kasaysayan, isang simpleng git push Tatanggihan ito. Para mapalitan ang kuwentong iyan, kailangan mo ng sapilitang pagtulak.
Mayroong dalawang karaniwang baryasyon: git push --force y git push --force-with-leaseAng una ay nag-o-overwrite nang hindi nagtatanong, habang ang pangalawa ay nagdaragdag ng isang uri ng "safety net" upang maiwasan pag-override sa mga commit ng ibang tao. May --force-with-leaseSinusuri ng Git na ang remote ay nakaturo pa rin sa commit na iyong nilikha; kung may nagbago ng branch sa server habang isinusulat mo muli ang iyong lokal na kasaysayan, ang push ay tatanggihan.
Isaalang-alang ang senaryo kung saan mayroon kang pagkakasunod-sunod ng mga commit sa malayong branch at napagpasyahan mong mali ang isa (halimbawa, c2). Sa lokal na paraan, isusulat mo ito muli, bubuo ng mga bagong commit (c3, c4), at gusto mong maging bagong realidad ang mga ito. Kung walang ibang nakahawak sa branch, ang isang push gamit ang `--force-with-lease` ay mag-a-update sa malayong branch nang walang problema. Gayunpaman, kung may nagdagdag, halimbawa, ng isang commit c5 habang inihahanda mo ang iyong mga pagbabago, pipigilan ka ng flag na ito na aksidenteng ma-overwrite ang kanilang trabaho.
Sa buod, kung napag-isip-isip mo na na kailangan mong pilitin ang isang push pagkatapos ng isang rebase, ang karaniwang paraan ay ang paggamit ng git push --force-with-lease maliban na lang kung mayroon kang isang napaka-tiyak na dahilan kung bakit mo gustong isulat muli ang lahat sa --forceGayunpaman, ipinapayong ipaalam pa rin ito sa pangkat at i-coordinate ang tiyempo upang mabawasan ang mga alitan.
Rebase, mga konteksto ng branch, at daloy ng trabaho
Isa pang kawili-wiling paraan upang maunawaan ang rebase ay ang pag-iisip ng mga branch bilang mga kontekstong nagtatrabaho na nagbabahagi ng isang bahagi ng kasaysayan ngunit pagkatapos ay umuusad sa magkahiwalay na landas. Halimbawa, kung susundin mo ang isang git-flow workflow, maaaring mayroon kang isang develop branch kung saan nalilikha ang mga functional branch (A1, A2, atbp.).
Kapag nasa konteksto ka ng A1, anumang gagawin mo roon ay hindi makakaapekto sa develop hangga't hindi ka nagsasagawa ng merge o rebase. Para itong pagkakaroon ng dalawang parallel timeline na may parehong pinagmulan ngunit nag-iipon ng magkakaibang pagbabago. Sa isang merge, pinagsasama mo ang mga timeline na ito, at itinatala ng Git ang isang commit kung saan sila nagtatagpo; sa isang rebase, inaayos mo muli ang A1 timeline upang magmukhang palaging ilang hakbang ang nauuna kaysa sa develop.
Kung habang nagde-develop si Pepe ay nagtatrabaho sa develop at si Nacho naman sa A1, darating ang panahon na ang develop ay magkakaroon ng mga bagong commit at ang A1 ay magkakaroon din ng mga bagong commit. Kung nais ni Nacho na maiwasan ang isang merge commit kapag isinasama ang A1 sa develop, magagawa niya ang mga sumusunod:
git checkout A1
git rebase develop
Dadalhin ng Git ang mga commit mula sa develop "sa ilalim" ng mga mula sa A1, muling isusulat ang history ng A1 upang lumitaw ang mga pagbabago nito sa ibabaw ng pinakabagong bersyon ng develop. Kung titingnan ang history, tila palaging umaasa ang Nacho sa pinakabagong estado ng develop, kahit na hindi naman talaga iyon ang kaso sa real time.
Ang ganitong uri ng daloy ng trabaho ay napaka-maginhawa kapag nagtatrabaho ka nang mag-isa o kapag ang A1 branch ay hindi pa naibabahagi. Lumilitaw ang problema kapag ang A1 ay nasa remote server na at ang ibang miyembro ng team ay nag-push na nito. Kung irebase ni Nacho ang A1 sa develop branch at pagkatapos ay pinipilit ang isang push, puputulin niya ang link sa pagitan ng remote na bersyon at ng lokal na bersyon na mayroon ang lahat, na pinipilit silang mag-synchronize sa isang story na hindi na katulad ng dati.
Pagbangon at mga nagresultang tunggalian sa pagtutulungan
Sa isang collaborative scenario, tulad ng aming inilarawan, ang interaksyon sa pagitan ng rebasing at ng mga lokal na repositoryo ng bawat tao ay maaaring maging maselan. Kapag nirebase ni Nacho ang A1, nireresolba niya ang mga conflict nang lokal at, nasiyahan sa resulta, nagsasagawa ng git push --force-with-leaseAng remote ngayon ay sumasalamin sa bago at muling isinulat na kasaysayan.
Samantala, ginagamit pa rin ni Pepe ang kanyang lokal na kopya ng A1, na nasa pre-rebase version pa rin. Kung kukunin o susubukan ni Pepe na i-push ang mga pagbabago, matutukoy ng Git na ang kanyang history ay naiiba sa remote . Sa pinakamagandang sitwasyon, kakailanganin niyang i-reset ang kanyang lokal na branch sa bagong remote HEAD at muling ilapat ang kanyang mga pagbabago; sa pinakamasamang sitwasyon, maaari siyang mawalan ng trabaho kung hindi siya mag-iingat at magsasagawa ng hard reset nang hindi nagse-save ng kahit ano.
Samakatuwid, kapag binabago ang base ng isang shared branch, mahalagang malinaw na ipaalam sa iba pang miyembro ng team na tahasang i-update ang kanilang local branch , halimbawa gamit ang:
git fetch origin
git checkout A1
git reset --hard origin/A1
Ang mga ganitong uri ng operasyon ay dapat na maging eksepsiyon, hindi ang panuntunan. Para sa pang-araw-araw na paggamit, karaniwang pinakamahusay na limitahan ang rebasing sa mga personal na feature branch at iwanan ang mga shared branch (develop, master) na may merge-based history, na hindi sumisira sa mga local clone ng sinuman.
Tungkol sa mga conflict na lumilitaw sa panahon ng isang rebase, ang proseso ay palaging pareho: Ipinapakita ng Git ang bawat conflict commit sa pamamagitan ng commit, ie-edit mo ang mga kasangkot na file, at minarkahan ang mga pagbabago bilang nalutas gamit ang git add at ipagpatuloy mo ang git rebase --continueKung, sa anumang kadahilanan, ang sitwasyon ay maging hindi na makontrol, maaari mong ihinto at pag-isipang muli ang estratehiya.
Interactive na rebase: kasiyahan at paglilinis para sa lahat
Bagama't maikli lamang itong nabanggit sa maraming tutorial, ang interactive rebate mode ay isa sa mga pinakamahusay na tool para sa paglikha ng isang history. malinis, pare-pareho at madaling repasuhin. May git rebase -i Sa isang sesyon lamang, maaari mong pagsamahin ang maliliit na commit, itama ang mga mensahe, at ilipat ang mga commit pataas o pababa. oras, hatiin ang isang malaking commit sa ilan pang mas lohikal, o burahin na lang ang mga pagbabagong walang katuturan.
Halimbawa, kung gusto mong pinuhin ang huling pitong commit, patakbuhin mo ang:
git rebase --interactive HEAD~7
Magbubukas ang iyong editor kasama ang listahan ng pitong commit na iyon. Mula doon, maaari kang magpasya kung ang isang partikular na commit na may maliliit na pag-aayos ay dapat pagsamahin sa orihinal na commit ng functionality (gamit ang squash o fixup ), kung ang isa pang commit ay dapat ilipat bago ang "Patch B", kung ang isang ikatlong commit ay dapat hatiin sa dalawa gamit ang edit , o kung ang isang mensahe na may mga typo ay dapat itama gamit ang reword.
Ang maganda rito ay matapos ang lahat ng gawaing ito. bago ibahagi ang mga pagbabago kasama ang ibang bahagi ng mundo, kaya ang naaabot ng remote team ay isa nang medyo malinis na rekord. Hindi lang ito mukhang mas maganda: mas pinapadali nito para sa ibang developer na suriin ang iyong mga commit, maunawaan agad kung ano ang kontribusyon ng bawat isa, at, kung kinakailangan, gumamit ng mga tool tulad ng git bisect para mahanap ang eksaktong punto kung saan naipakilala ang isang bug.
Gayunpaman, mahalagang tandaan ang lumang tuntunin: anumang gagawin mo sa interactive rebasing rewrites ay nagko-commit ng mga hash. Gamitin ito nang matipid sa mga branch na umiiral lamang sa iyong makina , at nang may matinding pag-iingat sa anumang branch na nailipat na sa isang remote server.
Sa madaling salita, ang rebase (at lalo na ang interactive mode nito) ay isang uri ng "history editor" para sa Git. Kapag ginamit nang tama, nagbibigay-daan ito sa iyong mapanatili ang isang repository na may madaling basahin at propesyonal na history; kapag ginamit nang hindi tama, maaari itong magdulot ng kalituhan at sakit ng ulo, lalo na kapag pinaghahalo nito ang mga nakabahagi nang branch at pinipilit ang mga pag-push nang walang koordinasyon.
Ang pag-master sa command na ito ay nangangailangan ng oras, ngunit kapag naunawaan mo na nang eksakto kung ano ang ginagawa nito sa iyong mga commit, ito ay magiging isang mahalagang tool para sa pagtatrabaho sa mga branch, pagpapanatiling malinis ng mga history, at maayos na pakikipagtulungan sa mga proyekto ng anumang laki.
Talatuntunan
- 1 Ano ang Git rebase?
- 2 Rebase laban sa merge: parehong layunin, magkaibang landas
- 3 Pangunahing paggamit ng Git rebase
- 4 Huwag muling ayusin ang pampublikong talaan
- 5 Karaniwang Git rebase kumpara sa interactive na Git rebase
- 6 Pag-unawa sa mga panganib ng muling pagsasaayos
- 7 Pagbangon mula sa isang mas mataas na antas ng reorganisasyon
- 8 Pagsamahin ang mga conflict sa rebase
- 9 I-rebase ang Git, i-push –force at i-push –force-with-lease
- 10 Rebase, mga konteksto ng branch, at daloy ng trabaho
- 11 Pagbangon at mga nagresultang tunggalian sa pagtutulungan
- 12 Interactive na rebase: kasiyahan at paglilinis para sa lahat