好吧,我认为这是一个简单的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
维护远程备份没有问题{{1}工作。到目前为止,我们还不错。
但是现在我想在master feature
提交之上重新F--G
,所以我git checkout feature
和git rebase master
。还好。现在我们有:
A--B--C------F--G (master)
\
D'--E' (feature)
问题:当我想要使用feature
备份新的重新定位git push origin feature
时,推送被拒绝,因为树已更改由于变基。这只能通过git push --force origin feature
来解决。
我讨厌使用--force
而不确定是否需要它。那么,我需要它吗? ,必然意味着下一个push
应该是--force
吗?
此功能分支不与任何其他开发人员共享,因此我没有问题事实上强制推送,我不会丢失任何数据,问题更具概念性。< / p>
答案 0 :(得分:548)
问题是git push
假设远程分支可以快速转发到本地分支,即本地和远程分支之间的所有区别在本地有一些新的提交,如下所示:
Z--X--R <- origin/some-branch (can be fast-forwarded to Y commit)
\
T--Y <- some-branch
当您执行git rebase
提交时,D和E将应用于新基础并创建新提交。这意味着在rebase之后你会有类似的东西:
A--B--C------F--G--D'--E' <- feature-branch
\
D--E <- origin/feature-branch
在那种情况下,远程分支无法快速转发到本地。虽然理论上本地分支可以合并到远程(显然你不需要它),但由于git push
只执行快进合并,它会引发错误。
而--force
选项所做的只是忽略远程分支的状态并将其设置为您正在推送的提交。因此,git push --force origin feature-branch
只会使用本地origin/feature-branch
覆盖feature-branch
。
在我看来,在master
上重新定位功能分支并强制将它们推回到远程存储库是可以的,只要你是唯一一个在该分支上工作的人。
答案 1 :(得分:320)
而不是使用-f或--force开发人员应该使用
--force-with-lease
为什么呢?因为它检查远程分支的更改,这绝对是个好主意。让我们想象一下,詹姆斯和丽莎正在研究同一个功能分支,丽莎已经推动了提交。詹姆斯现在重新调整他的当地分支,并在试图推动时被拒绝。当然,詹姆斯认为这是因为改变并使用--force并且会改写所有Lisa的变化。如果詹姆斯曾经使用过--force-with-lease,那么他会收到一个警告,告知其他人已做过提交。我不明白为什么有人会在推销一个rebase后使用--force而不是--force-with-lease。
答案 2 :(得分:40)
我会改为使用“checkout -b”,它更容易理解。
git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature
删除时,阻止推入包含不同SHA ID的现有分支。 在这种情况下,我只删除远程分支。
答案 3 :(得分:19)
对此的一个解决方案是执行msysGit的rebasing merge脚本执行的操作 - 在rebase之后,将feature
的旧主管与-s ours
合并。你最终得到了提交图:
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
(未经测试,但我认为这是正确的......)
答案 4 :(得分:15)
这个分支上只有一个开发人员,现在(在rebase之后)不与原点/特征内联,可能会也可能不会。
因此我建议使用以下序列:
git rebase master
git checkout -b feature_branch_2
git push origin feature_branch_2
是的,新的分支,这应该解决这个没有--force,我认为通常是一个主要的git缺点。
答案 5 :(得分:12)
其他人已经回答了你的问题。如果你重新分支一个分支,你将需要强制推动该分支。
Rebase和共享存储库通常不相处。这是重写历史。如果其他人正在使用该分支或从该分支分支,则rebase将非常不愉快。
一般来说,rebase适用于本地分支机构管理。远程分支管理最适合使用显式合并(--no-ff)。
我们还避免将master合并到功能分支中。相反,我们使用新的分支名称(例如添加版本后缀)来重新掌握。这避免了共享存储库中的重新定位问题。
答案 6 :(得分:11)
我避免强制推送的方法是创建一个新的分支并继续在新分支上工作,并在一些稳定之后,删除已经重新启动的旧分支:
答案 7 :(得分:8)
git merge master
分支上的feature
有什么问题?这将保留您的工作,同时将其与主线分支分开。
A--B--C------F--G
\ \
D--E------H
编辑啊抱歉没有看到你的问题陈述。执行rebase
时需要强制执行。修改历史记录的所有命令都需要--force
参数。这是一种可以防止您丢失工作的安全措施(旧的D
和E
会丢失)。
所以你执行了git rebase
使树看起来像(虽然部分隐藏为D
而E
不再在命名分支中):
A--B--C------F--G
\ \
D--E D'--E'
因此,当您尝试推送新的feature
分支(其中包含D'
和E'
)时,您将失去D
和E
。< / p>
答案 8 :(得分:4)
以下适用于我:
git push -f origin branch_name
并且它不会删除我的任何代码。
但是,如果您想避免这种情况,那么您可以执行以下操作:
git checkout master
git pull --rebase
git checkout -b new_branch_name
然后你可以挑选所有提交到新分支的提交。
git cherry-pick COMMIT ID
然后推动你的新分支。
答案 9 :(得分:2)
对我来说,遵循简单的步骤即可:
dnn
完成上述所有操作后,我们还可以通过以下命令删除myFeature分支:
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
答案 10 :(得分:1)
由于OP确实理解了这个问题,只需寻找更好的解决方案......
这作为一种做法怎么样?
拥有实际的功能开发分支(你永远不会改变和强制推送,所以你的同伴功能开发人员不讨厌你)。在这里,通过合并定期从main获取这些更改。 梅西耶历史,是的,但生活很简单,没有人会在他的工作中被中断。
拥有第二个功能开发分支,其中 一个 功能团队成员会定期将所有功能提交推送到实际上已被强制执行。所以几乎干净地基于最近的主提交。功能完成后,将该分支推送到主服务器顶部。
此方法可能已存在模式名称。
答案 11 :(得分:0)
在最新的master上获取master和rebase功能分支的新更改
git checkout master
git pull
git checkout feature
git pull --rebase origin master
git push origin feature
答案 12 :(得分:0)
我会做如下
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(具有旧的主机头)。如果您在解决冲突时犯了错误,这将使您以后进行比较。