如何修复级联分支变基混乱
How to fix cascading branches rebasing mess
我们有一个工作流,其中 只有一个 团队成员在多个功能分支上工作。工作是这样的,每个下一个分支都依赖于他所做的前一个分支。默认分支是 develop
.
让我们说这个场景:
- 他创建
featureA
分支,执行工作,推送分支,并在 GitHub 上创建 PR
- 他创建了
featureB
分支(基于 featureA
分支),完成工作并 PRs
- 他创建了
featureC
分支,(基于 featureB
)完成了工作并对其进行了 PR
- 他创建了
featureD
分支,(基于 featureC
)完成了工作并对其进行了 PR
None 个 PR 尚未合并。
现在,项目经理介入并开始合并。以这种方式合并:
- 项目经理将
featureA
合并到 develop
开发者在他这边做:
git checkout develop
git fetch origin
git rebase origin/develop
git checkout featureB
git rebase origin/develop
git push origin featureB
此时我们得到错误:
machine /c/Work/ (featureB)
$ git push origin featureB
To https://github.com/x.git
! [rejected] featureB -> featureB (non-fast-forward)
error: failed to push some refs to 'https://github.com/x.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
为什么会这样?
我们认为将 featureB
变基到 origin/develop
(合并后现在包含 featureA
)将使 featureB
准备好推送。但显然我们看到了错误。
解释所发生情况的最简单方法是查看存储库的历史记录。这是您的历史记录在合并前的样子(精简版):
*--*--*--* [develop, origin/develop]
\
*--*--* [featureA, origin/featureA]
\
A--B--C [featureB, origin/featureB]
与post-合并:
*--*--*--*---------* [develop, origin/develop]
\ /
*--*--*
\
A--B--C [featureB, origin/featureB]
然后你将 featureB
重新设置为 develop
:
*--*--*--*---------* [develop, origin/develop]
\ / \
*--*--* A'--B'--C' [featureB]
\
A--B--C [origin/featureB]
此处,A'
、B'
和C'
包含与A
、B
和C
相同的更改,分别 但它们不是相同的提交 ,因为 A'
具有不同的父提交。
因此,在每次变基之后,您必须强制推送变基分支:
git push --force-with-lease origin featureB
(--force-with-lease
确保自上次获取以来没有推送新的提交。虽然这里可能并不严格需要,但最好养成在 --force
上使用它的习惯.)
正如我在上一张图中看到的那样,任何时候分支(例如featureB
)和它的远程跟踪分支(例如origin/featureB
)已经分叉,您必须强制推送。因此,只要重新设置已经推送到远程的分支,就需要这样做。
我们有一个工作流,其中 只有一个 团队成员在多个功能分支上工作。工作是这样的,每个下一个分支都依赖于他所做的前一个分支。默认分支是 develop
.
让我们说这个场景:
- 他创建
featureA
分支,执行工作,推送分支,并在 GitHub 上创建 PR
- 他创建了
featureB
分支(基于featureA
分支),完成工作并 PRs - 他创建了
featureC
分支,(基于featureB
)完成了工作并对其进行了 PR - 他创建了
featureD
分支,(基于featureC
)完成了工作并对其进行了 PR
None 个 PR 尚未合并。
现在,项目经理介入并开始合并。以这种方式合并:
- 项目经理将
featureA
合并到 develop 开发者在他这边做:
git checkout develop git fetch origin git rebase origin/develop git checkout featureB git rebase origin/develop git push origin featureB
此时我们得到错误:
machine /c/Work/ (featureB)
$ git push origin featureB
To https://github.com/x.git
! [rejected] featureB -> featureB (non-fast-forward)
error: failed to push some refs to 'https://github.com/x.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
为什么会这样?
我们认为将 featureB
变基到 origin/develop
(合并后现在包含 featureA
)将使 featureB
准备好推送。但显然我们看到了错误。
解释所发生情况的最简单方法是查看存储库的历史记录。这是您的历史记录在合并前的样子(精简版):
*--*--*--* [develop, origin/develop]
\
*--*--* [featureA, origin/featureA]
\
A--B--C [featureB, origin/featureB]
与post-合并:
*--*--*--*---------* [develop, origin/develop]
\ /
*--*--*
\
A--B--C [featureB, origin/featureB]
然后你将 featureB
重新设置为 develop
:
*--*--*--*---------* [develop, origin/develop]
\ / \
*--*--* A'--B'--C' [featureB]
\
A--B--C [origin/featureB]
此处,A'
、B'
和C'
包含与A
、B
和C
相同的更改,分别 但它们不是相同的提交 ,因为 A'
具有不同的父提交。
因此,在每次变基之后,您必须强制推送变基分支:
git push --force-with-lease origin featureB
(--force-with-lease
确保自上次获取以来没有推送新的提交。虽然这里可能并不严格需要,但最好养成在 --force
上使用它的习惯.)
正如我在上一张图中看到的那样,任何时候分支(例如featureB
)和它的远程跟踪分支(例如origin/featureB
)已经分叉,您必须强制推送。因此,只要重新设置已经推送到远程的分支,就需要这样做。