Git
Chapters ▾ 2nd Edition

7.3 Гит алати - Скривање и чишћење

Скривање и чишћење

Док радите на делу пројекта, ствари су често у нереду и пожелите да пређете на другу грану да мало радите на нечему другом. Проблем настаје када не желите да комитујете напола довршен посао само да би касније могли да се вратите на ово место. Одговор на овај проблем је git stash команда.

Скривање узима неуређено стање вашег радног директоријума — то јест ваше измењене фајлове који се прате и стејџоване измене — и чува их на стек незавршених измена који касније у било које време можете поново да примените.

Белешка
Прелазак на git stash push

Крајем октобра 2017, било је опширне дискусије на Гит мејлинг листи у вези тога да ли је команда git stash save превазиђена постојећом алтернативом git stash push. Главни разлог за ово је што команда git stash push уводи опцију скривања изабраних pathspecs, нешто што команда git stash save не подржава.

git stash save не иде нигде у догледно време, тако да не треба да бринете да ће одједном нестати. Али могли бисте да почнете прелаз на push алтернативу јер доноси нову функционалност.

Скривање вашег рада

Да бисмо показали како се ово ради, ући ћете у свој пројекат и почети да радите на неколико фајлова и можда ћете стејџовати једну од измена. Ако извршите git status, видећете своје неуређено стање:

$ git status
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   lib/simplegit.rb

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

$ git stash
Saved working directory and index state \
  "WIP on master: 049d078 Create index file"
HEAD is now at 049d078 Create index file
(To restore them type "git stash apply")

Сада можете видети да је ваш радни директоријум чист:

$ git status
# On branch master
nothing to commit, working directory clean

У овом тренутку можете да промените грану и радите на другом месту; ваше измене су сачуване на стеку. Ако желите да видите која скривања имате сачувана, можете да употребите git stash list:

$ git stash list
stash@{0}: WIP on master: 049d078 Create index file
stash@{1}: WIP on master: c264051 Revert "Add file_size"
stash@{2}: WIP on master: 21d80a5 Add number to log

У овом случају, раније су сачувана два скривања, тако да имате приступ трима скривеним радовима. Онај који сте управо сакрили можете поново да примените употребом команде која је приказана у испису помоћи оригиналне команде скривања: git stash apply. Ако желите да примените неко од старијих скривања, можете га навести по имену, на следећи начин: git stash apply stash@{2}. Ако не наведете скривање, програм Гит претпоставља најскорије скривање и покушава да га примени:

$ git stash apply
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html
	modified:   lib/simplegit.rb

no changes added to commit (use "git add" and/or "git commit -a")

Можете видети да програм Гит поново мења фајлове које сте чувањем скривања вратили на старо стање. У овом случају, имали сте чист радни директоријум када сте покушали да примените скривање и покушали сте да га примените на исту грану са које сте га и сачували. Није потребно имати чист радни директоријум и бити на истој грани да би се успешно применило скривање. Скривање можете да сачувате на једној грани, касније пређете на другу, па покушате да поново примените измене. Када примењујете скривање, у радном директоријуму такође можете имати и измењене и некомитоване фајлове — програм Гит вам враћа конфликте при спајању ако постоји било шта што не може чисто да се примени.

Поново су примењене измене над вашим фајловима, али фајл који сте раније ставили на стејџ није поново на стејџу. Да бисте то урадили, команду git stash apply морате извршити са --index опцијом чиме јој налажете да покуша поново да примени стејџоване измене. Да сте то извршили, вратили бисте се на своју оригиналну позицију:

$ git stash apply --index
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   lib/simplegit.rb

Опција apply покушава да примени само скривени рад — још увек га имате на стеку. Ако желите да га уклоните, извршите git stash drop са именом скривања који желите да уклоните:

$ git stash list
stash@{0}: WIP on master: 049d078 Create index file
stash@{1}: WIP on master: c264051 Revert "Add file_size"
stash@{2}: WIP on master: 21d80a5 Add number to log
$ git stash drop stash@{0}
Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)

Такође можете да извршите git stash pop чиме примењујете скривање и непосредно након тога га уклањате са стека.

Креативно скривање

Постоји неколико варијанти скривања које такође могу бити корисне. Прва опција која је прилично популарна је --keep-index опција команде stash save. Она налаже програму Гит да у скривање укључи не само сав садржај на стејџу, већ и да га истовремено остави у индексу.

$ git status -s
M  index.html
 M lib/simplegit.rb

$ git stash --keep-index
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
M  index.html

Још једна уобичајена ствар коју можете да урадите скривањем је то да осим фајлова који се прате сакријете и фајлове који се не прате. Подразумевано, команда git stash ће сачувати само измењене и стејџоване фајлове који се прате. Ако наведете --include-untracked или -u, програм Гит ће такође сакрити и све креиране фајлове који се не прате. Међутим, укључивање фајлова који се не прате у скривање ипак неће укључити и фајлове који се експлицитно игноришу; ако желите да се и они укључе у скривање, употребите --all (или само -a).

$ git status -s
M  index.html
 M lib/simplegit.rb
?? new-file.txt

$ git stash -u
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
$

На крају, ако наведете заставицу --patch, програм Гит неће сакрити две што је измењено већ ће вас интерактивно питати које од промена желите да сакријете, а које хоћете да задржите у радном директоријуму.

$ git stash --patch
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 66d332e..8bb5674 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -16,6 +16,10 @@ class SimpleGit
         return `#{git_cmd} 2>&1`.chomp
       end
     end
+
+    def show(treeish = 'master')
+      command("git show #{treeish}")
+    end

 end
 test
Stash this hunk [y,n,q,a,d,/,e,?]? y

Saved working directory and index state WIP on master: 1b65b17 added the index file

Креирање гране из скривања

Ако сакријете неки рад, оставите га тако неко време и наставите даље на грани са које сте сакрили рад, могуће је да ћете имати проблема када пожелите да поново да га примените. Ако примењивање покуша да измени фајл који сте ви изменили након скривања, имаћете конфликт спајања и мораћете покушати да га разрешите. Ако желите једноставнији начин да поново тестирате скривене измене, можете да извршите git stash branch <име нове гране>, која вам креира нову грану са задатим именом, одјављује комит на којем сте били када сте сакрили рад, тамо поново примењује ваш рад, па брише скривање у случају да се успешно применило:

$ git stash branch testchanges
M	index.html
M	lib/simplegit.rb
Switched to a new branch 'testchanges'
On branch testchanges
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   lib/simplegit.rb

Dropped refs/stash@{0} (29d385a81d163dfd45a452a2ce816487a6b8b014)

Ово је фина скраћеница за једноставни опоравак скривеног рада и наставак посла на њему у новој грани.

Чишћење вашег радног директоријума

Коначно, можда нећете хтети да сакријете неки рад или фајлове из радног директоријума, већ једноставно хоћете да их се отарасите; команда git clean служи управо за то.

Неки уобичајени разлози за то би могли бити уклањање „крхотина” (crufts) које су генерисане спајањима или спољним алатима, или уклањање остатака након изградње како би се покренула чиста изградња.

Требало би да будете прилично опрезни са овом командом јер је дизајнирана да уклања фајлове из радног директоријума који се не прате. Ако се предомислите, често нема враћања садржаја ти фајлова. Безбеднија опција је да извршите git stash --all да уклоните све, али да га сакријете.

Ако желите из свог радног директоријума да уклоните фајлове крхотина, урадићете то помоћу команде git clean. Да из радног директоријума уклоните све фајлове који се не прате, извршите git clean -f -d, што ће уклонити све фајлове и поддиректоријуме који након уклањања фајлова остану празни. Опција -f значи force (принудно) или „уради како кажем” и неопходна је у случају до Гит конфигурациона променљива clean.requireForce није експлицитно постављена на false.

Ако некада пожелите да видите шта би команда урадила, покрените је са опцијом -n што значи „изврши пробу и реци ми шта би се уклонило”.

$ git clean -d -n
Would remove test.o
Would remove tmp/

Команда git clean ће подразумевано да уклони само непраћене фајлове који се не игноришу. Неће се уклонити било који фајл који се подудара са шаблоном из ваше .gitignore или неке друге листе фајлова који се игноришу. Ако и те фајлове желите да уклоните, као на пример све .o фајлове генерисане изградњом тако да можете покренути потпуно чисту изградњу, додајте -x комади чишћења.

$ git status -s
 M lib/simplegit.rb
?? build.TMP
?? tmp/

$ git clean -n -d
Would remove build.TMP
Would remove tmp/

$ git clean -n -d -x
Would remove build.TMP
Would remove test.o
Would remove tmp/

Ако не знате шта ће урадити команда git clean, увек је најпре покрените са -n и проверите резултат пре него што -n замените у -f и заиста извршите чишћење. Други начин на који можете бити опрезни у вези процеса је да га покренете са заставицом -i или „interactive”.

То покреће команду чишћења у интерактивном режиму.

$ git clean -x -i
Would remove the following items:
  build.TMP  test.o
*** Commands ***
    1: clean                2: filter by pattern    3: select by numbers    4: ask each             5: quit
    6: help
What now>

На овај начин можете интерактивно да пролазите преко сваког фајла појединачно или да интерактивно наведете шаблоне за брисање.

Белешка

Постоји чудна ситуација у којој може бити потребе да примените посебну принуду када од програма Гит тражите да очисти ваш радни директоријум. Рецимо да се налазите у радном директоријуму под којем сте копирали или клонирали друге Гит репозиторијуме (могуће као подмодуле), чак ће и команда git clean -fd одбити да обрише те директоријуме. У таквим случајевима чишћење морате да нагласите додавањем опције -f.