【问题标题】:git rebase and git push: non-fast forward, why use?git rebase 和 git push:非快进,为什么要使用?
【发布时间】:2010-10-08 06:39:45
【问题描述】:

我有一个分支,它应该可供其他贡献者使用,并且应该不断与主人保持同步。

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

【问题讨论】:

    标签: git merge rebase


    【解决方案1】:

    关于 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,或者避免推直到变基之后(并且只变基你的工作)。


    公开可见的存储库模型

    也许您使用的是不同的(更 gittish)模型,您只是希望人们能够从您的存储库中提取。在这种情况下, git push --force 并不算太糟糕,因为这样他们就可以跟上它。在将补丁提供给您之前,他们可以重新调整他们的更改以在您的更改之上。它可以防止你的 repo 搞砸了。

    但是,您可能有更好的方法。 git push --mirror

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

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


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

    【讨论】:

    • 呃,实际上,合并会创建合并提交,这缺乏必要的澄清。相反,git fetch, git rebase origin/master 很好,解决您与主(集中式)分支的所有本地冲突,然后推送仅向前推进的纯提交。 git pull --rebase 有类似的工作流程。这是一个强大的选项,但您必须小心使用它,因为重新设置错误的基础可能会重写已经在 origin/master 中的提交。例如。除非它们首先基于当前的原点/主分支,否则不要重新设置其他分支的基础。
    • 同意,在执行 git pull 时应避免合并提交。但是,我确实认为在有意将功能分支合并到 master 时保留它们是好的。
    • 我喜欢关于为什么会出现问题的解释,即推送一个重新定位的分支。但我不确定 --mirror 实现了什么。阅读描述 - “指定 所有 refs 将被镜像” - 困扰着我。我不希望 all refs 镜像,只有一个分支。 :) 命名一个分支只会反映那个分支吗?从 git 文档中我不清楚。
    【解决方案2】:

    不,rebase 对于公共存储库是完全合法的,甚至可能需要保持历史流畅。请记住,您不能使用 rebase 来重写远程发布提交的历史记录。也就是说,rebase 只能应用于您自己的、本地的、您从未发布过的提交。您在获取时使用 rebase 将您的提交放在它们之上,然后也许在那里调整它们。您可能会收到此类消息的另一个原因是您推送的分支已更新并且您需要同步——在您获取的内容之上获取并重新设置您的提交。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-20
      • 2018-09-30
      • 1970-01-01
      • 2012-02-15
      • 2012-08-28
      • 1970-01-01
      • 2011-09-11
      • 2015-03-21
      相关资源
      最近更新 更多