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

时间:2009-02-18 05:09:23

标签: git merge rebase

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

不幸的是,每当我做'git rebase'然后尝试推动时,它会导致'非快速前进'消息和推动堕胎。推动这里的唯一方法是使用--force。这是否意味着如果我的分支公开并且其他人正在研究它,我应该使用'git merge'而不是rebasing?

2 个答案:

答案 0 :(得分:100)

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

当你进行rebase时,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,或者避免推动直到rebase之后(并且只会改变你的工作)。


公开可见的存储库模型

也许你正在使用一种不同的(更加轻微的)模型,你只希望人们能够从你的回购中获取。在这种情况下,git push --force并不是太糟糕,因为那时他们可以处理跟上它的问题。在向您提供补丁之前,他们可以将他们的更改更改为您的更改。它可以防止你的repo搞砸了。

然而,可能有更好的方法。 git push --mirror

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

  

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


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

答案 1 :(得分:2)

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