簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-stash 最後更新於 2.52.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 export (--print | --to-ref <ref>) [<stash>…​]
git stash import <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”的區別在於它不能接受路徑名。相反,所有非選項引數都被連線起來形成暫存訊息。

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} 以 patch 格式檢視第二個最新的條目)。如果未提供<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 建立的給定暫存(一個懸空合併提交)儲存到暫存 ref 中,更新暫存 reflog。這旨在對指令碼有用。這可能不是你想要的命令;請參閱上面的“push”。

export ( --print | --to-ref <ref> ) [<stash>...]

匯出指定的暫存項(或全部,如果未指定),到一個提交鏈中,該鏈可以透過正常的 fetch 和 push 機制進行傳輸,然後透過 import 子命令匯入。

import <commit>

從指定的提交(必須由 export 建立)匯入指定的暫存項,並將它們新增到暫存列表中。要替換現有的暫存項,請先使用 clear

選項

-a
--all

此選項僅對 pushsave 命令有效。

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

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

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

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

--only-untracked

此選項僅對 show 命令有效。

在 diff 中只顯示暫存條目中的未跟蹤檔案。

--index

此選項僅對 popapply 命令有效。

嘗試恢復工作樹的更改,以及索引的更改。然而,當出現衝突時,這可能會失敗(衝突儲存在索引中,因此無法按原樣應用更改)。

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

此選項僅對 pushsave 命令有效。

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

-p
--patch

此選項僅對 pushsave 命令有效。

互動式地從 HEAD 和工作樹之間的 diff 中選擇要暫存的塊。暫存條目的索引狀態將與你的儲存庫的索引狀態相同,其工作樹僅包含你互動式選擇的更改。然後,這些選定的更改將從你的工作樹中回滾。要了解如何操作 --patch 模式,請參閱 git-add[1] 的“互動模式”部分。

選項 --patch 暗示 --keep-index。你可以使用 --no-keep-index 來覆蓋此設定。

-U<n>
--unified=<n>

生成具有 <n> 行上下文的 diff。如果配置選項未設定,則預設為 diff.context 或 3。

--inter-hunk-context=<n>

在差異塊之間顯示上下文,最多達指定行數 <number>,從而合併彼此接近的塊。預設為 diff.interHunkContext,如果未設定配置選項則為 0。

-S
--staged

此選項僅對 pushsave 命令有效。

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

選項 --patch 的優先順序高於此選項。

--pathspec-from-file=<file>

此選項僅對 push 命令有效。

路徑名(pathspec)將從<file>中讀取,而不是從命令列引數中讀取。如果<file>正好是 -,則使用標準輸入。路徑名由 LF 或 CR/LF 分隔。路徑名可以按 core.quotePath 配置變數(請參閱 git-config[1])的說明進行引用。另請參閱 --pathspec-file-nul 和全域性 --literal-pathspecs

--pathspec-file-nul

此選項僅對 push 命令有效。

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

-q
--quiet

此選項僅對 applydroppoppushsavestore 命令有效。

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

--print

此選項僅對 export 命令有效。

建立表示已匯出暫存項的提交鏈,而不將其儲存在任何 ref 名稱空間中,並將物件 ID 列印到標準輸出。這適用於指令碼。

--to-ref

此選項僅對 export 命令有效。

建立表示已匯出暫存項的提交鏈,並將其儲存到指定的 ref 中。

--

此選項僅對 push 命令有效。

為了消除歧義,將路徑名與選項分開。

<pathspec>...

此選項僅對 push 命令有效。

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

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

<stash>

此選項僅對 applybranchdroppopshowexport 命令有效。

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

討論

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

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

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

示例

拉取到髒樹

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

然而,在某些情況下,你的本地更改與上游更改發生衝突,git pull 會拒絕覆蓋你的更改。在這種情況下,你可以將你的更改暫存起來,執行 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.index

如果設定為 true,git stash applygit stash pop 的行為將如同 supplied 了 --index。預設為 false。

stash.showIncludeUntracked

如果設定為 true,git stash show 命令將顯示暫存條目的未跟蹤檔案。預設為 false。

stash.showPatch

如果設定為 true,git stash show 命令(不帶選項)將以 patch 格式顯示暫存條目。預設為 false。

stash.showStat

如果設定為 true,git stash show 命令(不帶選項)將顯示暫存條目的 diffstat。預設為 true。

GIT

Git[1] 套件的一部分