Git Pull Force - Как да заменим локалните промени с

Когато се научите да кодирате, рано или късно ще научите и за системите за контрол на версиите. И макар в това пространство да има много конкурентни инструменти, един от тях е де факто стандартът, използван от почти всички в бранша. Толкова е популярно, че има компании, които използват името му в своята марка. Говорим за Git, разбира се.

Докато Git е мощен инструмент, силата му е добре скрита. Има някои основни понятия, които трябва да разберете, за да станете наистина владеещи с Git. Добрата новина е, че след като ги научите, едва ли някога ще се сблъскате с проблеми, от които не можете да избягате.

Типичният работен процес

В типичен работен поток на Git ще използвате локално хранилище, отдалечено хранилище и един или повече клонове. Хранилищата съхраняват цялата информация за проекта, включително цялата му история и всички клонове. Клонът е по същество колекция от промени, водещи от празен проект до текущото състояние.

След клонирането на хранилище, вие работите върху вашето локално копие и въвеждате нови промени. Докато не натиснете локални промени в отдалеченото хранилище, цялата ви работа е достъпна само на вашата машина.

Когато завършите задача, е време да синхронизирате с отдалеченото хранилище. Искате да изтеглите отдалечените промени, за да сте в крак с напредъка на проекта, и искате да натиснете местните промени, за да споделите работата си с други.

Локални промени

Всичко е наред, когато вие и останалата част от вашия екип работите върху напълно отделни файлове. Каквото и да се случи, няма да си стъпвате на краката.

Има обаче моменти, когато вие и вашите съотборници едновременно въвеждате промени на едно и също място. И обикновено там започват проблемите.

Случвало ли ви се е да екзекутирате git pullсамо за да видите страховитите error: Your local changes to the following files would be overwritten by merge:? Рано или късно всеки се сблъсква с този проблем.

По-объркващото тук е, че не искате да обединявате нищо, а просто да дърпате, нали? Всъщност дърпането е малко по-сложно, отколкото бихте си помислили.

Колко точно работи Git Pull?

Издърпването не е нито една операция. Състои се от извличане на данни от отдалечения сървър и след това обединяване на промените с локалното хранилище. Тези две операции могат да се извършват ръчно, ако искате:

git fetch git merge origin/$CURRENT_BRANCH

На origin/$CURRENT_BRANCHчаст означава, че:

  • Git ще обедини промените от отдалеченото хранилище с име origin(това, от което сте клонирали)
  • които са добавени към $CURRENT_BRANCH
  • които вече не присъстват във вашия местен регистриран клон

Тъй като Git извършва обединения само когато няма неангажирани промени, всеки път, когато стартирате git pullс неангажирани промени, може да имате проблеми. За щастие има начини да се измъкнем от неприятностите с едно парче!

Ние сме семейство

Различни подходи

Когато сте премахнали локални промени и все още искате да изтеглите нова версия от отдалечения сървър, вашият случай на употреба обикновено попада в един от следните сценарии. Или:

  • не ви интересуват местните промени и искате да ги презапишете,
  • много ви е грижа за промените и бихте искали да ги приложите след отдалечените промени,
  • искате да изтеглите отдалечените модификации, но все още да не ги прилагате

Всеки от подходите изисква различно решение.

Не ви интересува местните промени

В този случай просто искате да изпуснете всички неангажирани локални промени. Може би сте модифицирали файл, за да експериментирате, но вече не се нуждаете от модификацията. Единственото, което ви интересува, е да бъдете в крак с горната част на веригата.

Това означава, че добавяте още една стъпка между извличането на отдалечените промени и обединяването им. Тази стъпка ще възстанови клона в немодифицирано състояние, като по този начин ще позволи git mergeда работи.

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

Ако не искате да въведете името на клон всеки път, когато стартирате тази команда, Git има хубав пряк път, сочещи към клона нагоре: @{u}. Клон нагоре по веригата е клонът в отдалеченото хранилище, към който натискате и извличате.

Ето как биха изглеждали горните команди с пряк път:

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

Ние цитираме прекия път в примера, за да попречим на черупката да го интерпретира.

Много се грижите за местните промени

Когато вашите неангажирани промени са важни за вас, има две възможности. Можете да ги ангажирате и след това да изпълните git pull, или можете да ги скриете.

Скриването означава да оставите промените за момент, за да ги върнете по-късно. За да бъдем по-точни, git stashсъздава ангажимент, който не се вижда в текущия ви клон, но все още е достъпен от Git.

За да върнете промените, запазени в последното скривалище, използвайте git stash popкомандата. След успешно прилагане на скритите промени, тази команда също премахва скриването на скриването, тъй като вече не е необходимо.

Тогава работният процес може да изглежда така:

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

By default, the changes from the stash will become staged. If you want to unstage them, use the command git restore --staged (if using Git newer than 2.25.0).

You Just Want to Download the Remote Changes

The last scenario is a little different from the previous ones. Let's say that you are in the middle of a very messy refactoring. Neither losing the changes nor stashing them is an option. Yet, you still want to have the remote changes available to run git diff against them.

As you have probably figured out, downloading the remote changes does not require git pull at all! git fetch is just enough.

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

Светът на Git е необятен. Тази статия обхваща само един от аспектите на поддръжката на хранилището: включване на отдалечени промени в локално хранилище. Дори този ежедневен сценарий изискваше да разгледаме малко по-задълбочено вътрешните механизми на този инструмент за контрол на версиите.

Изучаването на реални случаи на употреба ви помага да разберете по-добре как работи Git под капака. Това от своя страна ще ви накара да се чувствате овластени винаги, когато си изпаднете в беда. Всички правим това от време на време.