git stash命令
git stash
命令用於將更改儲藏在髒工作目錄中。
使用語法
git stash list [<options>]
git stash show [<stash>]
git stash drop [-q|--quiet] [<stash>]
git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
git stash branch <branchname> [<stash>]
git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [<message>]
git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [-m|--message <message>]]
[--] [<pathspec>…]]
git stash clear
git stash create [<message>]
git stash store [-m|--message <message>] [-q|--quiet] <commit>
描述
當要記錄工作目錄和索引的當前狀態,但想要返回到乾淨的工作目錄時,則使用git stash
。 該命令保存本地修改,並恢復工作目錄以匹配HEAD
提交。
這個命令所儲藏的修改可以使用git stash list
列出,使用git stash show
進行檢查,並使用git stash apply
恢復(可能在不同的提交之上)。調用沒有任何參數的git stash
相當於git stash save
。 默認情況下,儲藏列表爲「分支名稱上的WIP」,但您可以在創建一個消息時在命令行上給出更具描述性的消息。
創建的最新儲藏存儲在refs/stash
中; 這個引用的反垃圾郵件中會發現較舊的垃圾郵件,並且可以使用通常的reflog
語法命名(例如,stash@{0}
是最近創建的垃圾郵件,stash@{1}
是stash@{2.hours.ago}
之前也是可能的)。也可以通過指定存儲空間索引(例如整數n
相當於儲藏stash@{n}
)來引用鎖存。
示例
以下是一些示例 -
1.拉取到一棵骯髒的樹
當你處於某種狀態的時候,你會發現有一些上游的變化可能與正在做的事情有關。當您的本地更改不會與上游的更改衝突時,簡單的git pull
將讓您向前。
但是,有些情況下,本地更改與上游更改相沖突,git pull
拒絕覆蓋您的更改。 在這種情況下,您可以將更改隱藏起來,執行git pull
,然後解壓縮,如下所示:
git pull
...
file foobar not up to date, cannot merge.
$ git stash
$ git pull
$ git stash pop
2.工作流中斷
當你處於某種狀態的時候,比如你的老闆進來,要求立即開會或處理非常緊急的事務。 傳統上,應該提交一個臨時分支來存儲您的更改,並返回到原始(original
)分支進行緊急修復,如下所示:
# ... hack hack hack ...
$ git checkout -b my_wip
$ git commit -a -m "WIP"
$ git checkout master
$ edit emergency fix # 編輯內容
$ git commit -a -m "Fix in a hurry"
$ git checkout my_wip
$ git reset --soft HEAD^
# ... continue hacking ...
上面過程可以使用git stash
來簡化上述操作,如下所示:
# ... hack hack hack ...
$ git stash
$ edit emergency fix
$ git commit -a -m "Fix in a hurry"
$ git stash pop
# ... continue hacking ...
3.測試部分提交
當要從工作樹中的更改中提交兩個或多個提交時,可以使用git stash save --keep-index
,並且要在提交之前測試每個更改:
# ... hack hack hack ...
$ git add --patch foo # add just first part to the index
$ git stash save --keep-index # save all other changes to the stash
$ edit/build/test first part
$ git commit -m 'First part' # commit fully tested change
$ git stash pop # prepare to work on all other changes
# ... repeat above five steps until one commit remains ...
$ edit/build/test remaining parts
$ git commit foo -m 'Remaining parts'
4.恢復被錯誤地清除/丟棄的垃圾
如果你錯誤地刪除或清除了垃圾,就不能通過正常的安全機制來恢復。 但是,您可以嘗試以下命令來獲取仍在存儲庫中但仍無法訪問的隱藏列表:
git fsck --unreachable |
grep commit | cut -d\ -f3 |
xargs git log --merges --no-walk --grep=WIP
5.儲藏你的工作
爲了演示這一功能,可以進入你的項目,在一些文件上進行工作,有可能還暫存其中一個變更。如果運行git status
,可以看到你的中間狀態:
$ 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
:
$ 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")
現在,工作目錄就乾淨了:
$ git status
# On branch master
nothing to commit, working directory clean
這時,可以方便地切換到其他分支工作;變更都保存在棧上。要查看現有的儲藏,可以使用 git stash list
,如下所示 -
$ 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 默認使用最近的儲藏並嘗試應用它:
$ 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 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)
#
# modified: lib/simplegit.rb
#
apply
選項只嘗試應用儲藏的工作——儲藏的內容仍然在棧上。要移除它,可以運行 git stash drop
再加上希望移除的儲藏的名字:
$ 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
來重新應用儲藏,同時立刻將其從堆棧中移走。
6.取消儲藏
在某些情況下,可能想應用儲藏的修改,在進行了一些其他的修改後,又要取消之前所應用儲藏的修改。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
7.從儲藏中創建分支
如果儲藏了一些工作,暫時不去理會,然後繼續在你儲藏工作的分支上工作,在重新應用工作時可能會碰到一些問題。如果嘗試應用的變更是針對一個在那之後修改過的文件,會碰到一個歸併衝突並且必須去化解它。如果你想用更方便的方法來重新檢驗儲藏的變更,可以運行 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)