簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-stash 上次更新於 2.43.0

名稱

git-stash - 暫存髒工作目錄中的變更

概要

git stash list [<log-options>]
git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
git stash drop [-q | --quiet] [<stash>]
git stash pop [--index] [-q | --quiet] [<stash>]
git stash apply [--index] [-q | --quiet] [<stash>]
git stash branch <branchname> [<stash>]
git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
	     [-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
	     [--pathspec-from-file=<file> [--pathspec-file-nul]]
	     [--] [<pathspec>…​]]
git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
	     [-u | --include-untracked] [-a | --all] [<message>]
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。暫存預設顯示為“WIP on branchname …​”,但你可以在建立時在命令列上給出更具描述性的訊息。

你建立的最新暫存儲存在 refs/stash 中;舊的暫存可以在此引用的 reflog 中找到,並可以使用通常的 reflog 語法命名(例如,stash@{0} 是最新建立的暫存,stash@{1} 是它之前的,stash@{2.hours.ago} 也是可能的)。暫存也可以透過僅指定暫存索引來引用(例如,整數 n 等同於 stash@{n})。

命令

push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [(-m|--message) <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>…​]

將你的本地修改儲存為一個新的 *暫存條目*,並將它們回滾到 HEAD(在工作樹和索引中)。<message> 部分是可選的,並提供了與暫存狀態一起的描述。

為了快速建立快照,你可以省略“push”。在此模式下,不允許使用非選項引數,以防止拼寫錯誤的子命令建立不需要的暫存條目。兩個例外是 stash -p,它作為 stash push -p 的別名,以及 pathspec 元素,它們在雙連字元 -- 後允許用於消除歧義。

save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]

此選項已被棄用,推薦使用 *git stash push*。它與“stash push”的不同之處在於它不能接受 pathspec。相反,所有非選項引數都將連線起來形成暫存訊息。

list [<log-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]

show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]

顯示暫存條目中記錄的更改,作為暫存內容與首次建立暫存條目時的提交之間的差異。預設情況下,該命令顯示 diffstat,但它會接受 *git diff* 已知的任何格式(例如,git stash show -p stash@{1} 以補丁形式檢視倒數第二個最新條目)。如果沒有提供 <diff-option>,則預設行為將由 stash.showStatstash.showPatch 配置變數給出。你還可以使用 stash.showIncludeUntracked 來設定是否預設啟用 --include-untracked

pop [--index] [-q|--quiet] [<stash>]

從暫存列表中移除單個暫存狀態,並將其應用到當前工作樹狀態之上,即執行 git stash push 的逆操作。工作目錄必須與索引匹配。

應用狀態時可能會因衝突而失敗;在這種情況下,它不會從暫存列表中移除。你需要手動解決衝突,然後手動呼叫 git stash drop

apply [--index] [-q|--quiet] [<stash>]

pop 類似,但不會從暫存列表中移除狀態。與 pop 不同,<stash> 可以是任何看起來像由 stash pushstash create 建立的提交。

branch <branchname> [<stash>]

建立一個名為 <branchname> 的新分支並切換到該分支,該分支從 <stash> 最初建立時的提交開始,將 <stash> 中記錄的更改應用到新的工作樹和索引。如果成功,並且 <stash>stash@{<revision>} 形式的引用,則它會刪除 <stash>

如果執行 git stash push 的分支變化很大,導致 git stash apply 因衝突而失敗,此命令會很有用。由於暫存條目是在執行 git stash 時 HEAD 所在的提交之上應用的,因此它會恢復最初暫存的狀態,沒有衝突。

clear

移除所有暫存條目。請注意,這些條目隨後將受制於修剪,並且可能無法恢復(有關可能的策略,請參閱下面的 *示例*)。

drop [-q|--quiet] [<stash>]

從暫存條目列表中移除單個暫存條目。

create

建立一個暫存條目(它是一個普通的提交物件)並返回其物件名稱,而不在 ref 名稱空間的任何位置儲存它。這旨在對指令碼有用。這可能不是你想要使用的命令;請參閱上面的“push”命令。

store

將透過 *git stash create* 建立的給定暫存(它是一個懸空合併提交)儲存在暫存引用中,更新暫存 reflog。這旨在對指令碼有用。這可能不是你想要使用的命令;請參閱上面的“push”命令。

選項

-a
--all

此選項僅對 pushsave 命令有效。

所有被忽略和未跟蹤的檔案也會被暫存,然後用 git clean 清理。

-u
--include-untracked
--no-include-untracked

當與 pushsave 命令一起使用時,所有未跟蹤的檔案也會被暫存,然後用 git clean 清理。

當與 show 命令一起使用時,將暫存條目中的未跟蹤檔案作為差異的一部分顯示。

--only-untracked

此選項僅對 show 命令有效。

僅顯示暫存條目中未跟蹤的檔案作為差異的一部分。

--index

此選項僅對 popapply 命令有效。

嘗試不僅恢復工作樹的更改,還恢復索引的更改。但是,當存在衝突時(衝突儲存在索引中,因此你無法再按原樣應用更改),這可能會失敗。

-k
--keep-index
--no-keep-index

此選項僅對 pushsave 命令有效。

所有已新增到索引的更改都保持不變。

-p
--patch

此選項僅對 pushsave 命令有效。

互動式地選擇 HEAD 和工作樹之間差異中的程式碼塊進行暫存。暫存條目構建時,其索引狀態與你的倉庫的索引狀態相同,並且其工作樹僅包含你互動式選擇的更改。然後,所選更改將從你的工作樹中回滾。請參閱 git-add[1] 的“互動模式”部分,瞭解如何操作 --patch 模式。

--patch 選項隱含 --keep-index。你可以使用 --no-keep-index 覆蓋此設定。

-S
--staged

此選項僅對 pushsave 命令有效。

僅暫存當前已暫存的更改。這類似於基本的 git commit,只是狀態被提交到暫存而不是當前分支。

--patch 選項優先於此選項。

--pathspec-from-file=<file>

此選項僅對 push 命令有效。

pathspec 透過 <file> 傳遞,而不是命令列引數。如果 <file> 恰好是 -,則使用標準輸入。pathspec 元素由 LF 或 CR/LF 分隔。pathspec 元素可以像配置變數 core.quotePath 所解釋的那樣引用(請參閱 git-config[1])。另請參閱 --pathspec-file-nul 和全域性 --literal-pathspecs

--pathspec-file-nul

此選項僅對 push 命令有效。

僅在與 --pathspec-from-file 一起使用時有意義。pathspec 元素用 NUL 字元分隔,所有其他字元都按字面意義處理(包括換行符和引號)。

-q
--quiet

此選項僅對 applydroppoppushsavestore 命令有效。

安靜模式,抑制反饋訊息。

--

此選項僅對 push 命令有效。

將 pathspec 與選項分開,以消除歧義。

<pathspec>…​

此選項僅對 push 命令有效。

新的暫存條目僅記錄與 pathspec 匹配的檔案的修改狀態。索引條目和工作樹檔案也僅針對這些檔案回滾到 HEAD 中的狀態,不匹配 pathspec 的檔案則保持不變。

有關更多詳細資訊,請參閱 gitglossary[7] 中的 pathspec 條目。

<stash>

此選項僅對 applybranchdroppopshow 命令有效。

形式為 stash@{<revision>} 的引用。當未給出 <stash> 時,預設使用最新的暫存(即 stash@{0})。

討論

暫存條目表示為一個提交,其樹記錄了工作目錄的狀態,其第一個父級是建立條目時 HEAD 處的提交。第二個父級的樹記錄了建立條目時索引的狀態,並且它成為 HEAD 提交的子級。祖先圖如下所示

       .----W
      /    /
-----H----I

其中 HHEAD 提交,I 是記錄索引狀態的提交,W 是記錄工作樹狀態的提交。

示例

拉取到髒樹

當你在進行某項工作時,你得知上游有一些可能與你正在做的事情相關的更改。如果你的本地更改與上游的更改不衝突,一個簡單的 git pull 就可以讓你繼續進行。

但是,在某些情況下,你的本地更改與上游更改確實衝突,並且 git pull 拒絕覆蓋你的更改。在這種情況下,你可以暫存你的更改,執行拉取,然後解除暫存,像這樣

$ git pull
 ...
file foobar not up to date, cannot merge.
$ git stash
$ git pull
$ git stash pop
中斷的工作流程

當你正在進行某項工作時,你的老闆進來要求你立即修復某個問題。傳統上,你會將更改提交到一個臨時分支以儲存它們,然後返回到你的原始分支進行緊急修復,像這樣

# ... hack hack hack ...
$ git switch -c my_wip
$ git commit -a -m "WIP"
$ git switch master
$ edit emergency fix
$ git commit -a -m "Fix in a hurry"
$ git switch 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 ...
測試部分提交

當你想從工作樹中的更改建立兩個或更多提交,並且在提交之前測試每個更改時,可以使用 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'
儲存不相關的更改以備將來使用

當你在進行大量更改時,發現一些不相關的、你不想忘記修復的問題,你可以進行更改,暫存它們,然後使用 git stash push --staged 將它們暫存起來以備將來使用。這類似於提交已暫存的更改,只是提交最終位於暫存區而不是當前分支上。

# ... hack hack hack ...
$ git add --patch foo           # add unrelated changes to the index
$ git stash push --staged       # save these changes to the stash
# ... hack hack hack, finish current changes ...
$ git commit -m 'Massive'       # commit fully tested changes
$ git switch fixup-branch       # switch to another branch
$ git stash pop                 # to finish work on the saved changes
恢復錯誤清除/丟棄的暫存條目

如果你錯誤地刪除了暫存條目或清除了暫存,它們無法透過正常的安全機制恢復。但是,你可以嘗試以下咒語來獲取仍在你倉庫中但已無法訪問的暫存條目列表

git fsck --unreachable |
grep commit | cut -d\  -f3 |
xargs git log --merges --no-walk --grep=WIP

配置

本節中以下所有內容均從 git-config[1] 文件中選擇性地包含。內容與彼處相同:

stash.showIncludeUntracked

如果此項設定為 true,git stash show 命令將顯示暫存條目中的未跟蹤檔案。預設為 false。請參閱 git-stash[1] 中 *show* 命令的描述。

stash.showPatch

如果此項設定為 true,不帶選項的 git stash show 命令將以補丁形式顯示暫存條目。預設為 false。請參閱 git-stash[1] 中 *show* 命令的描述。

stash.showStat

如果此項設定為 true,不帶選項的 git stash show 命令將顯示暫存條目的 diffstat。預設為 true。請參閱 git-stash[1] 中 *show* 命令的描述。

GIT

Git[1] 套件的一部分

scroll-to-top