git rebase和git push:非快进,为什么用?

我有一个分支机构应该可以提供给其他贡献者,并应该不断跟上主人。

不幸的是,每次我做'git rebase'然后尝试推,它导致'非快速前进'的消息和堕胎推。 唯一的办法就是使用–force。 这是否意味着我应该使用“混帐合并”而不是重新分配,如果我的分支上市,其他人正在努力呢?

有关git如何工作的一些注意事项(非技术):

当你重新绑定的时候,git会提交这个提交,然后在一个干净的历史logging上“重新提交”它们。 这是为了防止历史显示:

Description: tree -> mywork -> merge -> mywork -> merge -> mywork -> merge Commit SHA1: aaaa -> bbbb -> cccc -> dddd -> eeee -> ffff -> gggg 

重build后,它可能看起来像这样(或类似):

 Description: tree -> rebase Commit SHA1: aaaa -> hhhh 

问题是你试图推出的新提交并不是你所推荐的分支提交的后代

现在,你知道同样的信息是在提交,但是git不仅仅是覆盖那些提交(上面例子中的bbbb-gggg)。


共享回购模式

如果你正在使用共享库,那么这样的事情可能会变得混乱。 让我解释一下为什么。 说另一个开发人员拉下了分支,他们已经提交aaaa – > gggg在他们的分支。 然后他们做了一个承诺iiii

与此同时,你重新启动,并推动,使树看起来像这样:

 Description: tree -> rebase Commit SHA1: aaaa -> hhhh 

当其他开发者试图推动时,他得到一个“非快速转发”的消息。 当他合并的时候,两个历史都会被联系在一起,最终你会陷入一片混乱

像这样(杂乱):

 Description: tree -> rebase -> mywork -> merge -> mywork -> merge -> mywork -> merge -> devwork -> merge Commit SHA1: aaaa -> hhhh -> bbbb -> cccc -> dddd -> eeee -> ffff -> gggg -> iiii -> jjjj 

换句话说,如果其他人在拉和推,最好还是坚持使用git merge,或者是在rebase之前避免push(直到你的工作重新开始)。


公开可见的存储库模型

也许你正在使用一个不同的(更有意思的)模型,你只希望人们能够从你的回购中获得回报。 在这种情况下,git push –force并不算太坏,因为这样他们可以处理它。 他们可以根据你的变化重新设置他们的变化 ,然后给他们补丁。 它可以防止你的回购搞砸了。

但是,对你来说可能有更好的办法。 git push –mirror

http://www.kernel.org/pub/software/scm/git/docs/git-push.html

将$ GIT_DIR / refs /(包括但不限于refs / heads /,refs / remotes /和refs / tags /)的所有ref映射到远程存储库,而不是将每个ref命名为push。 新创build的本地参考将被推送到远端,本地更新的参考将在远端强制更新,删除的参考将从远端移除。 如果设置了configuration选项remote..mirror,则这是默认值。


关于git的一个很棒的事情是它非常灵活,允许有许多不同的工作stream程。 但是真正的优势在于它是一个分布式模型,所以我相信通过这种方式可以获得最大的投资回报。

不,rebase与公共仓库是完全合法的,甚至可以保持历史的stream畅性。 请记住,您不能使用rebase来重写远程发布的提交的历史logging。 也就是说,rebase只能应用于你自己的,本地的,你从未发布的提交。 你可以使用rebase把你的提交放在它们之上,然后在那里调整它们。 您可能会收到这样的消息的另一个原因是,您推送的分支已更新,您需要同步 – 在提取的内容之上提取并重新提交您的提交。