我遇到了一个我不理解结果的场景。
我的团队正在开发一个带有提交的功能分支:
A--B--C
Run Code Online (Sandbox Code Playgroud)
一位同事推送了两个新提交:
A--B--C--D--E
Run Code Online (Sandbox Code Playgroud)
我,没有意识到其他人正在将代码推送到这个分支,我强制推送了一个修改后的提交:
A--B--C'
Run Code Online (Sandbox Code Playgroud)
在我意识到我的错误后,我建议他尝试(在他的仓库中,D 和 E 仍然存在):
git pull -r
git push
Run Code Online (Sandbox Code Playgroud)
我的想法是他的两次提交(D,E)不再出现在分支的历史记录中,因此,在 pull 时,git 会尝试将它们合并到历史记录中。我的期望是 D 和 E 会在 C' 之上重新建立,但这并没有发生。相反(释义):
$ git pull -r
+ commit...commit branch -> origin/branch (forced update)
$ git push
Everything up-to-date
Run Code Online (Sandbox Code Playgroud)
D和E不见了。我想也许他对他的 repo 做了一些其他的操作,所以它可能处于某种未知状态,所以我们在 reflog 中找到了 E 的哈希值,并做git reset --hard <E>了几次再试(主要是因为我很好奇为什么它没有像我预期的那样消失)并得到相同的结果。
我确定我误解了一些东西,但我不确定是什么。为什么不将git pull -r“新”提交 D 和 E(即我无意中从历史记录中删除的那些)重新设置在 C' 之上?
正如一些人指出的那样:C 也应该包含在我的期望中。我没有考虑那个,但我明白为什么,这是有道理的。
我的期望是“新”提交(现在更新为 C、D、E;即使它有效,也不会是我想要的)会被重新定位,但它们不是,我不明白为什么。
@matt 关于之前推送的提交的评论很有趣。如果有人可以详细说明该机制,这似乎是一个潜在的答案。
发生这种情况的原因是git pull -r(或git pull --rebase) 与以下命令不同:
git fetch
git rebase @{u}
Run Code Online (Sandbox Code Playgroud)
如果您运行这些命令,您将C-D-E在 之上重新建立基础A-B-C',产生:
A-B-C'-C-D-E。(也许 C 会失败,具体取决于你的修改做了什么。)
因为pull -r不完全是幕后的命令,强制推送后的结果将如您所见。
这是强制推动不受欢迎的另一个原因。这也是我一般不喜欢拉动的另一个原因。我总是更喜欢单独输入这两个命令,以防万一。
作为旁注(并在评论中提到),如果您使用git push --force-with-lease而不是git push --force您会注意到远程分支上的更改,并且能够重新设置您的分支而不是强制推送。我强烈建议始终使用--force-with-lease(或者可能是较新的--force-if-includes),除非您有一个特定的人为场景--force是必要的。
| 归档时间: |
|
| 查看次数: |
103 次 |
| 最近记录: |