gpt4 book ai didi

git - 为什么 git checkout FILE 不重新应用未提交的更改?

转载 作者:太空狗 更新时间:2023-10-29 14:35:22 25 4
gpt4 key购买 nike

git checkout COMMIT将当前状态切换到 COMMIT 指向的状态并重新应用任何未提交的更改(如果您未提交的更改与您要切换到的 COMMIT 不兼容,它甚至会失败。

这个功能与git checkout COMMIT FILE形成鲜明对比它只是盲目地丢弃所有未提交的更改(没有任何警告)FILE并“强制”FILE 的状态在COMMIT .

我的问题是,为什么不一致? (可能与历史/设计决策有关)

当然可以做到 git checkout COMMIT FILE试图重新应用未提交的更改 FILE如果失败,则优雅地失败。特别是因为 git checkout通常被宣传为“安全”操作。如果有的话,git checkout COMMIT FILE 的当前行为应该是 git reset --hard COMMIT FILE 的行为. (附带说明,git reset COMMITgit reset FILE 的行为也为一致性的改进留下了空间...)

最佳答案

git checkout <em>commit</em> switches your current state to that pointed by commit ...

是的,有点。实际上,它在幕后要复杂得多。

... and reapplies any uncommitted changes (it even fails nicely if your uncommitted changes are incompatible with the commit you want to switch to).

它确实不做第一部分(但做第二部分),这就是并发症:什么 git checkout正在做的是the git read-tree documentation calls a two tree merge的一个子集.如果你点击这个链接,你会看到这列出了 21 个单独的案例(一个,案例 #3,有两个子案例,我忽略了不可能发生的案例 #0,所以如果你计算子案例和案例 #0 你得到 23 个不同的案例)。我不会在这里列出它们,但它们可以归结为这个想法:如果 Git 在切换提交时不必触及索引和工作树,它就不会。那是是什么让您未提交的更改保持原样:Git 不会重新应用任何东西,它也不会删除任何东西。它只是轻轻地绕过未提交的更改。

反过来,这在某种程度上(但不完全)解释了这种截然不同的行为,包括我在内的一些人可能会称​​邪恶:

This functions in stark contrast to git checkout <em>commit</em> <em>file</em> which just blindly discards any uncommitted changes (without any warning) of file and "forces" the state of file to that in commit.

是的,这是因为 Git 将您的命令视为替换 file 的索引副本的请求。 来自 commit 。更新后的索引副本也被复制到工作树中。

我认为(过去也曾)认为这应该是一个单独的 Git 命令。它恰好由相同的源代码实现,因为该源代码充满了“从提交中提取文件,写入索引和工作树”的代码。但git reset也是如此, 和 git reset 一个单独的命令。1 所以这充其量只是Hysterical Raisins 的一个借口。形式。

Surely it could have been made such that git checkout <em>commit</em> <em>file</em> attempted to reapply uncommitted changes to file and failed gracefully if that failed.

这也可以在 git checkout 中找到, 在 -m 下选项...有点。但是,它不是基于每个文件,而是仅基于整个提交。也就是说,你可以 git checkout -m <em>commit</em> ,它将您的工作树与目标提交 merge (作为三树 merge ),但不是 git checkout -m <em>commit</em> <em>file</em> .要获得该效果,请从提交中提取文件,选择要提取的 merge 基础版本,然后使用 git merge-file关于三个文件:

git show other:file > file.other
git show base:file > file.base
git merge-file file file.base file.other

1Git 的 reset 将太多不相关的功能塞进一个面向用户的命令中,如果你问我,但你没有。

(On a side note, the behavior of git reset <em>commit</em> and git reset <em>file</em> also leaves room for improvement in consistency...)

好吧,也许你做到了! :-)

关于git - 为什么 git checkout FILE 不重新应用未提交的更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53511125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com