Гит Пулл Форце - Како преписати локалне промене помоћу Гит-а

Када научите да кодирате, пре или касније ћете сазнати и о системима за контролу верзија. И док у овом простору постоји много конкурентских алата, један од њих је де фацто стандард који користе готово сви у индустрији. Толико је популарно да постоје компаније које користе његово име у свом брендирању. Говоримо о Гиту, наравно.

Иако је Гит моћан алат, његова снага је добро скривена. Постоје неки основни концепти које морате разумети да бисте заиста били вешти у Гиту. Добра вест је да када их једном научите, тешко да ћете икада упасти у невоље од којих не можете побећи.

Типичан ток посла

У типичном Гит току рада користићете локално спремиште, удаљено спремиште и једну или више грана. Спремишта чувају све информације о пројекту, укључујући целокупну историју и све огранке. Подружница је у основи скуп промена које воде од празног пројекта до тренутног стања.

Након клонирања спремишта, радите на локалној копији и уносите нове промене. Док не потиснете локалне промене у удаљено спремиште, сав ваш рад је доступан само на вашем рачунару.

Када завршите задатак, време је за синхронизацију са удаљеним спремиштем. Желите да повучете даљинске промене да бисте ишли у корак са напретком пројекта, а желите да притиснете локалне промене да бисте свој рад поделили са другима.

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

Све је у реду када ви и остатак вашег тима радите на потпуно одвојеним датотекама. Шта год да се деси, нећете крочити једни другима на ноге.

Међутим, постоје тренуци када ви и ваши саиграчи истовремено уводите промене на истом месту. И ту обично проблеми почињу.

Да ли сте икада погубили git pullсамо да бисте видели стрепње error: Your local changes to the following files would be overwritten by merge:? Пре или касније, сви наиђу на тај проблем.

Још је збуњујуће то што не желите ништа да спојите, само повуците, зар не? Заправо, повлачење је мало компликованије него што сте могли помислити.

Како тачно делује Гит Пулл?

Повлачење није ни једна операција. Састоји се од преузимања података са удаљеног сервера, а затим спајања промена са локалним спремиштем. Ове две операције могу се ручно извршити ако желите:

git fetch git merge origin/$CURRENT_BRANCH

У origin/$CURRENT_BRANCHдео значи да:

  • Гит ће спојити промене из именованог удаљеног спремишта origin(оног из којег сте клонирали)
  • који су додати у $CURRENT_BRANCH
  • који већ нису присутни у вашој локалној одјављеној филијали

Будући да Гит спајања изводи само када нема неизвезених промена, сваки пут када покренете git pullнеизвезене промене може вам довести у проблеме. Срећом, постоје начини да се из невоље извучете у комаду!

Ми смо породица

Различити приступи

Када извршите локалне промене и још увек желите да повучете нову верзију са удаљеног сервера, ваш случај употребе обично спада у један од следећих сценарија. Или:

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

Сваки од приступа захтева различито решење.

Није вас брига за локалне промене

У овом случају, само желите да одустанете од свих неповезаних локалних промена. Можда сте модификовали датотеку за експеримент, али вам више није потребна. Важно вам је само да будете у току са узводном струјом.

То значи да додајете још један корак између преузимања удаљених промена и њиховог спајања. Овај корак ће грану вратити у њено неизмењено стање, омогућавајући git mergeтако рад.

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

Ако не желите да куцате грану Наме сваки пут када покренете ову команду, Фунд има леп пречицу који води до узводно грани: @{u}. Узводна грана је грана у удаљеном спремишту коју притиснете и преузмете из ње.

Ево како би горе наведене наредбе изгледале са пречицом:

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

Цитирамо пречицу у примеру да бисмо спречили љуску да је протумачи.

Веома вам је стало до локалних промена

Постоје две могућности када су вам неизвезане промене значајне. Можете их извршити, а затим извести git pull, или их сакрити.

Стасхинг значи одложити промене на тренутак да бисте их касније вратили. Да будемо прецизнији, git stashкреира урезивање које није видљиво на вашој тренутној грани, али му је и даље доступан Гит.

Користите git stash popнаредбу да бисте вратили промене сачуване у последњем скривању . Након успешне примене скривених промена, ова наредба такође уклања уређивање скривеног стања јер више није потребна.

Ток посла би тада могао изгледати овако:

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

По дефаулту, промене из скриваче постаће постепене. Ако желите да их уклоните са котача, користите команду git restore --staged(ако користите Гит новији од 2.25.0).

Само желите да преузмете даљинске промене

Последњи сценарио се мало разликује од претходних. Рецимо да сте усред врло неуредног преправљања. Нити губитак промена нити њихово скривање није опција. Ипак, и даље желите да даљинске промене буду доступне за git diffњихово покретање .

Као што сте вероватно већ схватили, преузимање даљинских промена уопште није потребно git pull! git fetchје сасвим довољно.

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

Свет Гита је простран. Овај чланак је обухватио само један од аспеката одржавања спремишта: укључивање даљинских промена у локално спремиште. Чак је и овај свакодневни сценарио захтевао да мало детаљније погледамо унутрашње механизме овог алата за контролу верзија.

Учење стварних случајева примене помаже вам да боље разумете како Гит ради испод хаубе. То ће се, пак, осећати оснажено кад год упаднете у невољу. Сви то радимо с времена на време.