仅存储未分阶段的Git更改


228

我想执行以下工作流程:

  1. 向舞台添加更改。
  2. 存放所有其他尚未上演的更改。
  3. 在阶段中做一些事情(例如,构建,运行测试等)
  4. 应用藏匿处。

有步骤2的方法吗?

 echo "123" > foo
 git add foo # Assumes this is a git directory
 echo "456" >> foo
 git stash
 cat foo # Should yield 123

在暂存更改后为什么不提交更改?
Shizzmo 2011年

3
IIRC --keepindex正是这样做的
sehe

4
因为如果说构建失败,我不想提交。我知道我可以删除提交,但是如果可能的话,我想不提交就删除它。
Unapiedra 2011年

喂谢谢 我可以确认这项工作。e,我看了一下linux.die.net/man/1/git-stash上的手册,它已经过时了。man git stash好多了。
Unapiedra 2011年

是--keep-index,fwiw。
jaf0 2014年

Answers:


287

git stash save有一个选项--keep-index可以满足您的需求。

因此,运行git stash save --keep-index


9
真正。我继续使用savegit stash。也许是我中的程序员坚持用apply / pop来尊重对称性。:)
vhallac 2011年

104
注意:这仍然会存储您的所有更改;与常规文件的唯一区别git stash save在于,它也将已经分阶段进行的更改也保留在工作副本中。在上面的工作流程中,这是可以正常工作的,因为您只是将隐藏应用在已经具有隐藏存储更改一半的本地副本之上(git非常聪明,可以忽略)。但是,如果在重新应用存储之前编辑代码,则在应用时可能会看到合并冲突。菲
peterflynn 2014年

2
@ytpete咬了我好多次。我真的希望git有一种方法可以只隐藏您不保留的内容...我经常提交东西,然后进行完整的git隐藏,知道我所提交的内容git commit --ammend如果有问题就可以。
rjmunro 2014年

1
--amend(而不是--ammend
Rhubbarb,2015年

19
由于peterflynn描述的问题,该解决方案对我不起作用。这不是一个很好的答案,因为它仍然隐含了分阶段进行的更改。有人有更好的解决方案吗?
user643011

43

这可以分3个步骤完成:保存已分阶段的更改,存储所有其他内容,使用已分阶段的更改还原索引。基本上是:

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

这将完全满足您的要求。


3
注意:-u还会存储未跟踪的文件。
ma11hew28

这种方法本质上是重复git stash save --keep-index了很多工作。我看不出任何优势。
Inigo

1
@vas否,该方法不会重复该操作。请参阅peterflynn对已接受答案的评论。
亚历山大·克劳尔

28
git stash save --keep-index

另外,Re:

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

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

除了所有这些事实,当然,作为一个经验丰富的程序员,您有天生的冲动去测试和审查那些更改,只是部分是在开玩笑。


14

git version 2.7.4您一起可以做:

git stash save --patch

git会要求你添加或不更改为藏匿。
然后你就回答yn

您可以像往常一样还原工作目录:

git stash pop

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

git stash apply

这太棒了。这有点费力,但是至少您可以跳过并添加整个文件。
Dustin Oprea

5

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

首先隐藏所有内容,但完整保留分阶段的更改

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

现在也分别存储分阶段的更改

$ git stash保存

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

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

$ git commit -m“修复...”

现在,还原先前上演的更改:

$ git stash pop

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

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


4

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

git stash -k

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

git stash pop

4

在Git中仅存储工作树(未分阶段的更改)比应有的困难。接受的答案会隐藏未分阶段的更改,但也会隐藏已分阶段的更改(并使它们也已分阶段),这几乎是您所不想要的。

此别名运作良好:

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

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

它与@Simon Knapp的答案类似,但有一些细微的区别-它用于--quiet执行的临时操作,并且可以为存储项接受任意数量的参数push,而不是对进行硬编码-m,并且确实会增加--soft最终值重置,以使索引保持为开始状态。

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


2

与该问题有关的另一个技巧:

当您有效地存储您未使用的更改时,使用

$ git stash save --keep-index

您可能希望给存储区一个消息,以便在执行git stash list存储操作时,您之前存储的内容更加明显,特别是如果您通过进一步保存执行存储操作时。例如

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

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

例如,上面可能紧随其后:

$ git stash保存“功能X的分阶段更改”

但是要当心,您不能再使用

$ git stash apply“ stash @ {1}” ###✘并未完全满足您的要求

还原未分级的更改。


2

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的答案可能会更容易。


0

该命令的现代形式是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脚本)

参见Thomas Gummerer()的commit 7db9302(2019年3月11日。 请参阅Johannes Schindelin()的提交1366c78提交7b556aa(2019年3月7日(通过合并JUNIOÇ滨野- -提交0ba1ba4,2019年4月22日)tgummerer
dscho
gitster

内置stash:(glob)再次处理pathspecs

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

这有所作为,例如在打电话时

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

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

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

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

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


0

我使用一个别名,该别名接受一个字符串用作存储项的消息。

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

哪一个:

  • 提交索引中的所有内容,
  • 隐藏工作树中的更改(当然可以添加-u-a),
  • 将最后一次提交重置为工作尝试(可能要使用--soft以将其保留在索引中)。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.