我想使用这个工作流:

进行一些改变。 将未分阶段的更改保存到存储中。 用阶段中的东西做一些事情(构建、测试等)。 提交。 恢复未分阶段的更改。

有办法完成第二步吗?

例子:

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

当前回答

从Git 2.35+ (Q1 2022)开始,你现在可以在Git stash推送上使用——staging标志(man)来只stage你的索引的变化。

既然你的问题正好相反,我们有两个选择:

像这样反向操作:

git stash push --staged            # Stash staged changes
git stash                          # Stash everything else
git stash pop stash@{1}            # Restore staged changes stash

阶段性的更改是你想要保存的,而不是你想要保留的。现在你可以运行:

git stash push --staged

我从另一个S/O帖子的回答中得到了这个信息。

其他回答

重新思考:没有必要只将存储数据限制在工作树更改上,但是可以稍后在应用时决定只应用存储的工作树更改。

因此,在储存时间,只要像往常一样做:

git stash [-k|--keep-index]

在申请的时候

git cherry-pick -m2 -n stash

解释:-m2选择对阶段提交的第二个父元素的更改,即存储的索引状态。-n|——no-commit阻止自动提交。stash@{1}将是堆栈中第二个stash的ref…

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

首先把所有东西都藏起来,但保留阶段性的变化

$ git保存——keep-index[——include-untracked]

现在也将阶段性更改单独保存

$ git保存

为解决问题做出改变;和测试;提交:

$ git add[——interactive][——patch] $ git commit -m"fix…"

现在恢复之前的更改:

$ git隐藏pop

解决任何冲突,并注意如果存在冲突,git将应用而不是删除顶部的隐藏条目。

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

Git stash push有一个选项——keep-index,这正是你所需要的。

运行git stash push——keep-index。

没有阶段性变化的隐藏

——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推送,而不是硬编码-m,它确实在最终重置中添加——soft,以便索引保持它开始时的状态。它还在提交时使用——no-verify来避免来自预提交钩子(HT: @Granfalloner)对工作副本的更改。

关于只存储阶段性更改的相反问题(别名stash-index),请参阅此答案。

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

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

这正是你想要的。