奇怪的 git 合并问题
这是 gitk 目前在我们的一个项目中的样子:
https://dl.dropbox。 com/u/2582508/gitk.png
据我们所知,这显然是在远程分支完成一次“git merge”之后发生的 - 我们不确定为什么或发生了什么。知道这里发生了什么吗?
更重要的是,修复它的最佳方法是什么?这些合并提交是空的,但是当执行“git rebase -i”时,合并提交通常似乎不会出现。
最重要的是,我不想让历史与其他克隆不兼容,即它们仍然应该能够与其拉/推/合并。这可能吗?
This is how gitk currently looks in one of our projects:
https://dl.dropbox.com/u/2582508/gitk.png
This apparently, from all we can tell, happened after a single "git merge" was done with a remote branch - we're not sure why or what is going on. Any idea what happened here?
More importantly, what's the best way to fix it? Those merge commits are empty, but when doing "git rebase -i" merge commits generally don't seem to appear.
Most importantly, I would prefer to not make the history incompatible with other clones, i.e. they should still able to pull/push/merge with it. Is that even possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是某人使用 git pull(或者等效地,git fetch 和 git merge)更新其项目的结果。想象一下,您的存储库看起来像这样:
也就是说,您已经在原始仓库。
与此同时,其他人进行更改并将其推送到共享存储库。如果你然后运行 git fetch ,你的存储库看起来像这样:
现在,如果你运行 git merge (记住:
git pull
只是git fetch
后跟git merge
)。你会得到这样的结果:假设一切顺利,
G
可能只是一个“愚蠢的”合并提交;从技术上讲,G
的状态与F
和C
不同,因此必须以不同方式考虑。现在,如果你推动这个改变,你会得到这个:
如果你继续开发,你会得到这个:
现在,如果你继续这样做(并且如果很多人继续这样做),你最终会得到一棵像这样的树你照片中的那个。这并不是“错误”,但很多人不喜欢它,因为它使得发展历史很难遵循。
这个问题的解决办法就是教人们rebase。变基将(正如您所指出的)远程无用的合并提交,并为您提供更清晰的历史记录。在上面的例子中,你最终会得到一个线性的开发历史。这更容易遵循。但是,您需要知道,在变基之后,您需要重建并重新测试您的代码……仅仅因为代码很容易合并并不意味着结果是正确的。
如果您使用中央存储库来共享官方开发线,您可以实现一个预接收钩子来检测这些自动(“愚蠢”/“无用”)合并提交并拒绝推送 - 强制用户重新设置基准。实际上,您希望挂钩查找默认的合并提交消息...因此,如果您确实想保留合并提交(有时这是有意义的),您至少必须编写一条智能提交消息。
这是一个钩子示例。我去掉了一些额外的东西,所以我没有测试它。
This is the result of someone updating their project using
git pull
(or, equivalently,git fetch
andgit merge
). Imagine you're repository looks like this:That is, you've done commits
A
,B
andC
on top of what was in the original repo.In the mean time, some else makes changes and pushes them up to the shared repository. If you then run
git fetch
your repository looks like this:Now, if you run
git merge
(remember:git pull
is justgit fetch
followed bygit merge
). You'll have this:Assuming all goes well,
G
is probably just a "stupid" merge commit; technically, the state ofG
is different fromF
andC
and so it must be considered differently.Now, if you push this change, you'll have this:
And if you continue development you'll get this:
Now, if you keep doing this (and if many people keep doing this) you'll end up with a tree like the one in your picture. This isn't "wrong" but many people don't like it because it makes the development history very hard to follow.
The solution to this problem is to teach people to rebase. Rebasing will (as you noted) remote the useless merge commits and git you a much cleaner history. In the case above, you'll end up with a linear development history. That's much easier to follow. However, you need to know that after you rebase you need to rebuild and retest your code... just because the code merged easily doesn't mean the result is correct.
If you're using a central repository to share an official development line, you can implement a pre-receive hook that detects these automatic ("stupid"/"useless") merge commits and rejects the push -- forcing the user to either rebase. Actually, you want the hook to look for the default merge commit message... so, if you really do want to keep the merge commit (sometimes that makes sense) you must at least write an intelligent commit message.
Here's an example hook. I stripped a bunch of extra stuff out so I didn't get to test it.