功能分支变基后 Git 推送被拒绝

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8939977/
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 12:47:12  来源:igfitidea点击:

Git push rejected after feature branch rebase

git

提问by Yuval Adam

OK, I thought this was a simple git scenario, what am I missing?

好吧,我以为这是一个简单的 git 场景,我错过了什么?

I have a masterbranch and a featurebranch. I do some work on master, some on feature, and then some more on master. I end up with something like this (lexicographic order implies the order of commits):

我有一个master分支和一个feature分支。我做了一些工作master,一些工作,feature然后更多master。我最终得到了这样的结果(字典顺序意味着提交的顺序):

A--B--C------F--G  (master)
       \    
        D--E  (feature)

I have no problem to git push origin masterto keep the remote masterupdated, nor with git push origin feature(when on feature) to maintain a remote backup for my featurework. Up until now, we're good.

我没有问题可以git push origin master保持远程master更新,也没有问题git push origin feature(打开时feature)为我的feature工作维护远程备份。到目前为止,我们很好。

But now I want to rebase featureon top of the F--Gcommits on master, so I git checkout featureand git rebase master. Still good. Now we have:

但是现在我想在 masterfeature上的F--G提交基础上重新构建,所以我git checkout featuregit rebase master. 还好。现在我们有:

A--B--C------F--G  (master)
                 \
                  D'--E'  (feature)

Problem:the moment I want to backup the new rebased featurebranched with git push origin feature, the push is rejectedsince the tree has changed due to the rebasing. This can only be solved with git push --force origin feature.

问题:当我想备份新的 rebasefeature分支时git push origin feature推送被拒绝,因为树由于rebase发生了变化。这只能用 来解决git push --force origin feature

I hate using --forcewithout being sure I need it. So, do I need it? Does the rebasing necessarilyimply that the next pushshould be --forceful?

我讨厌--force在不确定我需要它的情况下使用它。那么,我需要吗?变基一定意味着下一个push应该是--force完整的吗?

This feature branch is not shared with any other devs, so I have no problem de factowith the force push, I'm not going to lose any data, the question is more conceptual.

此功能分支不与任何其他开发人员共享,因此我实际上对强制推送没有问题,我不会丢失任何数据,问题更具概念性。

采纳答案by KL-7

The problem is that git pushassumes that remote branch can be fast-forwarded to your local branch, that is that all the difference between local and remote branches is in local having some new commits at the end like that:

问题是git push假设远程分支可以快速转发到您的本地分支,也就是说,本地分支和远程分支之间的所有区别都在本地,最后有一些新的提交,如下所示:

Z--X--R         <- origin/some-branch (can be fast-forwarded to Y commit)
       \        
        T--Y    <- some-branch

When you perform git rebasecommits D and E are applied to new base and new commits are created. That means after rebase you have something like that:

当您执行git rebase提交时,D 和 E 将应用于新的基础并创建新的提交。这意味着在 rebase 之后你有类似的东西:

A--B--C------F--G--D'--E'   <- feature-branch
       \  
        D--E                <- origin/feature-branch

In that situation remote branch can't be fast-forwarded to local. Though, theoretically local branch can be merged into remote (obviously you don't need it in that case), but as git pushperforms only fast-forward merges it throws and error.

在这种情况下,远程分支无法快进到本地。虽然,理论上本地分支可以合并到远程分支(显然在这种情况下你不需要它),但是当git push只执行快进合并时,它会抛出和错误。

And what --forceoption does is just ignoring state of remote branch and setting it to the commit you're pushing into it. So git push --force origin feature-branchsimply overrides origin/feature-branchwith local feature-branch.

--force选项所做的只是忽略远程分支的状态并将其设置为您正在推送的提交。所以git push --force origin feature-branch简单地origin/feature-branch用 local覆盖feature-branch

In my opinion, rebasing feature branches on masterand force-pushing them back to remote repository is OK as long as you're the only one who works on that branch.

在我看来,master只要您是唯一在该分支上工作的人,就可以将功能分支重新设置为基础并将它们强制推送回远程存储库。

回答by Hardev

Instead of using -f or --force developers should use

而不是使用 -f 或 --force 开发人员应该使用

--force-with-lease

Why? Because it checks the remote branch for changes which is absolutely a good idea. Let's imagine that James and Lisa are working on the same feature branch and Lisa has pushed a commit. James now rebases his local branch and is rejected when trying to push. Of course James thinks this is due to rebase and uses --force and would rewrite all Lisa's changes. If James had used --force-with-lease he would have received a warning that there are commits done by someone else. I don't see why anyone would use --force instead of --force-with-lease when pushing after a rebase.

为什么?因为它会检查远程分支的更改,这绝对是一个好主意。让我们假设 James 和 Lisa 在同一个功能分支上工作,而 Lisa 推送了一个提交。James 现在重新设置他的本地分支,并在尝试推送时被拒绝。当然,James 认为这是由于 rebase 和使用 --force 并且会重写 Lisa 的所有更改。如果 James 使用了 --force-with-lease,他会收到一个警告,指出有其他人完成了提交。我不明白为什么有人会在 rebase 后推送时使用 --force 而不是 --force-with-lease。

回答by Eddy Hernandez

I would use instead "checkout -b" and it is easier to understand.

我会改用“checkout -b”,这样更容易理解。

git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature

when you delete you prevent to push in an exiting branch that contains different SHA ID. I am deleting only the remote branch in this case.

当您删除时,您会阻止推送包含不同 SHA ID 的现有分支。在这种情况下,我只删除远程分支。

回答by Mark Longair

One solution to this is to do what msysGit's rebasing mergescript does - after the rebase, merge in the old head of featurewith -s ours. You end up with the commit graph:

对此的一种解决方案是执行 msysGit 的rebase合并脚本所做的操作 - 在 rebase 之后,在featurewith的旧头中合并-s ours。你最终得到了提交图:

A--B--C------F--G (master)
       \         \
        \         D'--E' (feature)
         \           /
          \       --
           \    /
            D--E (old-feature)

... and your push of featurewill be a fast-forward.

......你的推动feature将是一个快进。

In other words, you can do:

换句话说,你可以这样做:

git checkout feature
git branch old-feature
git rebase master
git merge -s ours old-feature
git push origin feature

(Not tested, but I think that's right...)

(未测试,但我认为这是正确的...)

回答by JAR.JAR.beans

It may or may not be the case that there is only one developer on this branch, that is now (after the rebase) not inline with the origin/feature.

可能是也可能不是这个分支上只有一个开发人员,即现在(在 rebase 之后)不与原点/功能内联。

As such I would suggest to use the following sequence:

因此,我建议使用以下顺序:

git rebase master
git checkout -b feature_branch_2
git push origin feature_branch_2

Yeah, new branch, this should solve this without a --force, which I think generally is a major git drawback.

是的,新分支,这应该可以在没有 --force 的情况下解决这个问题,我认为这通常是 git 的主要缺点。

回答by Nabi

My way of avoiding the force push is to create a new branch and continuing work on that new branch and after some stability, remove the old branch that was rebased:

我避免强制推送的方法是创建一个新分支并继续在该新分支上工作,经过一定程度的稳定后,删除重新定位的旧分支:

  • Rebasing the checked out branch locally
  • Branching from the rebased branch to a new branch
  • Pushing that branch as a new branch to remote. and deleting the old branch on remote
  • 在本地重新定位签出的分支
  • 从 rebase 分支到新分支
  • 将该分支作为新分支推送到远程。并删除远程上的旧分支

回答by Bill Door

Other's have answered your question. If you rebase a branch you will need to force to push that branch.

别人已经回答了你的问题。如果您重新设置分支,则需要强制推送该分支。

Rebase and a shared repository generally do not get along. This is rewriting history. If others are using that branch or have branched from that branch then rebase will be quite unpleasant.

Rebase 和共享存储库通常不会相处。这是在改写历史。如果其他人正在使用该分支或从该分支分支,那么 rebase 将非常令人不快。

In general, rebase works well for local branch management. Remote branch management works best with explicit merges (--no-ff).

一般来说,rebase 很适合本地分支管理。远程分支管理最适合显式合并 (--no-ff)。

We also avoid merging master into a feature branch. Instead we rebase to master but with a new branch name (e.g adding a version suffix). This avoids the problem of rebasing in the shared repository.

我们还避免将 master 合并到一个特性分支中。相反,我们使用新的分支名称(例如添加版本后缀)变基为 master。这避免了在共享存储库中变基的问题。

回答by Bouke

What is wrong with a git merge masteron the featurebranch? This will preserve the work you had, while keeping it separate from the mainline branch.

分支git merge master上的a 有什么问题feature?这将保留您的工作,同时将其与主线分支分开。

A--B--C------F--G
       \         \
        D--E------H

Edit:Ah sorry did not read your problem statement. You will need force as you performed a rebase. All commands that modify the history will need the --forceargument. This is a failsafe to prevent you from losing work (the old Dand Ewould be lost).

编辑:啊抱歉没有阅读你的问题陈述。执行rebase. 所有修改历史的命令都需要--force参数。这是一种可靠的,以防止丢失工作(老的DE将丢失)。

So you performed a git rebasewhich made the tree look like (although partially hidden as Dand Eare no longer in a named branch):

因此,您执行了一个git rebase使树看起来像的操作(尽管部分隐藏D并且E不再位于命名分支中):

A--B--C------F--G
       \         \
        D--E      D'--E'

So, when trying to push your new featurebranch (with D'and E'in it), you would lose Dand E.

因此,当尝试推送您的新feature分支(包含D'E'在其中)时,您将丢失DE

回答by Neeraj Khede

For me following easy steps works:

对我来说,以下简单的步骤有效:

1. git checkout myFeature
2. git rebase master
3. git push --force-with-lease
4. git branch -f master HEAD
5. git checkout master
6. git pull

After doing all above, we can delete myFeature branch as well by following command:

完成上述所有操作后,我们也可以通过以下命令删除 myFeature 分支:

git push origin --delete myFeature

回答by Sohair Ahmad

The following works for me:

以下对我有用:

git push -f origin branch_name

git push -f origin branch_name

and it does not remove any of my code.

它不会删除我的任何代码。

But, if you want to avoid this then you can do the following:

但是,如果您想避免这种情况,则可以执行以下操作:

git checkout master
git pull --rebase
git checkout -b new_branch_name

then you can cherry-pick all your commits to the new branch. git cherry-pick COMMIT IDand then push your new branch.

然后你可以挑选你对新分支的所有提交。 git cherry-pick COMMIT ID然后推送你的新分支。