Git - 为什么有些客户端在有阶段性更改时不能应用存储

Git - why can't some clients apply stash when there are staged changes

我为 file1 隐藏了一些更改。然后我在一个独特的 file2 中改变了一些东西并且我上演了这些改变。

当我尝试应用存储时,我会得到不同的行为,具体取决于我使用的 Git 客户端:

这些是操作不成功时的错误:

考虑到隐藏文件和暂存文件是不同的,为什么在与某些客户合作时不应用隐藏?

顺便说一句,我问这个是因为我们正试图在基于 JGit 的 Git 客户端中实施“应用存储”操作,并且我们遇到与EGit(也是基于JGit).

git stash 在幕后创建一个提交(它实际上创建了 2 个提交:检查 git log --oneline --graph stash 以查看它),并且 git stash apply 大致是 git cherry-pick 的序列在这些提交上。

因此,当您尝试恢复与最初不完全相同的工作树+索引上的存储时,您可能会遇到冲突(常规冲突)。


如果遇到冲突,您应该处理它们,或者向用户显示一条消息,说明“存在冲突,请处理它们”。

使用任何客户端都会发生同样的冲突,也许 git cli 或 SourceTree 只是提及冲突而不用大错误消息突出显示它。

GitKraken 显然增加了一个额外的安全步骤:如果索引中有内容,它会拒绝应用存储。
这是有道理的技术原因:在实际应用存储之前,您无法真正预览索引将如何修改,并且如果索引被弄乱,用户没有可行的方法来恢复他的索引。
强制用户提交(或丢弃、隐藏或...)是防止此问题的一种方法。

EGit 不是 Git,GitKraken 也不是 Git。这两个似乎在不同方面与 Git 不同,但是:

  • EGit 是 Git 的 重新实现 ,使用 JGit。由于它是一个完全不同的源代码库,它将与 Git 本身同步或不同步,因为 Git 获得了 JGit 缺少的新功能,或者 JGit获得 Git 缺少的新功能。这甚至很难猜测某些组件 X 是否会在两者中工作,如果是,则以相同的方式工作。

  • GitKraken 似乎是一个 GUI 包装器 for Git。如果字面上是 运行ning Git,那么当它 运行 Git 时,效果将与原始 Git.

    中使用的效果相匹配

在你的例子中,你发现 JGit 的存储应用代码(至少 EGit 使用的)与 Git 的不匹配. (Git 的存储应用代码在 Git 2.22.0 中从 shell 脚本重写为 C,于 2019 年 6 月首次发布,随后在行为上有一些小的变化,但这个特别行为在 Git 很长一段时间内没有改变:git stash apply 总是允许应用带有“脏”工作树的存储。我强烈建议 不要 做这是我自己,所以 EGit 的行为可以说是“更好”,但它是不同的。)

正如 LeGEC 所说,GitKraken 的抱怨是您的索引当前与您当前的提交不匹配。这实际上也可能是一件明智的事情:git stash apply 必须 运行 合并机器,合并机器需要使用索引。旧的脚本版本和 C 版本在这里可能有些不同,尤其是在新的合并代码进入时,但是同样,如果这个工作树的(主)索引与此工作树的提交。

LeGEC 的回答有一个技术错误(可能用 roughly 这个词掩盖了):

... and git stash apply is roughly a sequence of git cherry-picks on those commits.

取消隐藏将:

  • 如果你使用 --index,应用索引提交的索引更改,否则完全忽略它;
  • 使用默认(当前,recursive,即将 ort)合并策略应用工作树提交的更改。

合并策略代码并不总是进行自己的检查以确保工作树和索引在开始工作之前是“干净的”,部分原因是相同的代码被章鱼策略重新使用,其中每个要合并的提交按顺序 运行。然后章鱼策略会注意到任何冲突,并在发生任何冲突时完全中止合并,而常规 recursive/resolve 代码会在索引和工作树中留下合并混乱。

如果不实际尝试合并,则无法预测是否以及何时应用存储会导致冲突。事实上,合并 使用 索引 工作树,至少在当前的实现中,这意味着应用一个存储与其中任何一个“ dirty”(与当前提交不匹配)会给你留下一个不容易恢复的混乱:git reset --hard,它干净地中止了一个失败的合并,从一个干净的设置开始,破坏了正在进行的工作 git stash apply 搞砸了。

在您的特定情况下,显然合并进行得很顺利,也不需要触及暂存文件。 Git 在这里进行了一些优化,这对于使 git merge 的速度达到可接受的速度很重要,以避免触及不需要对它们做任何事情的文件的索引或工作树,这可能就是让你逃脱的原因这个。