简体中文 ▾ 主题 ▾ 最新版本 ▾ 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 中;较旧的储藏可以在此引用的引用日志中找到,并且可以使用常用的引用日志语法来命名(例如 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 的别名,以及路径规范元素,它们可以在双连字符 -- 之后使用以消除歧义。

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} 以补丁形式查看第二个最新条目)。如果未提供 <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>]

从最初创建 <stash> 的提交开始,创建并检出一个名为 <branchname> 的新分支,并将 <stash> 中记录的更改应用于新的工作树和索引。 如果成功,并且 <stash>stash@{<revision>} 形式的引用,则它会删除 <stash>

如果您运行 git stash push 的分支已更改到足以导致 git stash apply 由于冲突而失败,这将非常有用。 由于储藏条目应用于运行 git stash 时 HEAD 的提交之上,因此它会恢复最初储藏的状态,而不会产生冲突。

clear

删除所有储藏条目。 请注意,这些条目随后将受到修剪的影响,并且可能无法恢复(有关可能的策略,请参阅下面的*示例*)。

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

从储藏条目列表中删除单个储藏条目。

create

创建一个储藏条目(这是一个常规提交对象)并返回其对象名称,而不在 ref 命名空间中的任何位置存储它。 这旨在对脚本有用。 这可能不是您要使用的命令; 请参阅上面的“push”。

store

在储藏 ref 中存储通过 *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