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


68

我有一个分支,该分支应该可供其他贡献者使用,并且应该经常与主服务器保持同步。

不幸的是,每次我执行“ git rebase”然后尝试进行推送时,都会导致“非快进”消息并中止推送。推送到此处的唯一方法是使用--force。这是否意味着如果我的分支公开并且其他人正在研究它,我应该使用“ git merge”而不是重新定基?

Answers:


100

关于git如何工作的一些说明(非技术性):

当您重新设置基准时,git会采用有问题的提交,并在干净的历史记录之上“重新提交”它们。这是为了防止历史记录显示:

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

重新设置基准之后,它可能看起来像这样(或类似内容):

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或AVOID PUSHING,直到重新设置基准(并且仅重新设置工作基准)为止。


公开可见的存储库模型

也许您使用的是其他(更灵巧)的模型,您只是希望人们能够从您的回购中撤资。在这种情况下,git push --force不太糟糕,因为这样他们就可以跟上它的步伐。他们可以在将更改提供给您之前将其更改重新置于您的更改之上。它可以防止您的仓库陷入困境。

但是,可能有更好的方法适合您。 git push-镜像

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

指定将$ GIT_DIR / refs /(包括但不限于refs / heads /,refs / remotes /和refs / tags /)下的所有ref镜像到远程存储库,而不是命名要推送的ref。新创建的本地裁判将被推送到远程端,本地更新的裁判将在远程端强制更新,而已删除的裁判将从远程端删除。如果设置了配置选项remote..mirror,则为默认设置。


git的一大优点是它非常灵活,并允许许多不同类型的工作流。但是它的真正优势在于它是一个分布式模型,因此,我相信通过这种方式可以获得最大的投资回报。


7
实际上,Err合并会创建合并提交,但缺乏必要的澄清。相反,它很重要,它可以git fetch, git rebase origin/master解决您与master(集中式)分支的所有本地冲突,然后推送仅向前执行的纯提交。 git pull --rebase具有类似的工作流程。这是一个功能强大的选项,但是您必须谨慎使用它,因为基于错误的内容进行重新定位可能会重写源/主服务器中已经存在的提交。例如,除非其他分支首先基于当前的原产地/原产地,否则不要对其进行重新分类。
卡扎伊2010年

同意,执行git pull时应避免合并提交。但是,我确实认为有意将功能分支合并到master中时可以保留它们。
ndbroadbent 2012年

3
我喜欢解释为什么存在问题的原因,它推了一个经过重新设计的分支。但是我不确定--mirror能实现什么。阅读说明-“指定所有引用都将被镜像”-使我感到困扰。我不希望所有裁判都被镜像,只是一个分支。:)命名分支只会反映那个分支吗?从git文档对我来说还不清楚。
约翰·C

2

不可以,在公共存储库中进行重新存储是完全合法的,甚至可能希望保持历史记录流畅。请记住,您一定不能使用rebase重写远程发布的提交的历史记录。也就是说,rebase只能应用于您从未发布过的本地提交。您可以使用rebase在提交时将提交放置在提交之上,然后在那儿进行调整。您可能会收到这样的消息的另一个原因是,您推送的分支已更新,您需要进行同步-在获取的内容之上获取并重新构建提交。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.