308

我想使用这个工作流程:

  1. 阶段性的一些变化。
  2. 将未暂存的更改保存到存储中。
  3. 对阶段中的事物做一些事情(构建、测试等)。
  4. 犯罪。
  5. 恢复未暂存的更改。

有没有办法做第2步?

例子:

git init
echo one >file
git add file
git commit
echo two >>file
git add file
echo three >>file
git stash push
test
git commit
git stash pop
4

14 回答 14

383

git stash push有一个选项--keep-index可以完全满足您的需要。

所以,运行git stash push --keep-index

于 2011-10-04T16:10:50.650 回答
72

这可以通过 3 个步骤完成:保存分阶段更改、存储其他所有内容、使用分阶段更改恢复索引。基本上是:

git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^

这将完全符合您的要求。

于 2015-04-25T10:13:12.747 回答
31
git stash save --keep-index

另外,回复:

为什么不在暂存后提交您的更改?– 申

答:因为您应该始终检查已测试的代码 :) 这意味着,您只需要使用即将提交的更改来运行测试

所有这一切,当然,作为一个有经验的程序员,你天生就有测试和审查这些变化的冲动——只是部分开玩笑

于 2011-10-04T16:13:25.937 回答
21

没有分阶段更改的存储

--keep-index/的问题-k

在 Git 中仅存储工作树(未暂存的更改)比应有的困难。接受的答案,以及相当多的其他答案,隐藏了未暂存的更改,并按照要求通过--keep-index.

然而,不明显的是,它--keep-index隐藏了分阶段的变化。分阶段的更改最终会出现在阶段和存储中。这很少是人们想要的,因为对存储的任何临时更改都可能在以后弹出存储时导致冲突。

别名解决方案

这个别名非常适合暂存工作副本更改:

stash-working = "!f() { \
  git commit --quiet --no-verify -m \"temp for stash-working\" && \
  git stash push \"$@\" && \
  git reset --quiet --soft HEAD~1; }; f"

它临时提交分阶段的更改,从剩余的更改中创建一个存储(并允许其他参数,例如--include-untracked--message作为别名参数传递),然后重置临时提交以取回分阶段的更改。

它类似于@Simon Knapp 的答案,但有一些细微的差别——它用于--quiet临时操作,并且它接受任意数量的 stash 参数push,而不是硬编码-m,它确实添加--soft到 final重置,以便索引保持启动状态。它还用于--no-verify提交以避免从预提交挂钩(HT:@Granfalloner)更改工作副本。

对于仅存储分阶段更改(别名stash-index)的相反问题,请参见此答案

于 2020-03-26T19:50:16.660 回答
20

git version 2.7.4可以这样做:

git stash save --patch

git要求您将更改添加或不添加到存储中。
然后你只需回答yn

您可以像往常一样恢复工作目录:

git stash pop

或者,如果您想将保存的更改保存在存储中:

git stash apply
于 2017-06-29T11:48:49.440 回答
12

要将未标记(未添加到提交)的文件添加到存储,请运行以下命令:

git stash -k

如果您想将新添加的文件(未暂存 - 不是绿色)也包含到存储中,请执行以下操作:

git stash -k -u

然后您可以提交暂存文件。之后,您可以使用以下命令取回最后隐藏的文件:

git stash pop
于 2018-11-23T10:49:57.123 回答
5

Git 没有仅存储未暂存更改的命令。

但是,Git 确实允许您指定要存储的文件。

git stash push --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

如果您只想在这些文件中存储特定更改,请添加该--patch选项。

git stash push --patch --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

--include-untracked选项允许您存储未跟踪的文件。

git stash push --include-untracked --message 'Untracked files' -- app/controllers/widgets_controller.rb test/controllers/widgets_controller_test.rb

运行git help stash(或man git-stash)以获取更多信息。

注意:如果您的未分级更改相当混乱,@alesguzik 的答案可能更容易。

于 2018-12-17T22:14:38.900 回答
4

扩展以前的答案,我有时会进行一组复杂的更改,但希望先提交单独的更改。例如,我可能已经发现了一个错误或其他不正确的代码,我想在分阶段更改之前修复它们。一种可能的方法是:

首先存储所有内容,但保留分阶段的更改

$ git stash save --keep-index [--include-untracked]

现在也单独存储分阶段的更改

$ git stash 保存

进行更改以进行修复;和测试;提交他们:

$ git add [--interactive] [--patch]

$ git commit -m"修复..."

现在恢复先前阶段的更改:

$ git stash pop

解决任何冲突,并注意如果存在冲突,git 将应用但不会删除该顶级存储条目。

(...然后提交分阶段的更改,并恢复所有其他更改的存储,然后继续...)

于 2015-01-21T13:10:39.357 回答
3

与问题相关的另一个提示:

当您使用

$ git stash save --keep-index

您可能希望给 stash 一条消息,这样当您执行 a 时,git stash list您之前存储的内容会更加明显,特别是如果您通过进一步保存来遵循该 stash 操作。例如

$ git stash save --keep-index "更改尚未上演"

(尽管实际上它确实包含其他答案中提到的所有更改)。

例如,上面可能紧跟着:

$ git stash save “功能 X 的阶段性更改”

但请注意,您不能使用

$ git stash apply "stash@{1}" ### ✘ 并不完全符合您的要求

只恢复未暂存的更改。

于 2015-01-21T13:21:44.270 回答
3

I use an an alias, which accepts a string to use as a message to the stash entry.

mystash = "!f() { git commit -m hold && git stash push -m \"$1\" && git reset HEAD^; }; f"

Which:

  • commits everything in the index,
  • stashes what is changed in the working tree (could of course add -u or -a),
  • resets the last commit back to the working try (may want to use --soft to keep it in the index).
于 2020-03-13T00:59:14.693 回答
1

这是(在我看来)最好的解决方案,它完全符合 OP 的要求。它只存储未暂存的、跟踪的文件——没有不必要的提交或存储所有更改的文件--keep-index

它列出了所有未暂存的、跟踪的更改 ( git diff --name-only) 将换行符转换为空格 ( | tr '\n' ' ') 并使用以下命令存储所有这些文件git stash push

git stash push $(git diff --name-only | tr '\n' ' ')
于 2022-02-17T00:08:06.883 回答
1

从 Git 2.35+(2022 年第一季度)开始,您现在可以使用--staged标志 ( man )来仅暂存index 中git stash push的更改。

由于您的问题完全相反,我们有两个选择:

  1. 像这样反转操作:
git stash push --staged            # Stash staged changes
git stash                          # Stash everything else
git stash pop stash@{1}            # Restore staged changes stash
  1. 暂存您想要隐藏的更改,而不是您想要保留的更改。现在你可以运行:
git stash push --staged

我从另一个 S/O 帖子的这个答案中获得了这些信息。

于 2022-02-22T13:53:01.133 回答
0

2022:我在“ Stash only staged changes in git - is it possible? ”中提到,Git 2.35(2022 年第一季度)带有“ git stash push --stagedman

此选项仅对推送和保存命令有效。

仅存储当前暂存的更改。
这类似于基本git commit的,除了状态被提交到存储而不是当前分支。


2019:该命令的现代形式是git stash push [--] [<pathspec>...],因为 Git 2.16+(git stash save已弃用

您可以将其与通配符形式结合使用,例如:

git stash push --all --keep-index ':(glob)**/*.testextension' 

但这不适用于 Windows 的 Git,直到 Git 2.22(2019 年第二季度),请参阅issue 2037,考虑到git stash已在 C 中重新实现(而不是 shell 脚本)

请参阅Thomas Gummerer ( ) 的提交 7db9302(2019 年 3 月 11 日。 请参阅Johannes Schindelin ( ) 的commit 1366c78commit 7b556aa(2019 年 3 月 7 日(由Junio C Hamano 合并 -- --0ba1ba4 提交中,2019 年 4 月 22 日)tgummerer
dscho
gitster

内置:再次stash处理路径规范:(glob)

在将路径规范列表传递给 时git add,我们需要小心使用原始形式,而不是路径规范的解析形式。

这会有所不同,例如在调用时

git stash -- ':(glob)**/*.txt'

其中原始形式包含:(glob)前缀,而解析后的形式不包含。

但是,在内置的 中git stash,我们传递了已解析(即不正确)的表单,并且git add会失败并显示错误消息:

fatal: pathspec '**/*.txt' did not match any files

在从工作树中git stash删除更改的阶段,即使refs/stash实际上已成功更新。

于 2019-04-22T18:26:43.990 回答
0

据我所知,目前不可能使用保存工作树中未暂存的更改git stash push,即保存索引状态的更改。此命令保存工作树中的所有更改(分阶段和非分阶段更改),即从 HEAD 状态更改,即使使用--keep-index将工作树状态设置为索引状态而不是 HEAD 状态的选项(从而在恢复用 ) 从 HEAD 状态更改。如果有一个只保存未暂存更改的选项(对我来说这个选项有缺陷),那将非常方便,因为它已经有一个只保存暂存更改的选项。git stash popgit stash push-U|--unstaged--keep-index-S|--staged

所以暂时你必须效仿

git stash push --unstaged

git stash pop

有一个临时文件:

git diff >unstaged
git restore .

git apply unstaged
rm unstaged

您的用例是在提交部分更改之前进行测试,它已经在参考文档中,但有缺陷的选项--keep-index会产生冲突。这是带有模拟选项的版本-U|--unstaged

git init
echo one >file
git add file
git commit
echo two >>file
git add file
echo three >>file
git diff >unstaged
git restore .
test
git commit
git apply unstaged
rm unstaged

可视化状态

为了更好地理解存储,我认为在每个步骤中查看工作树、索引和 HEAD 的状态很重要。让我们来看看你的用例。

git init

在职的 指数

echo one >file

在职的 指数

git add file

在职的 指数

git commit

在职的 指数

echo two >>file

在职的 指数

git add file

在职的 指数

echo three >>file

在职的 指数

git diff >unstaged

git restore .

在职的 指数

test

git commit

在职的 指数

git apply unstaged

rm unstaged

在职的 指数
于 2022-01-30T13:14:21.150 回答