Git
简体中文 ▾ Topics ▾ Latest version ▾ git-stash last updated in 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(在工作区和索引中)。 <信息>部分是可选的,它给出了描述和储藏的状态。

为了快速制作快照,你可以省略 "push"。 在这种模式下,非选项参数是不允许的,以防止拼写错误的子命令产生不需要的储藏条目。 这方面的两个例外是`stash -p`,它作为`stash push -p`的别名,以及为消除歧义允许在双连字符`--`之后的路径规范元素。

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

该选项已被弃用,改为 "git stash push"。 它与 "stash push "的不同之处在于,它不能接受路径规范。 取而代之的是,所有非选项的参数都被串联起来,形成储藏消息。

list [<日志选项>]

列出你目前拥有的储藏目录。 每个 "储藏目录 "都列出了它的名字(例如,`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选项>] [<储藏目录>]

显示贮藏中记录的修改,作为贮藏内容与贮藏库条目首次创建时的提交之间的差异。 默认情况下,该命令显示diff统计,但它会接受 "git diff "已知的任何格式(例如,git stash show -p stash@{1}`以补丁形式查看第二条最新条目)。 如果没有提供<diff选项>,默认行为将由`stash.showStat`和`stash.showPatch`配置变量给出。你也可以使用`stash.showIncludeUntracked`来设置是否默认启用--include-untracked`。

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

从贮藏库列表中移除一个单一的贮藏状态,并将其应用于当前工作区状态之上,也就是做`git stash push`的逆向操作。工作目录必须与索引匹配。

应用状态可能会因为冲突而失败;在这种情况下,它不会被从贮藏库列表中删除。你需要手动解决冲突,并在之后调用 git stash drop

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

pop 一样,但不从贮藏库列表中删除该状态。与`pop`不同,`<贮藏项>`可以是任何看起来像由`stash push`或`stash create`创建的提交。

branch <分支名> [<贮藏项>]

创建并检查一个名为 <分支名> 的新分支,从最初创建 <贮藏项> 的提交开始,将 <贮藏项> 中记录的修改应用到新的工作树和索引。 如果成功了,并且`<贮藏项>是`stash@{<版本>}`形式的引用,那么它将删除<贮藏项>`。

如果你运行 git stash push 的分支发生了足够的变化,以至于 git stash apply 因冲突而失败,那么这就很有用。由于贮藏条目是在运行 git stash 时的当前分支提交之上应用的,它没有冲突地恢复了最初的贮藏状态。

clear

删除所有的贮藏条目。直接切断任何联系,而且可能无法恢复(可能的策略见下面的 "例子")。

Drop [-q|--quite] [<贮藏项>]

从贮藏条目列表中删除一个单一的贮藏条目。

create

创建一个贮藏条目(这是一个普通的提交对象),并返回其对象名称,而不将其存储在引用命名空间的任何地方。 这是为了对脚本有用。 你可能不想用这个命令;可以看看前面的 "push"。

store

将通过’git stash create'(这是一个悬空的合并提交)创建的特定贮藏库存储在贮藏库引用中,更新贮藏库参考文件。 这是为了对脚本有用。 这条命令可能不是你想要的;见上文"push"。

选项

-a
--all

这个选项只对`push`和`save`命令有效。

所有被忽略的和未被追踪的文件也被贮藏起来,然后用`git clean`来清理。

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

当与`push`和`save`命令一起使用时,所有未被追踪的文件也被贮藏起来,然后用`git clean`来清理。

当与`show`命令一起使用时,显示贮藏库条目中未被追踪的文件作为差异的一部分。

--only-untracked

这个选项只对`show`命令有效。

只显示贮藏库条目中未被追踪的文件作为差异的一部分。

--index

这个选项只对`pop`和`apply`命令有效。

不仅试图恢复工作区的变化,而且恢复索引的变化。然而,这可能会在出现冲突时失败(这些冲突被存储在索引中,因此你不能再按原来的方式应用这些变化)。

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

这个选项只对`push`和`save`命令有效。

所有已经添加到索引中的变化都保持原样。

-p
--patch

这个选项只对`push`和`save`命令有效。

交互式地从当前分支和工作区之间的差异中选择要存储的内容。 藏匿条目的构造是这样的:它的索引状态与你仓库的索引状态相同,它的工作区只包含你交互选择的变化。 被选中的修改会从你的工作区中回滚。参见 git-add[1] 中的 ‘`互动模式’'一节,了解如何操作`--patch`模式。

选项`---patch`意味着`---keep-index`。 你可以使用`--no-keep-index`来覆盖它。

-S
--staged

这个选项只对`push`和`save`命令有效。

只存放当前分阶段的修改。这类似于基本的`git commit`,只不过是将状态提交到贮藏室而不是当前分支。

`--patch`选项要优先于这个选项。

--pathspec-from-file=<file>

这个选项只对`push`命令有效。

Pathspec在 <file> 中传递,而不是在命令行参数中传递。如果 <file> 正好是 -,则使用标准输入。Pathspec 元素由 LF 或 CR/LF 分隔。可以引用配置变量 core.quotePath 的 Pathspec 元素(请参见 git-config[1])。另请参见 --pathspec-file-nul `和全局 `--literal-pathspecs

--pathspec-file-nul

这个选项只对`push`命令有效。

Only meaningful with --pathspec-from-file. Pathspec elements are separated with NUL character and all other characters are taken literally (including newlines and quotes).

-q
--quiet

这个选项只对`apply`、droppoppushsave、`store`命令有效。

静默,压制反馈信息。

--

这个选项只对`push`命令有效。

为了消除歧义,将路径规范与选项分开。

<pathspec>…​

这个选项只对`push`命令有效。

新的贮藏条目只记录了符合路径规范文件的修改状态。 然后索引条目和工作区文件也被回滚到当前分支中的状态,只留下不符合路径规范的文件。

更多细节请参见 gitglossary[7] 中的 路径规范 条目。

<stash>

这个选项只对`apply`、branchdroppop、`show`命令有效。

一个形式为`stash@{<版本>}的引用。如果没有给出<贮藏项>,则假定是最新的储藏库(即`stash@{0})。

讨论

一个贮藏库条目被表示为一个提交,它的目录树记录了工作目录的状态,它的第一个父节点是创建该条目时在`HEAD`的提交。 第二个父节点的树记录了条目生成时索引的状态,它是`HEAD`提交的一个子节点。 祖先图看起来像这样:

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

其中`H`是`HEAD`提交,`I`是记录索引状态的提交,`W`是记录工作区状态的提交。

实例

拉进一个脏目录树

当你在做某件事的时候,你得知上游有一些变化可能与你正在做的事情有关。 当你的本地修改与上游的修改不冲突时,一个简单的`git pull’就可以让你继续前进。

然而,在有些情况下,你的本地修改确实与上游修改有冲突,而`git pull`拒绝覆盖你的修改。 在这种情况下,你可以把你的进度保存起来,执行一次拉取,然后再解开,像这样:

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

当你正在做某件事的时候,你的老板来了,要求你立即修复某件事。 传统上,你会向一个临时分支提交,以储存你的修改,然后返回到你的原始分支进行紧急修复,就像这样:

# ... 嗨骇害 ...
$ git switch -c my_wip
$ git commit -a -m "我待会还得写点东西"
$ git switch master
$ edit emergency fix
$ git commit -a -m "速速修复BUG"
$ git switch my_wip
$ git reset --soft HEAD^
# ... 继续骇入 ...

你可以用’git stash’来简化上述工作,像这样:

# ... 嗨骇害 ...
$ git stash
$ edit emergency fix
$ git commit -a -m "紧急修复"
$ git stash pop
# ... 继续骇入 ...
Testing partial commits

当你想把工作区上的改动做两个或更多的提交,并且想在提交前测试每个改动时,你可以使用`git stash push --keep-index`:

# ... 嗨骇害 ...
$ git add --patch foo # 仅将第一部分添加到索引中
$ git stash push --keep-index # 将所有其他改动保存到储藏室中
$ edit/build/test first part
$ git commit -m '第一个部分' # 提交完全测试过的改动
$ git stash pop # 准备处理所有其他改动
# ... 重复以上五个步骤,直到剩下一个提交...
$ 编辑/构建/测试剩余部分
$ git commit foo -m '剩余部分'。
保存不相关的变化供将来使用

当你在进行大规模修改时,发现一些不相关的问题,你不想忘记修复,你可以进行修改,将其分阶段,然后使用 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

配置

Warning

Missing zh_HANS-CN/includes/cmd-config-section-all.txt

See original version for this content.

Warning

Missing zh_HANS-CN/config/stash.txt

See original version for this content.

GIT

属于 git[1] 文档

scroll-to-top