如果我在本地存储库中编辑了一些文件但未提交它们,然后尝试进行git pull
,则失败的原因很明显,即git不知道我打算如何协调新拉出的对这些文件的更改与我有未提交的版本。
我知道解决方案是git pull --rebase --autostash
。但是为什么--rebase
是必需的?
--rebase
option is explained为:
为true时,在获取后将当前分支重新置于上游分支的顶部。
git-rebase-重新应用在另一个基本提示上
但是在上述情况下,没有任何本地提交需要在被拉取的内容之上重新应用,只有未提交更改。为何git决定要求--rebase
做--autostash
,这是否出于某种逻辑?或者这仅仅是偶然的?
答案 0 :(得分:2)
TL; DR:这是历史性的事故。
请记住,git pull
的意思是:
运行git fetch
从其他Git存储库中获取新的提交。任何人都可以随时安全地执行此操作,因此该步骤基本上可以正常工作(除非出于某种原因您的网络已关闭或其他原因)。
然后,假设第1步有效,请运行 second Git命令,该命令会以某种方式使当前分支混乱。
步骤2是有问题的步骤。实际的命令运行通常为git merge
;另一个选项是git rebase
。
现在,如果您有未完成的工作,则不能运行git merge
或git rebase
(除了一个例外,我将在以后讨论)。在这种情况下,步骤1很好,但步骤2不好。
autostash选项基本上为您运行git stash push
,而git stash push
表示提交我现在的内容,但是在 no 分支上,然后执行{{1 }} (它放弃了您所做的工作,但现在已安全地存储在某些提交中)。完成此操作后,现在始终可以执行第2步。如果第2步成功完成(尽管并非总是如此,无论您使用的是第二个命令是什么),Git都会为您运行git reset --hard
。
您可以在此处提出几个合理的问题。一种是:为什么不允许在git stash pop
之前使用它?您可以隐藏,变基和弹出,但也可以隐藏,合并和弹出;如果可以隐藏,合并和弹出,为什么不选择它呢?唯一的真实答案是:当重新设置是一个精美的shell脚本时,添加了git merge
选项以重新提供重新设置,并且更容易在其中添加它。 merge命令不是一个花哨的shell脚本,很难在其中添加它。
另一个问题是我认为您曾问过的一个问题:如果您自己没有提交,并且已经做了--autostash
,都 git stash push
–默认情况下,在这种情况下会执行快进操作,这意味着它实际上并没有合并任何内容-和 git merge
会做同样的事情:直接检查退出另一个Git的最新提交(并且不会在pull的步骤2中失败)。再次,您可能想知道为什么不让git rebase
处理这两种情况。同样,唯一的真实答案是“因为它更容易添加到基准代码路径中”。
我们应该注意,即使--autostash
可以进行快进,也并非总是如此。特别是,您可以使用git merge
强制Git进行真正的合并,而不是进行快进操作。您也可以使用git merge --no-ff
将其设置为在拉(git config
)或始终(pull.ff
)进行。因此,pull可以进行合并,即使它可以进行快进也可以。尽管如此,如果它可以快速前进,它将进行的合并将成功,并且我们回到与以前相同的情况。
现在该提一个特殊情况了。如果merge.ff
可以并且确实选择执行快进操作(本质上是git merge
可以将分支名称向前拖动到提交图中),而不是真正的合并,那么Git可以执行此操作即使您有未完成的工作,只要未提交的工作位于结帐未更新的文件中。因此,有一种情况,使用git checkout
的{{1}}不会 require 自动存储。尽管如此,实际上做一个推/快进/弹出顺序就可以了,我们真的又回到了历史性事故。
如果您对这种事情有强烈的感觉,则可以随时编写一个补丁来教Git如何自动隐藏git pull
和/或git merge
。 Git的来源是可用的;参见例如https://github.com/git/git上的仅发布克隆。