在功能分支重新基址后拒绝Git推送

dgiusagp  于 2022-09-21  发布在  Git
关注(0)|答案(14)|浏览(237)

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

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

A--B--C------F--G  (master)

        D--E  (feature)

我可以使用git push origin master来保持远程master的更新,也可以使用git push origin feature(如果在feature上)来为我的feature工作维护远程备份。到目前为止,我们都很好。

但现在我想在主服务器上F--G提交的基础上重新设置feature的基数,因此我选择git checkout featuregit rebase master。还是很好。现在我们有:

A--B--C------F--G  (master)

                  D'--E'  (feature)

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

我讨厌在不确定自己是否需要的情况下使用--force。那么,我需要它吗?重新设定基准是否“必然”意味着下一个push应该是e1d19d1ful?

这个功能分支不会与任何其他开发人员共享,所以我对强制推送没有问题,我不会丢失任何数据,问题更多的是概念性的。

xoefb8l8

xoefb8l81#

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

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

        T--Y    <- some-branch

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

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

        D--E                <- origin/feature-branch

在这种情况下,远程分支不能快进到本地。虽然从理论上讲,本地分支可以合并到远程(显然在这种情况下您不需要它),但由于git push只执行快进合并,因此会抛出错误。

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

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

9rnv2umw

9rnv2umw2#

与使用-f--force相比,开发人员应该使用

--force-with-lease

为什么?因为它会检查远程分支的更改,这绝对是个好主意。让我们假设James和Lisa正在开发相同的功能分支,而Lisa已经推送了一个提交。詹姆斯现在重新部署了他的当地分支机构,当试图推进时被拒绝。当然,詹姆斯认为这是因为重新设置了基址,并使用了--force,并会重写Lisa的所有更改。如果James使用了--force-with-lease,他会收到一个警告,告诉他有其他人执行了提交。我不明白为什么有人会在改版后使用--force而不是--force-with-lease

siotufzp

siotufzp3#

我会使用“check out-b”,这样更容易理解。

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

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

h7wcgrx3

h7wcgrx34#

一种解决方案是像msysGit的rebasing merge脚本所做的那样-在重新基址之后,将feature的旧头与e1d1e合并。您最终得到了提交图:

A--B--C------F--G (master)

                 D'--E' (feature)
                    /
                 --
               /
            D--E (old-feature)

..。而你的feature推送将是快进。

换句话说,您可以执行以下操作:

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

(没有经过测试,但我认为这是正确的…)

2ledvvac

2ledvvac5#

其他人已经回答了你的问题。如果你改变一个分支的基数,你将需要强制推入该分支。

Rebase和共享存储库通常相处不好。这是在改写历史。如果其他人正在使用该分支或从该分支分支,那么重新定基将是非常不愉快的。

总体而言,Rebase适用于本地分支机构管理。远程分支管理最适合使用显式合并(--no-ff)。

我们还避免将主文件合并到功能分支中。相反,我们使用新的分支名称(例如,添加一个版本后缀)重新设置为主版本。这避免了在共享存储库中重新建立基础的问题。

vxqlmq5t

vxqlmq5t6#

这个分支上可能只有一个开发人员,也可能不是。

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

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

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

tzxcd3kk

tzxcd3kk7#

我避免强制推送的方法是创建一个新分支,并继续在该新分支上工作,在一些稳定之后,删除重新建立基础的旧分支:

  • 在本地重新确定已 checkout 分支机构的基础
  • 从重新定位的分支机构分支到新的分支机构
  • 将该分支作为新分支推送到远程。并删除远程上的旧分支
aiqt4smr

aiqt4smr8#

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

A--B--C------F--G

        D--E------H

**编辑:**我很抱歉没有阅读您的问题声明。当您执行rebase时,您需要用力。所有修改历史记录的命令都需要--force参数。这是一种故障保护措施,可以防止您丢失工作(旧的DE会丢失)。

因此,您执行了git rebase,使树看起来像(尽管部分隐藏,因为DE不再位于命名的分支中):

A--B--C------F--G

        D--E      D'--E'

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

bnl4lu3b

bnl4lu3b9#

对我来说,以下简单的步骤很管用:

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

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

git push origin --delete myFeature
kq0g1dla

kq0g1dla10#

以下内容对我来说很管用:

git push -f origin branch_name

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

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

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

然后你可以挑选你所有的承诺给新的分支机构。git cherry-pick COMMIT ID,然后按下您的新分支。

hfwmuf9z

hfwmuf9z11#

获取主文件的新更改,并在最新的主文件上重新设置要素分支的基础

git checkout master
git pull
git checkout feature
git pull --rebase origin master
git push origin feature
yqyhoc1h

yqyhoc1h12#

因为行动组确实理解这个问题,只是寻找一个更好的解决方案。

这个练习怎么样?

  • 有实际的功能开发分支(这里你永远不会改基和强制推送,这样你的功能开发同行就不会恨你了)。在这里,通过合并定期从Main获取这些更改。更糟糕的历史,是的,但生活很容易,没有人会在他的工作中受到干扰。
  • 有第二个功能开发分支,其中*一个**功能团队成员定期推送所有功能承诺,确实是重新建立的,确实是强制的。几乎干净利落地基于最近的主提交。功能完成后,将该分支推到MASTER上。

此方法可能已有模式名称。

biswetbf

biswetbf13#

我会做如下所示

rebase feature
git checkout -b feature2 origin/feature
git push -u origin feature2:feature2
Delete the old remote branch feature
git push -u origin feature:feature

现在遥控器将具有功能(基于最新的主控器)和功能2(具有旧的主控头)。这将允许你在以后比较你在解决冲突时是否犯了错误。

tjvv9vkg

tjvv9vkg14#

要在REBASE之后将更改推送到分支,您需要在Git上的git推送命令中使用-f或--force标志强制推送提交。

可以这样做,

在GIT重新基址后,推送提交到分支

git push origin -f FEATURE_BRANCH_NAME

这是因为远程分支中的某些内容已更改,并且远程分支和本地分支的提交历史记录都不同。

如果您试图推送本地更改,GIT将拒绝它,并显示一条消息,如您当前分支的尖端在其远程分支之后。对本地分支进行强制推送可以解决问题。

别害怕。如果您是唯一一个在同一分支上工作的人,这是一个很好的方法。👍🏽

相关问题