如何在Git中仅隐藏未暂存的更改?

380

我想使用以下工作流程:

  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
如果我没记错的话,“--keepindex”正是这样做的。 - sehe
5
如果构建失败,我不想提交这个版本。我知道我可以删除提交记录,但如果可能的话,我希望不用提交就能解决这个问题。 - Unapiedra
Sehe,谢谢。我可以确认这个有效。天哪,我看了过时的http://linux.die.net/man/1/git-stash手册。`man git stash`更好。 - Unapiedra
这帮助我学习了'index' == 暂存区。 - JonnyRaa
git push [-k|--keep-index]时,没有必要限制stash数据。相反,您可以在应用时决定并使用git cherry-pick -m2 -n stash仅选择未暂存的更改。请参见详细答案。 - kxr
显示剩余5条评论
16个回答

3

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

当您使用

$ git stash save --keep-index

有效地隐藏您的未暂存更改时,您可能希望给stash一个消息,以便在执行 git stash list 时更容易看出您之前隐藏了什么内容,特别是如果您在随后进行更多保存的操作。例如:

$ git stash save --keep-index "changes not yet staged"

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

例如,上述操作可能会立即跟随以下操作:

$ git stash save "staged changes for feature X"

但要注意,您则无法使用

$ git stash apply "stash@{1}" ### ✘ 并不能完全恢复您想要的未暂存更改

仅恢复未暂存的更改。


2
2022年:我在 "仅将暂存的更改藏在 Git 中 - 可以吗?"中提到,Git 2.35(2022年第一季度)带来了 "git stash push --staged"(man)

此选项仅适用于 push 和 save 命令。

仅藏匿当前已暂存的更改。
这类似于基本的 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 年第二季度),参见 问题 2037,考虑到 git stash 已经被重新实现为 C 语言代码(而不是一个 shell 脚本)。
查看提交7db9302(2019年3月11日),作者为Thomas Gummerer(tgummerer
查看提交1366c78提交7b556aa(2019年3月7日),作者为Johannes Schindelin(dscho
(由Junio C Hamano -- gitster --提交0ba1ba4中合并,日期为2019年4月22日)

built-in stash: handle :(glob) pathspecs again

When passing a list of pathspecs to, say, git add, we need to be careful to use the original form, not the parsed form of the pathspecs.

This makes a difference e.g. when calling

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

where the original form includes the :(glob) prefix while the parsed form does not.

However, in the built-in git stash, we passed the parsed (i.e. incorrect) form, and git add would fail with the error message:

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

at the stage where git stash drops the changes from the worktree, even if refs/stash has been actually updated successfully.


1
以下是我认为最好的解决方案,完全符合 OP 的要求。它仅存储未暂存但已跟踪的文件,无需进行不必要的提交或使用 --keep-index 存储所有更改的文件。
它列出了所有未暂存但已跟踪的更改(git diff --name-only),将换行符转换为空格(| tr '\n' ' '),并使用 git stash push 存储所有这些文件。
git stash push $(git diff --name-only | tr '\n' ' ')

简单而有效!谢谢! - Georgiy Bukharov
没问题!很高兴能帮助@GeorgiyBukharov - citysurrounded
我刚刚运行了这个程序,它也隐藏了我的未提交更改。 - Anentropic
@Anentropic 这正是 OP 所要求的-储存未暂存的更改。那是打字错误吗? - citysurrounded
这将隐藏所有具有未暂存更改的文件,这意味着它也将隐藏那些文件在暂存区中的更改。 - jrg
显示剩余2条评论

0
重新考虑:不必将贮藏的数据仅限制于工作树更改,而是可以在应用时决定仅应用贮藏的工作树更改。
因此,在贮藏时就像往常一样:
git stash [-k|--keep-index]

在应用时间执行

git cherry-pick -m2 -n stash

解释: -m2 选择阶段提交的第二个父级所做的更改,即存储的索引状态。 -n | --no-commit 阻止自动提交。 stash@{1} 将是堆栈上第二个贮藏的引用...


0

-1
据我所知,使用git stash push目前不可能仅保存工作树中未暂存的更改,即保存来自索引状态的更改。该命令会保存工作树中的所有更改(已暂存和未暂存的更改),即来自HEAD状态的更改,即使使用选项--keep-index也会将工作树状态设置为索引状态而不是HEAD状态(因此在使用git stash pop从HEAD状态恢复更改时会创建冲突)。如果git 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

工作区 索引 HEAD

echo one >file

工作区 索引 HEAD
one

git add file

工作区 索引 HEAD
one one

git commit

工作区 暂存区 版本库
one one one

echo two >>file

工作区 暂存区 版本库
one one one
two

git add file

工作区 暂存区 版本库
one one one
two two

echo three >>file

工作区 暂存区 HEAD
one one one
two two
three

git diff >unstaged

git restore .

工作区 暂存区 HEAD
one one one
two two

测试

git commit

工作区 索引区 HEAD
one one one
two two two

git apply unstaged

rm unstaged

工作区 索引区 HEAD
one one one
two two two
three

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接