为什么'git stash apply'应用我的变化?

时间:2009-08-06 04:46:59

标签: git

我进行了更改,然后是git stash,然后是git stash apply

我的问题是

  1. 为什么在git stash apply之后,我的变化变为'上演'?即如果我做git diff,我就什么都看不到,如果我做git diff --cached,我只能看到我的不同之处?

  2. 无论如何要通过git stash apply命令“取消暂停”我的更改?

  3. 是否有任何git命令基本上让我'备份我的更改,将其重置为HEAD并将我的备份复制回来'?我认为git stash然后git stash apply就是那个命令,但有些人如何'上演'我的所有变化?是否有任何等同物让我git stash apply没有上演我的更改部分?

3 个答案:

答案 0 :(得分:13)

如果您发现您的更改意外暂停,请执行以下操作:

git reset HEAD

如果在应用隐藏更改时发生冲突,我通常只会看到这一点。在执行git reset之前,您需要检查是否是这种情况。

git stash命令是最适合您用例的命令。我一直用它来达到这个目的。

答案 1 :(得分:9)

  

为什么git stash会应用我的更改?

任何会影响工作树的内容(like a git checkout -- afile)都会首先影响您的索引。

  

索引是将工作树中的东西移动到对象存储库以及将东西从对象存储区移动到工作树的中间人。

git stash apply也使用索引来记录合并冲突,index has stage-n entries。见git merge

  

对于冲突路径,索引文件最多可记录三个版本:

     
      
  • 阶段1存储来自共同祖先的版本
  •   
  • HEAD的第2阶段,
  •   
  • 来自MERGE_HEAD的第3阶段(您可以使用git ls-files -u检查阶段)。
  •   

git stash --apply的演变历史中,需要注意两个有趣的事件: 2011年4月(Git 1.7.5.1,commit e0e2a9c),stash在申请时删除了肮脏的工作树检查。

  

在我们应用存储之前,我们确保工作树中没有不在索引中的更改。此检查的日期可以追溯到原始git-stash.sh,并且可能是为了防止工作树中的更改在合并期间意外丢失。

     

但是,此检查有两个问题:

     
      
  1. 这是过于严格的限制。如果我的藏匿只更改文件" foo",但" bar"在工作树中很脏,它会阻止我们应用藏匿处。

  2.   
  3. 这是多余的。在我们实际调用merge-recursive之前,我们根本不会触摸工作树   但它有自己的(更准确的)检查,以避免丢失工作树数据,并将通过更好的消息中止合并,告诉我们哪些路径是问题。

  4.         

    所以我们可以完全放弃支票。

使用索引管理由git stash apply导致的合并导致另一个错误,在2015年4月检测到,Git 2.4.2,commit ed178ef

  

stash:需要一个干净的索引来应用

     

如果您在索引中已暂存内容并运行" stash apply",我们可能会遇到冲突并将新条目添加到索引中。
  此时恢复到原始状态很困难,因为" git reset --keep"会吹走任何上演的东西   我们可以通过在有阶段性变化时拒绝申请来使这更安全。

答案 2 :(得分:3)

我认为您的配置可能有问题,因为git stash在重置为最新提交之前记录索引状态和工作树,git stash apply应该只尝试恢复状态如果您使用--index选项,则为索引。

一个可能的混淆点是,如果你有冲突(即引入合并冲突,因为存储被应用于一个不同的提交,其中受存储影响的文件自存储的提交以来已被更改),然后如果您使用mergetool来解决冲突,mergetool会在成功解决后自动暂存对文件的更改。

正如Greg Hewgill所说,简单的重置将取消所有阶段性的变化。

git reset