Git:定期合并/重新调整长期存在的错误修复分支以掌握
上下文
我们使用多个具有相同工作流程的 git 存储库,涉及两个分支,并且想知道如何最好地将提交从一个存储库“同步”到另一个分支。
简而言之,我们的 git 存储库包含:
- 长期存在的分支
- 两个分支:
- master(持续开发分支)
- 1.0(仅修复错误的分支,以维持稳定的版本)
- 两个分支都定期推送到公共存储库
- 有时,持续的开发和错误修复会影响同一文件中的同一行,因此合并/变基等时会发生冲突。
我们还有一些不太常见的情况:
- 不寻常的比率:错误修复的差异(在 1.0 分支上)比正在进行的开发(在 master 分支上)的差异大得多。
- 有时,来自 1.0 分支的提交会被精心挑选到主分支(稳定版本和开发都需要“紧急”错误修复)
我们可以如下说明这一点(提交 5'
是一个樱桃-从 1.0 分支中选择提交 5
):
<前><代码>-1--2-3--5'--7--(主) \ 4--5---6-- (1.0)
目标
我们经常需要确保 1.0 分支上的所有错误修复都可以在 master 分支上使用。
执行此操作时,我们的需求是:
- 1.0 分支不得更改(没有从 master 提交到 1.0 分支)
- Master 需要与 origin/master 保持兼容,以便我们可以推送到远程存储库。这基本上意味着避免重写 master 的历史记录(除非有一种我们不知道的神奇方法来推动它!)
- 我们不想丢失提交历史记录:我们需要能够查看来自 1.0 分支的提交是否具有已应用于master分支。
- 我们宁愿不必手动解决因之前的挑选而产生的冲突,我认为 git 应该能够自行解决这个问题(如手册页中所示)。
- 将来,我们将再次遇到类似的情况,需要以相同的方式解决它,但不想记住我们已经整理过一次的提交 4 和 6 使用什么解决方案。
因此,我们目标情况的说明是:
<前><代码>-1--2-3--5'--7--4'--6'--(主) \ 4--5---6-- (1.0)
我们尝试过
- 使用 1.0 分支的副本,并将其重新建立到 master 上:
- 似乎有效
- 但是如果我们将来再次执行相同的操作,我们必须审查新的提交和旧的提交
- 将 master 重新定位到 1.0 分支
- 在本地存储库中工作
- 但无法推送到远程,因为这会重写 origin/master
- 将 1.0 分支合并到 master
- 所有冲突解决最终都会在一次提交中完成,因此历史记录不会显示先前提交所需的实际修改
- 理想情况下,我们需要一个“git merge --interactive”,类似于“git rebase --interactive”:合并分支,但以交互方式选择要包含或不包含的提交
问题
在我们看来,这可能是 git 的一个非常典型的用例,或者对于任何在公共 git 存储库中维护和开发软件的人来说,无论如何。
你会怎么做呢?
谢谢!
Context
We use several git repositories with the same workflow, involving two branches, and are wondering how best to "synchronize" commits from one to the other.
Put simply, our git repositories contain:
- Long living branches
- Two branches:
- master (branch for ongoing development)
- 1.0 (branch for bugfixes only, to maintain a stable version)
- Both branches are both regularly pushed to a public repo
- Sometimes, ongoing development and bugfixes affect the same lines in the same files, so conflicts occur when merging/rebasing/etc.
We also have some less common conditions:
- Unusual ratio: diffs of bugfixes (on 1.0 branch) are much bigger than those from ongoing development (on master branch).
- Sometimes, commits from the 1.0 branch are cherry-picked to the master branch ("urgent" bugfixes needed both for stable releases and for development)
We could illustrate this as follows (commit 5'
is a cherry-pick of commit 5
from the 1.0 branch):
-1--2-3--5'--7-- (master) \ 4--5---6-- (1.0)
Aim
Every so often, we need to make sure all bugfixes on the 1.0 branch are available on the master branch.
When doing this, our needs are:
- The 1.0 branch must not be changed (no commits from master go to 1.0 branch)
- Master needs to remain compatible with origin/master, so that we can push to a remote repo. This basically means avoiding rewriting master's history (unless there's a magic way to push this we don't know about!)
- We don't want to lose the commit history: we need to be able to see whether a commit from the 1.0 branch has been applied to the master branch.
- We'd rather not have to manually resolve conflicts arising from previous cherry-picks, I think git should be able to work this out by itself (as indicated in the man pages).
- In the future, we'll reach a similar situation again, and need to resolve it the same way, but don't want to have to remember what resolutions to use for the commits 4 and 6 that we've already sorted out once.
So, an illustration of the situation we're aiming for is:
-1--2-3--5'--7--4'--6'-- (master) \ 4--5---6-- (1.0)
What we've tried
- Using a copy of the 1.0 branch, and rebasing it onto master:
- Seems to work
- But if we do the same operation again in the future, we have to review new commits AND old ones
- Rebasing master onto the 1.0 branch
- Works in a local repo
- But can't be pushed to remote, as this would be rewriting origin/master
- Merging 1.0 branch into master
- All conflict resolution ends up in ONE single commit, so the history doesn't show the actual modifications previous commits required
- Ideally, we would need a "git merge --interactive", similar to "git rebase --interactive": merge branches but interactively choose which commits to include or not, as we go
The question
It seems to us that this is probably a pretty typical use case for git, or for anyone maintaining and developing software in a public git repo, anyway.
How would you go about this?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所有的选择都有起有落,做出明智的决定在很大程度上取决于阅读你可能找到的所有内容。最大的问题是 git 并不是真正从头开始设计的,而是着眼于维护多个“长期”分支,您可能需要在一个分支上维护多年的更改。因此,当分支之间的代码库发生重大变化时,您最终可能会遇到合并问题。
如果您阅读了大部分工作流程文档,那么您反复阅读的最重要的内容之一就是:“将补丁应用于错误修复分支并向上合并它们”,而不是相反。
以下是我为 Net-SNMP 项目提出的解决方案。我写了一个 Git WorkFlow [in Net-SNMP] 页面,您可以在其中查看可能会读到,因为它包含圆圈和箭头,试图解释如何与大量错误修复分支一起工作。
然而,合并的缺点是历史变得非常非线性。这使得阅读“git log”,无论你尝试并抛出多少选项,都会有点令人困惑。
我们的一位开发人员善意地指出,我们需要强制使用“git merge --log”,这至少对历史记录有一点帮助。
祝你好运!
There are ups and downs to all the choices, and making an informed decision will rely heavily on reading everything you can possibly find. The biggest problem is that git wasn't really designed from the ground up with any eye toward maintaining multiple "long term" branches, where you may need to maintain changes on a branch for years. So it's likely you'll eventually run into merge issues when code bases between branches have significantly changed.
If you read most of the workflow documents, one of the biggest things your read repeatedly is: "apply patches to the bug fix branches and merge them upward", never ever the other way around.
Here's what I came up with as the solution I've come up with for our Net-SNMP project. I wrote up a Git WorkFlow [in Net-SNMP] page that you might read, as it contains circles and arrows trying to explain how things work with lots of bug-fix branches.
The downside to merging, though, is that the history becomes very non-linear. Which makes reading "git log", no matter how many options you try and throw at it, sort of confusing.
One of our developers kindly pointed out that we need to mandate the use of 'git merge --log', which at least helps the history a bit.
Good luck!