Git
Chapters ▾ 2nd Edition

7.3 Orodja Git - Shranjevanje na varno (angl. stashing) in čiščenje

Shranjevanje na varno (angl. stashing) in čiščenje

Pogosto, ko delate na delu svojega projekta, so stvari v neurejenem stanju in si želite za nekaj časa preklopiti na drugo vejo, da bi delali na nečem drugem. Problem je v tem, da ne želite potrditi nepopolnega dela, samo da se lahko kasneje vrnete na točko, kjer ste ostali. Rešitev tega problema je ukaz git stash.

Shramba na varnem (angl. stash) vzame nepopolno stanje vašega delovnega direktorija — to je vaše spremenjene sledene datoteke in spremembe v področju priprave — in jih shrani na kup nedokončanih sprememb, ki jih lahko kadar koli znova uporabite (tudi na drugi veji).

Opomba
Migracija na git stash push

Od konca oktobra 2017 poteka obsežna razprava na seznamu za pošiljanje sporočil v zvezi z Gitom, kjer se ukaz git stash save nadomešča z že obstoječo alternativo git stash push. Glavni razlog za to je, da git stash push omogoča shranjevanje izbranih parametrov pathspec, kar git stash save ne podpira.

git stash save ne bo kmalu izginil, zato ni treba preveč skrbeti glede nenadne spremembe. Vendar pa bi bilo smiselno začeti migrirati na alternativo push, da lahko izkoristite nove funkcionalnosti.

Shranjevanje vašega dela na varno

Da bi prikazali uporabo shranjevanja na varno, boste vstopili v svoj projekt in začeli delati na nekaj datotekah ter morda eno od sprememb zaključili z git add, da jo pripravite za potrditev. Če zaženete git status, lahko vidite svoje nepopolno stanje:

$ 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

Zdaj želite preklopiti na drugo vejo, vendar še ne želite potrditi, kar ste do sedaj naredili, zato boste shranili spremembe na varno. Da bi novo shrambo na varnem potisnili na vrh vašega sklada, poženite git stash ali git stash push:

$ 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")

Sedaj lahko vidite, da je vaš delovni direktorij ponovno čist:

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

Sedaj lahko preklopite na drugo vejo in delate drugje; vaše spremembe so shranjene na vašem skladu. Za ogled seznama shranjenih sprememb na varnem uporabite 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

V tem primeru sta bili prej shranjeni dve shrambi na varnem, zato imate dostop do treh različnih shranjenih del na varnem. Zadnje shranjeno lahko ponovno uporabite s pomočjo ukaza, prikazanega v izhodnem besedilu pomoči prvotnega ukaza stash: git stash apply. Če želite uporabiti eno od starejših shramb na varnem, jo lahko imenujete tako, da jo navedete: git stash apply stash@{2}. Če ne navedete shrambe, Git predpostavi najnovejšo shrambo in poskusi uporabiti to:

$ 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")

Vidite, da Git ponovno spremeni datoteke, ki ste jih vrnili na prejšnje stanje, ko ste shranili shrambo na varnem. V tem primeru ste imeli čist delovni imenik, ko ste poskušali uporabiti shrambo na varnem, in ste jo poskušali uporabiti v isti veji, v kateri ste jo shranili. Čist delovni imenik in uporaba shranjevanja na varnem v isti veji nista potrebna za uspešno uporabo shrambe. Shranite lahko shrambo v eni veji, kasneje preklopite na drugo in poskusite znova uporabiti spremembe. Ko uporabite shrambo na varnem, imate lahko v svojem delovnem imeniku tudi spremenjene in nepotrjene datoteke — Git vam bo dal konflikte združevanja, če se karkoli ne da več uporabiti gladko.

Spremembe v vaših datotekah so bile ponovno uporabljene, vendar datoteka, ki ste jo izdelali, preden ste jo shranili, ni bila ponovno vzpostavljena. Da bi to storili, morate izvesti ukaz git stash apply z možnostjo --index, da ukazu poveste, naj poskusi znova uporabiti spremembe v področju priprave. Če bi namesto tega izvedli to, bi se vrnili v prvotni položaj:

$ 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

Možnost apply poskusi samo uporabiti shranjeno delo na varnem — še vedno ga imate v skladu. Če ga želite odstraniti, lahko zaženete git stash drop z imenom shrambe, ki jo želite odstraniti:

$ 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)

Lahko zaženete tudi git stash pop, da uporabite shrambo na varnem in jo takoj odstranite iz svojega seznama shramb.

Kreativno shranjevanje na varno

Obstajajo nekatere variante shramb na varnem, ki vam lahko prav tako pomagajo. Prva možnost, ki je precej priljubljena, je uporaba možnosti --keep-index za ukaz git stash. To pove Gitu, naj vključi v ustvarjeno shrambo na varno vse vsebine, ki so v območju priprave, hkrati pa naj jih pusti v indeksu.

$ 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

Še ena pogosta stvar, ki jo lahko želite narediti s stash, je, da shranite tudi nesledene datoteke skupaj s sledenimi. Privzeto git stash shrani le spremenjene in pripravljene sledene datoteke. Če navedete --include-untracked ali -u, Git vključi nesledene datoteke v ustvarjeno shrambo. Vendar pa vključevanje nesledenih datotek v shrambo še vedno ne vključuje eksplicitno ignoriranih datotek; da vključite tudi ignorirane datoteke, uporabite --all (ali samo -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
$

Na koncu, če navedete zastavico --patch, Git ne bo dal v shrambo vsega, kar je spremenjeno, ampak vam bo interaktivno ponudil možnost izbire, kaj bi radi dali v shrambo in kaj bi radi obdržali v svojem delovnem imeniku.

$ 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

Ustvarjanje veje iz shrambe

Če neko delo shranite na varno, ga pustite tam nekaj časa in nadaljujete delo na veji, s katere ste shranili delo, imate lahko težave pri ponovnem nanašanju dela. Če poskuša uporaba spremeniti datoteko, ki ste jo od takrat spremenili, boste dobili konflikt med združevanjem in ga boste morali poskusiti rešiti. Če želite enostavnejši način za testiranje shranjenih sprememb na varnem, lahko zaženete git stash branch <ime nove veje>, kar vam ustvari novo vejo z izbranim imenom, izvleče potrditev, na kateri ste bili, ko ste shranili svoje delo, nanjo znova nanese vaše delo in nato zavrže shrambo, če se uspešno uvede:

$ 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)

To je lepa bližnjica za enostavno obnovitev shranjenega dela in delo na njem v novi veji.

Čiščenje vašega delovnega direktorija

Na koncu morda ne želite nekaterih delovnih datotek ali datotek v svojem delovnem imeniku, ampak jih preprosto želite odstraniti; za to je namenjen ukaz git clean.

Nekateri pogosti razlogi za čiščenje vašega delovnega imenika so odstranjevanje nepotrebnih datotek, ki so bile ustvarjene med združevanjem ali z zunanjimi orodji, ali pa odstranjevanje gradbenih artefaktov, da lahko zaženete čisto gradnjo.

Pri tem ukazu boste morali biti previdni, saj je namenjen odstranjevanju datotek iz vašega delovnega imenika, ki niso sledene. Če si premislite, pogosto ni mogoče obnoviti vsebine teh datotek. Bolj varna možnost je izvedba git stash --all, da odstranite vse, vendar shranite spremembe v shrambo.

Ob predpostavki, da želite odstraniti napačne datoteke ali počistiti svoj delovni imenik, lahko to storite z git clean. Če pa želite odstraniti vse nesledene datoteke v vašem delovnem imeniku, lahko to storite z ukazom git clean -f -d, ki odstrani vse datoteke in tudi vse podmape, ki postanejo prazne kot posledica tega. -f pomeni »prisilno« (angl. force) oz. »to res izvedi« in je zahtevan, če ni eksplicitno nastavljena Gitova konfiguracijska spremenljivka clean.requireForce na false.

Če želite videti, kaj bi storil, lahko ukaz poženete z možnostjo --dry-run (ali -n), kar pomeni »Izvedi suhi tek in mi povej, kaj bi odstranil«.

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

Privzeto ukaz git clean odstrani samo nesledene datoteke, ki niso ignorirane. Datoteke, ki se prilegajo vzorcem v vaši datoteki .gitignore, ali pa druge ignorirane datoteke, ne bodo odstranjene. Če želite odstraniti tudi te datoteke, na primer, da odstranite vse datoteke .o, ki so bile ustvarjene pri gradnji, da lahko izvedete popolno čiščenje, lahko ukazu clean dodate -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/

Če ne veste, kaj bo ukaz git clean naredil, ga vedno najprej zaženite s stikalom -n, da preverite, preden ga spremenite v -f in dejansko izvedete ukaz. Drugi način, kako biti previdni med postopkom, je, da ga zaženete s stikalom -i (»interaktivno«).

To bo zagnalo ukaz clean v interaktivnem načinu.

$ 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>

Tako lahko po posameznih datotekah stopite skozi vsako posebej ali pa interaktivno določite vzorce za brisanje.

Opomba

Obstaja nenavadna situacija, ko je morda potrebno posebno poudariti zahtevo Gitu, da počisti vaš delovni imenik. Če ste v delovnem imeniku, pod katerim ste kopirali ali klonirali druge repozitorije Git (morda kot podmoduli), bo celo git clean -fd zavrnil brisanje teh imenikov. V takšnih primerih je potrebno dodati še drugo možnost -f za poudarek.

scroll-to-top