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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/559917/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:10:42  来源:igfitidea点击:

git rebase and git push: non-fast forward, why use?

gitmergerebase

提问by snitko

I have a branch that should be available to other contributors and that should constantly stay up to date with the master.

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

Unfortunately, every time I do 'git rebase' and then try to push, it results in 'non-fast forward' message and abortion of pushing. The only way to push here is to use --force. Does that mean I should use 'git merge' instead of rebasing if my branch went public and others are working on it?

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

回答by gahooa

A few notes on how git works (non technical):

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

When you rebase, git takes the commits in question, and "recommits" them on top of a clean history. This is to prevent the history from showing:

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

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

After a rebase, it may look like this (or similar):

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

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

The issue is that the new commit you are attempting to push out there is NOT a descendantof the commit on the tip of the branch you are pushing to.

问题是您尝试推送的新提交不是您推送到的分支尖端的提交的后代

Now, you know that the same info is in the commits, but git is being responsible by not just overwriting those commits out there (bbbb-gggg in the example above).

现在,您知道提交中包含相同的信息,但是 git 负责的不仅仅是覆盖那些提交(上面示例中的 bbbb-gggg)。



Shared Repo Model

共享回购模型

If you are using a shared repository, then things like this can get mighty confusing. Let me explain why. Say another developer pulled down the branch, and they have commits aaaa -> ggggin their branch. Then they make a commit iiii

如果您使用的是共享存储库,那么像这样的事情会变得非常混乱。让我解释一下原因。假设另一个开发人员删除了分支,并且他们在他们的分支中提交了aaaa -> gggg。然后他们进行提交iiii

In the meanwhile, you rebased and forced a push, causing the tree to look like this:

同时,您重新定位并强制推送,导致树看起来像这样:

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

When the other developer tries to push, he gets a "non-fast forward" message. When he does a merge, then both histories are RELINKED together, and you end up with a mess

当其他开发人员尝试推送时,他会收到“非快进”消息。当他进行合并时,两个历史记录都重新链接在一起,你最终会变得一团糟

Something like this (messy):

像这样(凌乱):

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

IN other words, if others are pulling AND pushing, it's better that you stick with git merge, or AVOID PUSHINGuntil after the rebase (and only rebase your work).

换句话说,如果其他人在拉动和推动,最好坚持使用 git merge,或者在 rebase 之前避免 PUSHING(并且只对你的工作进行 rebase)。



Publicly Visible Repository Model

公开可见的存储库模型

Perhaps you are using a different (more gittish) model where you just want people to be able to pull from your repo. In this case, git push --force isn't too bad, because then they can deal with keeping up with it. They can rebase their changesto be on top of your changes before giving their patches to you. It prevents your repo from getting all messed up.

也许您正在使用不同的(更笨拙的)模型,您只是希望人们能够从您的仓库中提取。在这种情况下, git push --force 还不错,因为这样他们就可以跟上它。在向您提供补丁之前,他们可以将他们的更改重新设置为基于您的更改。它可以防止你的回购变得一团糟。

However, there may be a better way for you. git push --mirror

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

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

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

Instead of naming each ref to push, specifies that all refs under $GIT_DIR/refs/ (which includes but is not limited to refs/heads/, refs/remotes/, and refs/tags/) be mirrored to the remote repository. Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end. This is the default if the configuration option remote..mirror is set.

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



One of the great things about gitis that it is very flexible and allows for many different kind of workflows. But it's real strength lies in the fact that it is a distributed model, so I believe that the most ROI can be reaped by using it that way.

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

回答by Val

No, rebase is perfectly legal with public repositories and may even be desirable to keep the history fluent. Just keep in mind that you must not use rebase to rewrite the history of remotely published commits. That is, rebase can only be applied to your own, local, commits that you have never published. You use rebase to place your commits on top of them when fetch and then, perhaps, adjust them there. Another reason that you may receive such message is that the branch you pushing was updated and you need to synchronize -- fetch and rebase your commits on top of what you have fetched.

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