提问人:Louis Strous 提问时间:1/17/2018 最后编辑:Louis Strous 更新时间:11/29/2019 访问量:163
使用 git,如何将主(上游)分支合并到主题分支中,但看到差异就像将主题分支合并到主分支中一样?
Using git, how do I merge the main (upstream) branch into a topic branch but see the differences as if I merged the topic branch into the main branch?
问:
使用 git,如何将主(上游)分支合并到主题分支中,但看到差异就像将主题分支合并到主分支中一样?
我们的习惯是,当一个主题分支准备好时,将合并到主分支(使用 git)作为一个两阶段的过程:
- 将 main 分支合并到 topic 分支中。推送主题分支,这将触发外部测试系统上的测试,以检查应用程序功能是否仍按预期工作。
- 将主题分支合并到主分支中。按下主分支,这将再次触发测试。
这样做的好处是,如果合并后的版本有任何问题,那么它们很可能已经出现在主题分支中,在那里它们还没有打扰其他开发人员。
缺点是,当将 main 分支合并到 topic 分支中时,报告的差异是其他开发人员引入 main 分支的差异。它们可能非常多,而我没有参与制作它们中的任何一个,所以我很难验证合并是否没有犯任何错误。
相反,如果我立即将主题分支合并到主分支中,而不先将主分支合并到主题分支中,那么报告的差异只是我为主题分支引入的差异。它们的数量较少,而且我非常熟悉它们,因此我更容易验证合并是否犯了任何错误,但是我们没有首先在主题分支的上下文中测试组合的优势。
在推送之前,我无法在本地运行测试,因此无法将主题分支合并到主分支中,然后进行测试,解决任何问题,然后才推送主分支。
假设合并进展顺利,对于最终代码来说,我是将主题分支合并到主分支还是将主分支合并到主题分支中并不重要:在这两种情况下,我最终都会得到相同的代码,但与不同的分支相关联。
我想要的是将合并的代码放在主题分支中,但要看到差异,就好像我将主题分支合并到主分支中一样。最方便的方法是什么?
笨拙的方法是拥有存储库的两个本地副本,其中一个检出主分支,另一个检出主题分支。在第一个存储库副本中将主题分支合并到主分支中(仅请参阅我自己的差异 - 优秀!),然后将源代码而不是 .git 目录复制到另一个存储库副本中,并提交到主题分支中。这很麻烦,而且浪费磁盘空间。
我还尝试将主题分支合并到主分支中(但不是推送!),然后将主题分支硬重置到主分支中的合并提交上,但这只是移动了主题分支标记,失去了与主题分支中先前提交的连接。
编辑:在评论的建议下,我将自己的解决方案从这里移到了答案,2019-11-29。
答:
第一个部分解决方案,添加于 2018-01-19
我已经找到了解决我问题的部分方法。当我正在将主分支合并到主题分支中时,那么
git diff --stat MERGE_HEAD...
(注意末尾的三个点)显示自最近与主分支的共同祖先以来,主题分支中的文件发生了多少行更改。如果我将主题分支合并到主分支中,这些文件将被报告为已更改;这些是我更改的文件。
在将主分支合并到主题分支中时,我可以忽略 git diff 中不在该列表中的所有文件。那些要忽略的文件没有被我更改,所以我不需要仔细检查它们是否存在 git 无法检测到的合并问题。
第二部分解决方案,添加于 2018-01-23
此解决方案基于 Steve 在此问题下方添加的评论,并进行了一些补充。
- 在 master 上创建一个新的临时分支,并将主题分支合并到其中。将提交消息更改为“将主分支合并到主题分支”之类的内容,类似于将主分支直接合并到主题分支中的情况。(默认提交消息提到了临时分支,我们很快就会删除它,因此如果提交消息引用它会令人困惑。此外,有效的合并方向将与默认提交消息所说的相反。
- 切换到主题分支并将临时分支合并(快进)到此分支中。删除临时分支。然后推送主题分支以触发测试。
- 将现在测试的主题分支合并(可能与 --no-ff?)合并到 master 中。
第三部分解决方案
我的一位同事提出了第三种方法来减轻痛苦:使用工作树来获得主分支的廉价第二个副本,而不必再次克隆整个存储库。假设您位于主存储库目录“repo”中,并选中了主题分支:
# create worktree and check out main-branch in it:
git worktree add ../repo-worktree main-branch
cd ../repo-worktree
git merge topic-branch
# (resolve any merge conflicts)
# copy changed files to the main repository:
cp <changed-files> ../repo
cd ../repo # go to main repository
git add -u # stage copied files (no new ones!)
git commit -m "merged main branch into topic branch"
# when you don't need the worktree anymore, then
rm -rf ../repo-worktree # removes worktree
git worktree prune # removes obsolete worktree administrative files
评论
git diff -R <your options/commit-ish>
git diff -R <commit>
git diff <commit>
--no-ff