Git Pull Force - Kako prepisati lokalne spremembe z Git

Ko se naučite kodirati, prej ali slej spoznate tudi sisteme za nadzor različic. In čeprav je v tem prostoru veliko konkurenčnih orodij, je eno od njih dejanski standard, ki ga uporabljajo skoraj vsi v panogi. Tako priljubljeno je, da obstajajo podjetja, ki njegovo ime uporabljajo pri svojih blagovnih znamkah. Govorimo seveda o Gitu.

Čeprav je Git močno orodje, je njegova moč dobro skrita. Obstaja nekaj bistvenih konceptov, ki jih morate razumeti, da boste Git zares usposobljeni. Dobra novica je, da ko se jih enkrat naučite, skoraj nikoli ne boste naleteli na težave, ki jim ne morete ubežati.

Tipičen potek dela

V običajnem delovnem toku Git boste uporabljali lokalno repozitorij, oddaljeno repozitorij in eno ali več vej. Repozitoriji hranijo vse informacije o projektu, vključno z njegovo celotno zgodovino in vsemi vejami. Podružnica je v bistvu zbirka sprememb, ki vodijo od praznega projekta do trenutnega stanja.

Po kloniranju repozitorija delate na lokalni kopiji in uvedete nove spremembe. Dokler ne potisnete lokalnih sprememb v oddaljeni repozitorij, je vse vaše delo na voljo samo v vaši napravi.

Ko končate opravilo, je čas za sinhronizacijo z oddaljenim skladiščem. Želite potegniti oddaljene spremembe, da boste sledili napredku projekta, lokalne spremembe pa želite deliti z drugimi.

Lokalne spremembe

Vse skupaj je dobro, ko vi in ​​ostala ekipa delate na popolnoma ločenih datotekah. Karkoli se bo zgodilo, drug drugemu ne bosta stopila na noge.

Vendar se včasih zgodi, da vi in ​​vaši soigralci hkrati uvajate spremembe na istem mestu. In tu se težave običajno začnejo.

Ste že kdaj usmrtili git pullsamo zato, da bi videli strašljive error: Your local changes to the following files would be overwritten by merge:? Prej ali slej vsi naletijo na to težavo.

Tu je še bolj zmedeno, da ne želite ničesar združiti, ampak samo potegnite, kajne? Pravzaprav je vlečenje nekoliko bolj zapleteno, kot ste morda mislili.

Kako natančno deluje Git Pull?

Vlečenje ni niti ena operacija. Sestavljen je iz pridobivanja podatkov z oddaljenega strežnika in nato združevanja sprememb z lokalnim repozitorijem. Ti dve operaciji lahko izvedete ročno, če želite:

git fetch git merge origin/$CURRENT_BRANCH

Za origin/$CURRENT_BRANCHdel sredstev, ki:

  • Git bo spojil spremembe iz oddaljenega repozitorija z imenom origin(tistega, iz katerega ste klonirali)
  • ki so bili dodani v $CURRENT_BRANCH
  • ki še niso prisotni v vaši lokalni odjavljeni veji

Ker Git spajanja izvaja le, kadar ni nobenih nepovezanih sprememb, git pullbi vas lahko vsakič, ko zaženete z neobveznimi spremembami, spravljate v težave. Na srečo obstajajo načini, kako se iz težav rešiti v enem kosu!

Smo družina

Različni pristopi

Ko imate nedovoljene lokalne spremembe in še vedno želite potegniti novo različico z oddaljenega strežnika, vaš primer uporabe običajno spada v enega od naslednjih scenarijev. Ali:

  • vas ne zanimajo lokalne spremembe in jih želite prepisati,
  • vas zelo zanimajo spremembe in bi jih radi uporabili po oddaljenih spremembah,
  • želite prenesti oddaljene spremembe, vendar jih še ne uporabite

Vsak od pristopov zahteva drugačno rešitev.

Ne zanimajo vas lokalne spremembe

V tem primeru želite samo opustiti vse nedovoljene lokalne spremembe. Morda ste datoteko spremenili za preizkus, vendar je ne potrebujete več. Vse, kar vas zanima, je, da ste na tekočem z zgornjim tokom.

To pomeni, da dodate še en korak med pridobivanjem oddaljenih sprememb in njihovim združevanjem. Ta korak bo vejo ponastavil v nespremenjeno stanje in tako omogočil git mergedelo.

git fetch git reset --hard HEAD git merge origin/$CURRENT_BRANCH

Če ne želite, da vtipkate ime podružnica vsakič, ko zaženete ta ukaz, Git je lepo bližnjico, ki kažejo na podružnice nabavnem: @{u}. Gornja veja je veja v oddaljenem repozitoriju, ki jo potisnete in iz nje prenesete.

Tako bi izgledali zgornji ukazi z bližnjico:

git fetch git reset --hard HEAD git merge '@{u}'

V primeru navajamo bližnjico, da lupini preprečimo njeno interpretacijo.

Zelo vas skrbi za lokalne spremembe

Ko so vaše neizvedene spremembe pomembne za vas, obstajata dve možnosti. Lahko jih zavežete in nato izvedete git pullali pa jih shranite.

Skrivanje pomeni, da spremembe za trenutek pospravimo, da jih pozneje vrnemo. Natančneje, git stashustvari objavo, ki ni vidna na vaši trenutni veji, vendar je Git še vedno dostopen do nje.

Če želite vrniti spremembe, shranjene v zadnjem skladišču, uporabite git stash popukaz. Po uspešni uporabi skritih sprememb ta ukaz tudi odstrani skrito objavo, ker ni več potreben.

Potek dela bi lahko bil videti takole:

git fetch git stash git merge '@{u}' git stash pop

Privzeto bodo spremembe iz zaloge postale postopne. Če jih želite odstraniti, uporabite ukaz git restore --staged(če uporabljate Git novejši od 2.25.0).

Samo želite prenesti oddaljene spremembe

Zadnji scenarij se nekoliko razlikuje od prejšnjih. Recimo, da ste sredi zelo neurejenega preoblikovanja. Niti izguba sprememb niti njihovo skrivanje ni možnost. Kljub temu pa še vedno želite imeti na voljo oddaljene spremembe, ki bi jih lahko izvajali git diff.

Kot ste verjetno že ugotovili, prenos oddaljenih sprememb sploh ni potreben git pull! git fetchje dovolj.

One thing to note is that by default, git fetch will only bring you changes from the current branch. To get all the changes from all the branches, use git fetch --all. And if you'd like to clean up some of the branches that no longer exist in the remote repository, git fetch --all --prune will do the cleaning up!

Some Automation

Have you heard of Git Config? It's a file where Git stores all of the user-configured settings. It resides in your home directory: either as ~/.gitconfig or ~/.config/git/config. You can edit it to add some custom aliases that will be understood as Git commands.

For example, to have a shortcut equivalent to git diff --cached (that shows the difference between the current branch and the staged files), you'd add the following section:

[alias] dc = diff --cached

After that, you can run git dc whenever you wish to review the changes. Going this way, we can set up a few aliases related to the previous use cases.

[alias] pull_force = !"git fetch --all; git reset --hard HEAD; git merge @{u}" pf = pull_force pull_stash = !"git fetch --all; git stash; git merge @{u}; git stash pop"

This way, running git pull_force will overwrite the local changes, while git pull_stash will preserve them.

The Other Git Pull Force

Curious minds may have already discovered that there is such a thing as git pull --force. However, this is a very different beast to what's presented in this article.

It may sound like something that would help us overwrite local changes. Instead, it lets us fetch the changes from one remote branch to a different local branch. git pull --force only modifies the behavior of the fetching part. It is therefore equivalent to git fetch --force.

Like git push, git fetch allows us to specify which local and remote branch do we want to operate on. git fetch origin/feature-1:my-feature will mean that the changes in the feature-1 branch from the remote repository will end up visible on the local branch my-feature. When such an operation modifies the existing history, it is not permitted by Git without an explicit --force parameter.

Just like git push --force allows overwriting remote branches, git fetch --force (or git pull --force) allows overwriting local branches. It is always used with source and destination branches mentioned as parameters. An alternative approach to overwriting local changes using git --pull force could be git pull --force "@{u}:HEAD".

Conclusion

Svet Gita je prostran. Ta članek je zajemal le enega od vidikov vzdrževanja repozitorija: vključevanje oddaljenih sprememb v lokalno repozitorij. Tudi ta vsakdanji scenarij je od nas zahteval nekoliko bolj poglobljen pregled notranjih mehanizmov tega orodja za nadzor različic.

Učenje primerov dejanske uporabe vam pomaga bolje razumeti, kako Git deluje pod pokrovom. Zaradi tega se boste počutili pooblaščene, kadar koli se znajdete v težavah. Vsi to počnemo od časa do časa.