# git-stash
> 原文: [https://git-scm.com/docs/git-stash](https://git-scm.com/docs/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 [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 push`。默認情況下,存儲被列為“ _branchname_ 上的WIP ...”,但您可以在創建存儲時在命令行上提供更具描述性的消息。
您創建的最新存儲存儲在`refs/stash`中;在此引用的reflog中可以找到較舊的stashes,并且可以使用通常的reflog語法命名(例如`stash@{0}`是最近創建的stash,`stash@{1}`是之前的那個,`stash@{2.hours.ago}`也是可能的)。也可以通過僅指定存儲索引來引用狀態(例如,整數`n`等同于`stash@{n}`)。
## OPTIONS
```
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>…?]
```
將本地修改保存到新的_存儲條目_并將它們回滾到HEAD(在工作樹和索引中)。 < message> part是可選的,并提供描述以及stashed狀態。
要快速創建快照,可以省略“推送”。在此模式下,不允許使用非選項參數來防止拼寫錯誤的子命令生成不需要的存儲條目。對此的兩個例外是`stash -p`,它作為`stash push -p`和pathspecs的別名,在雙連字符`--`之后允許消除歧義。
當pathspec被賦予 _git stash push_ 時,新的存儲條目僅記錄與pathspec匹配的文件的修改狀態。然后,索引條目和工作樹文件也僅針對這些文件回滾到HEAD中的狀態,從而保留與pathspec不匹配的文件。
如果使用`--keep-index`選項,則已添加到索引的所有更改都將保持不變。
如果使用`--include-untracked`選項,所有未跟蹤的文件也會被隱藏,然后使用`git clean`清除,使工作目錄處于非常干凈的狀態。如果使用`--all`選項,則除了未跟蹤的文件外,還會隱藏和清除被忽略的文件。
使用`--patch`,您可以交互式地從HEAD和工作樹之間的差異中選擇要存儲的數據。構建存儲條目,使其索引狀態與存儲庫的索引狀態相同,并且其工作樹僅包含您以交互方式選擇的更改。然后,從您的工作樹中回滾所選更改。請參閱 [git-add [1]](https://git-scm.com/docs/git-add) 的“交互模式”部分,了解如何操作`--patch`模式。
`--patch`選項意味著`--keep-index`。您可以使用`--no-keep-index`覆蓋它。
```
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]
```
不推薦使用此選項,而使用 _git stash push_ 。它與“stash push”的不同之處在于它不能采用pathspecs,并且任何非選項參數都構成了消息。
```
list [<options>]
```
列出您當前擁有的存儲條目。列出每個_存儲條目_及其名稱(例如`stash@{0}`是最新條目,`stash@{1}`是之前的條目,等等),條目的當前分支名稱,以及條目所基于的提交的簡短描述。
```
stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
stash@{1}: On master: 9cc0589... Add git-stash
```
該命令采用適用于 _git log_ 命令的選項來控制顯示的內容和方式。參見 [git-log [1]](https://git-scm.com/docs/git-log) 。
```
show [<stash>]
```
將存儲條目中記錄的更改顯示為隱藏內容與首次創建存儲條目時的提交之間的差異。如果沒有給出`<stash>`,則顯示最新的一個。默認情況下,該命令顯示diffstat,但它將接受 _git diff_ 已知的任何格式(例如,`git stash show -p stash@{1}`以補丁形式查看第二個最新條目)。您可以使用stash.showStat和/或stash.showPatch配置變量來更改默認行為。
```
pop [--index] [-q|--quiet] [<stash>]
```
從存儲列表中刪除單個隱藏狀態并將其應用于當前工作樹狀態之上,即執行`git stash push`的反向操作。工作目錄必須與索引匹配。
應用國家可能會因沖突而失敗;在這種情況下,它不會從隱藏列表中刪除。您需要手動解決沖突并隨后手動調用`git stash drop`。
如果使用`--index`選項,則嘗試不僅恢復工作樹的更改,還嘗試恢復索引的更改。但是,如果存在沖突(存儲在索引中,因此您無法再像以前那樣應用更改),則可能會失敗。
如果沒有給出`<stash>`,則假定為`stash@{0}`,否則`<stash>`必須是`stash@{<revision>}`形式的參考。
```
apply [--index] [-q|--quiet] [<stash>]
```
與`pop`類似,但不要從隱藏列表中刪除狀態。與`pop`不同,`<stash>`可能是任何看似由`stash push`或`stash create`創建的提交的提交。
```
branch <branchname> [<stash>]
```
創建并檢出一個名為`<branchname>`的新分支,從最初創建`<stash>`的提交開始,將`<stash>`中記錄的更改應用于新的工作樹和索引。如果成功,`<stash>`是`stash@{<revision>}`形式的參考,則它會丟棄`<stash>`。如果沒有給出`<stash>`,則應用最新的一個。
如果運行`git stash push`的分支已經發生了足夠的變化,使得`git stash apply`因沖突而失敗,這將非常有用。由于存儲條目應用于`git stash`運行時HEAD的提交之上,因此它恢復原始存儲狀態而沒有沖突。
```
clear
```
刪除所有存儲條目。請注意,這些條目將進行修剪,并且可能無法恢復(請參閱下面的_示例_以獲取可能的策略)。
```
drop [-q|--quiet] [<stash>]
```
從存儲條目列表中刪除單個存儲條目。如果沒有給出`<stash>`,它將刪除最新的一個。即`stash@{0}`,否則`<stash>`必須是`stash@{<revision>}`形式的有效存儲日志引用。
```
create
```
創建一個存儲條目(這是一個常規提交對象)并返回其對象名稱,而不將其存儲在ref命名空間中的任何位置。這對腳本非常有用。它可能不是你想要使用的命令;看到上面的“推”。
```
store
```
存儲通過 _git stash創建的給定存儲創建_(這是一個懸空的合并提交)在存儲引用中,更新存儲reflog。這對腳本非常有用。它可能不是你想要使用的命令;看到上面的“推”。
## 討論
存儲條目表示為提交,其樹記錄工作目錄的狀態,其第一個父項是創建條目時`HEAD`的提交。第二個父樹的樹在創建條目時記錄索引的狀態,并且它成為`HEAD`提交的子代。祖先圖如下所示:
```
.----W
/ /
-----H----I
```
其中`H`是`HEAD`提交,`I`是記錄索引狀態的提交,`W`是記錄工作樹狀態的提交。
## 例子
```
Pulling into a dirty tree
```
當您處于某種狀態時,您會發現存在可能與您正在進行的操作相關的上游更改。當您的本地更改不與上游的更改沖突時,一個簡單的`git pull`將讓您繼續前進。
但是,在某些情況下,您的本地更改會與上游更改發生沖突,`git pull`會拒絕覆蓋您的更改。在這種情況下,您可以隱藏您的更改,執行拉動,然后取消暫停,如下所示:
```
$ git pull
...
file foobar not up to date, cannot merge.
$ git stash
$ git pull
$ git stash pop
```
```
Interrupted workflow
```
當你處于中間狀態時,你的老板會進來并要求你立即修理。傳統上,您將提交臨時分支以存儲您的更改,并返回到原始分支以進行緊急修復,如下所示:
```
# ... 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 ...
```
```
Testing partial commits
```
如果要從工作樹中的更改中進行兩次或更多次提交,并且希望在提交之前測試每個更改,則可以使用`git stash push --keep-index`:
```
# ... hack hack hack ...
$ git add --patch foo # add just first part to the index
$ git stash push --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'
```
```
Recovering stash entries that were cleared/dropped erroneously
```
如果您錯誤地刪除或清除了存儲條目,則無法通過正常的安全機制恢復它們。但是,您可以嘗試以下咒語來獲取仍在存儲庫中但不再可訪問的存儲條目列表:
```
git fsck --unreachable |
grep commit | cut -d\ -f3 |
xargs git log --merges --no-walk --grep=WIP
```
## 也可以看看
[git-checkout [1]](https://git-scm.com/docs/git-checkout) , [git-commit [1]](https://git-scm.com/docs/git-commit) , [git-reflog [1]](https://git-scm.com/docs/git-reflog) , [git-reset [1]](https://git-scm.com/docs/git-reset)
## GIT
部分 [git [1]](https://git-scm.com/docs/git) 套件
- git
- git-config
- git-help
- git-init
- git-clone
- git-add
- git-status
- git-diff
- git-commit
- git-reset
- git-rm
- git-mv
- git-branch
- git-checkout
- git-merge
- git-mergetool
- git-log
- git-stash
- git-tag
- git-worktree
- git-fetch
- git-pull
- git-push
- git-remote
- git-submodule
- git-show
- git-log
- git-shortlog
- git-describe
- git-apply
- git-cherry-pick
- git-rebase
- git-revert
- git-bisect
- git-blame
- git-grep
- gitattributes
- giteveryday
- gitglossary
- githooks
- gitignore
- gitmodules
- gitrevisions
- gittutorial
- gitworkflows
- git-am
- git-format-patch
- git-send-email
- git-request-pull
- git-svn
- git-fast-import
- git-clean
- git-gc
- git-fsck
- git-reflog
- git-filter-branch
- git-instaweb
- git-archive
- git-bundle
- git-daemon
- git-update-server-info
- git-cat-file
- git-check-ignore
- git-checkout-index
- git-commit-tree
- git-count-objects
- git-diff-index
- git-for-each-ref
- git-hash-object
- git-ls-files
- git-merge-base
- git-read-tree
- git-rev-list
- git-rev-parse
- git-show-ref
- git-symbolic-ref
- git-update-index
- git-update-ref
- git-verify-pack
- git-write-tree