Git Pull Force - Sådan overskrives lokale ændringer med Git

Når du lærer at kode, lærer du før eller senere også om versionskontrolsystemer. Og mens der er mange konkurrerende værktøjer i dette rum, er en af ​​dem de facto-standarden, der bruges af næsten alle i branchen. Det er så populært, at der er virksomheder, der bruger navnet i deres branding. Vi taler selvfølgelig om Git.

Mens Git er et kraftfuldt værktøj, er dets kraft godt skjult. Der er nogle vigtige begreber, som du skal forstå for at blive virkelig dygtige med Git. Den gode nyhed er, at når du først har lært dem, løber du næppe nogensinde i problemer, du ikke kan flygte fra.

Den typiske arbejdsgang

I en typisk Git-arbejdsgang bruger du et lokalt arkiv, et eksternt lager og en eller flere grene. Repositories gemmer alle oplysninger om projektet, inklusive hele dets historie og alle filialer. En gren er dybest set en samling af ændringer, der fører fra et tomt projekt til den aktuelle tilstand.

Efter kloning af et arkiv arbejder du på din lokale kopi og introducerer nye ændringer. Indtil du skubber lokale ændringer til fjernlageret, er alt dit arbejde kun tilgængeligt på din maskine.

Når du er færdig med en opgave, er det tid til at synkronisere med fjernlageret. Du vil trække fjernændringerne for at holde trit med projektets fremskridt, og du vil skubbe de lokale ændringer for at dele dit arbejde med andre.

Lokale ændringer

Alt er godt, når du og resten af ​​dit team arbejder på helt separate filer. Uanset hvad der sker, træder du ikke på hinandens fødder.

Der er dog tidspunkter, hvor du og dine holdkammerater samtidigt introducerer ændringer samme sted. Og det er normalt her, problemerne begynder.

Har du nogensinde git pullkun henrettet for at se de frygtede error: Your local changes to the following files would be overwritten by merge:? Før eller senere løber alle ind i dette problem.

Hvad der er mere forvirrende her er, at du ikke vil flette noget, bare træk, ikke? Faktisk er pull lidt mere kompliceret end du måske havde troet.

Hvor præcist fungerer Git Pull?

Træk er ikke en enkelt handling. Den består i at hente data fra fjernserveren og derefter flette ændringerne med det lokale lager. Disse to operationer kan udføres manuelt, hvis du vil:

git fetch git merge origin/$CURRENT_BRANCH

De origin/$CURRENT_BRANCHdel betyder, at:

  • Git vil flette ændringerne fra det navngivne eksterne lager origin(det du klonede fra)
  • der er føjet til $CURRENT_BRANCH
  • der ikke allerede er til stede i din lokale udtjente filial

Da Git kun udfører fusioner, når der ikke er uforpligtede ændringer, kan hver gang du løber git pullmed uforpligtede ændringer få dig i problemer. Heldigvis er der måder at komme ud af problemer i ét stykke!

Vi er familie

Forskellige tilgange

Når du ikke har forpligtet lokale ændringer og stadig vil hente en ny version fra fjernserveren, falder din brugssag typisk i et af følgende scenarier. Enten:

  • du er ligeglad med de lokale ændringer og vil overskrive dem,
  • du holder meget af ændringerne og vil gerne anvende dem efter fjernændringerne,
  • du vil downloade fjernændringerne, men ikke anvende dem endnu

Hver af fremgangsmåderne kræver en anden løsning.

Du er ligeglad med de lokale ændringer

I dette tilfælde vil du bare slippe alle de ikke-forpligtede lokale ændringer. Måske har du ændret en fil for at eksperimentere, men du har ikke længere brug for ændringen. Alt hvad du holder af er at være opdateret med opstrøms.

Dette betyder, at du tilføjer endnu et trin mellem at hente fjernændringerne og flette dem. Dette trin nulstiller filialen til sin umodificerede tilstand, hvilket gør det muligt git mergeat arbejde.

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

Hvis du ikke ønsker at skrive under branche navn, hver gang du kører denne kommando, Git har en dejlig genvej peger på den opstrøms gren: @{u}. En gren opstrøms er den gren i det eksterne lager, som du skubber til og henter fra.

Sådan ser ovenstående kommandoer ud med genvejen:

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

Vi citerer genvejen i eksemplet for at forhindre, at skallen fortolker den.

Du holder meget af de lokale ændringer

Når dine uforpligtede ændringer er vigtige for dig, er der to muligheder. Du kan begå dem og derefter udføre git pull, eller du kan gemme dem.

Stashing betyder at lægge ændringerne væk et øjeblik for at bringe dem tilbage senere. For at være mere præcis git stashopretter du en forpligtelse, der ikke er synlig på din nuværende gren, men som stadig er tilgængelig af Git.

For at bringe de ændringer, der er gemt i sidste stash, tilbage, skal du bruge git stash popkommandoen. Efter at have anvendt de lagrede ændringer med succes fjerner denne kommando også stash-forpligtelsen, da den ikke længere er nødvendig.

Workflowet kunne derefter se sådan ud:

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

Ændringerne fra stashen bliver som standard iscenesat. Hvis du vil afinstallere dem, skal du bruge kommandoen git restore --staged(hvis du bruger Git nyere end 2.25.0).

Du vil bare downloade fjernændringerne

Det sidste scenario er lidt anderledes end de foregående. Lad os sige, at du er midt i en meget rodet refactoring. Hverken at miste ændringerne eller stash dem er en mulighed. Alligevel vil du stadig have fjernændringerne tilgængelige for at køre git diffmod dem.

Som du sandsynligvis har fundet ud af, er det slet ikke nødvendigt git pullat downloade fjernændringerne ! git fetcher lige nok.

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

Gits verden er enorm. Denne artikel dækkede kun en af ​​facetterne ved vedligeholdelse af lageret: integrering af fjernændringer i et lokalt lager. Selv dette daglige scenarie krævede, at vi kiggede lidt mere dybtgående i dette versionskontrolværktøjs interne mekanismer.

At lære faktiske brugssager hjælper dig med bedre at forstå, hvordan Git fungerer under emhætten. Dette vil igen få dig til at føle dig bemyndiget, når du får dig selv i problemer. Det gør vi alle fra tid til anden.