常常有這樣的事情發生,當你正在進行項目中某一部分的工做,裏面的東西處於一個比較雜亂的狀態,而你想轉到其餘分支上進行一些工做。問題是,你不想提交進行了一半的工做,不然之後你沒法回到這個工做點。解決這個問題的辦法就是git stash
命令。html
「‘儲藏」「能夠獲取你工做目錄的中間狀態——也就是你修改過的被追蹤的文件和暫存的變動——並將它保存到一個未完結變動的堆棧中,隨時能夠從新應用。git
爲了演示這一功能,你能夠進入你的項目,在一些文件上進行工做,有可能還暫存其中一個變動。若是你運行 git status
,你能夠看到你的中間狀態:app
$ git status # 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) # # modified: lib/simplegit.rb #
如今你想切換分支,可是你還不想提交你正在進行中的工做;因此你儲藏這些變動。爲了往堆棧推送一個新的儲藏,只要運行 git stash
:rest
$ git stash Saved working directory and index state \ "WIP on master: 049d078 added the index file" HEAD is now at 049d078 added the index file (To restore them type "git stash apply")
你的工做目錄就乾淨了:code
$ git status # On branch master nothing to commit, working directory clean
這時,你能夠方便地切換到其餘分支工做;你的變動都保存在棧上。要查看現有的儲藏,你可使用 git stash list
:htm
$ git stash list stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051 Revert "added file_size" stash@{2}: WIP on master: 21d80a5 added number to log
在這個案例中,以前已經進行了兩次儲藏,因此你能夠訪問到三個不一樣的儲藏。你能夠從新應用你剛剛實施的儲藏,所採用的命令就是以前在原始的 stash 命令的幫助輸出裏提示的:git stash apply
。若是你想應用更早的儲藏,你能夠經過名字指定它,像這樣:git stash apply stash@{2}
。若是你不指明,Git 默認使用最近的儲藏並嘗試應用它:get
$ git stash apply # On branch master # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # # modified: index.html # modified: lib/simplegit.rb #
你能夠看到 Git 從新修改了你所儲藏的那些當時還沒有提交的文件。在這個案例裏,你嘗試應用儲藏的工做目錄是乾淨的,而且屬於同一分支;可是一個乾淨的工做目錄和應用到相同的分支上並非應用儲藏的必要條件。你能夠在其中一個分支上保留一份儲藏,隨後切換到另一個分支,再從新應用這些變動。在工做目錄裏包含已修改和未提交的文件時,你也能夠應用儲藏——Git 會給出歸併衝突若是有任何變動沒法乾淨地被應用。it
對文件的變動被從新應用,可是被暫存的文件沒有從新被暫存。想那樣的話,你必須在運行 git stash apply
命令時帶上一個 --index
的選項來告訴命令從新應用被暫存的變動。若是你是這麼作的,你應該已經回到你原來的位置:ast
$ 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) # # modified: lib/simplegit.rb #
apply 選項只嘗試應用儲藏的工做——儲藏的內容仍然在棧上。要移除它,你能夠運行 git stash drop
,加上你但願移除的儲藏的名字:test
$ git stash list stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051 Revert "added file_size" stash@{2}: WIP on master: 21d80a5 added number to log $ git stash drop stash@{0} Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
你也能夠運行 git stash pop
來從新應用儲藏,同時馬上將其從堆棧中移走。
在某些狀況下,你可能想應用儲藏的修改,在進行了一些其餘的修改後,又要取消以前所應用儲藏的修改。Git沒有提供相似於 stash unapply
的命令,可是能夠經過取消該儲藏的補丁達到一樣的效果:
$ git stash show -p stash@{0} | git apply -R
一樣的,若是你沒有指定具體的某個儲藏,Git 會選擇最近的儲藏:
$ git stash show -p | git apply -R
你可能會想要新建一個別名,在你的 Git 裏增長一個 stash-unapply
命令,這樣更有效率。例如:
$ git config --global alias.stash-unapply '!git stash show -p | git apply -R' $ git stash apply $ #... work work work $ git stash-unapply
若是你儲藏了一些工做,暫時不去理會,而後繼續在你儲藏工做的分支上工做,你在從新應用工做時可能會碰到一些問題。若是嘗試應用的變動是針對一個你那以後修改過的文件,你會碰到一個歸併衝突而且必須去化解它。若是你想用更方便的方法來從新檢驗你儲藏的變動,你能夠運行 git stash branch
,這會建立一個新的分支,檢出你儲藏工做時的所處的提交,從新應用你的工做,若是成功,將會丟棄儲藏。
$ git stash branch testchanges 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) # # modified: lib/simplegit.rb # Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
這是一個很棒的捷徑來恢復儲藏的工做而後在新的分支上繼續當時的工做。