首页 > 解决方案 > 如何查看一个 git 分支在贡献分支的整个生命周期内对另一个分支的净贡献

问题描述

我们有一个中央 MASTER 分支和多个单独的任务分支,我们的生命周期如下所示:

  1. 从 MASTER 创建单个任务分支 A
  2. 做A并完成任务
  3. 将 A 合并回 MASTER
  4. ...如果测试确定了 A 中需要的其他更改,则将最新的 MASTER 合并到 A 中(以使 A 恢复与任务 B、C 的速度,....可能已在过渡期间合并到 MASTER 中)
  5. 修复分支 A 中的问题
  6. 将 A 合并回 MASTER
  7. (重复 4 => 6 直到 A 工作结束)

上面的很好,但是我们需要在第 7 步之后做的是识别(通过某种 GIT diff):

在完成上述生命周期后,A 已将净值更改为 MASTER。

因此,我们正在寻找一个单向差异 A => MASTER 来显示在两个分支之间双向发生多次合并后由 A 引入 MASTER 的净变化。

非常感谢我能得到的任何意见 - 谢谢!

标签: git

解决方案


您的生命周期模型与能够在合并到基线之前查看所有更改的目标相冲突,特别是在完成测试之前将主题分支合并到主分支的步骤。

相反,保留主题分支中的所有更改,直到最终签核后的集成之前。寿命较长的主题分支可能需要master 进行一些合并,即

git fetch
git merge origin/master

这样,您就可以在主题分支的第 4 步到第 7 步中执行测试和所有其他活动。在最终签核之前,使用简单的方法查看累积更改

git fetch
git diff origin/master

最后,合并的确切机制将取决于您的工作流程。

如果您不介意基线中可能存在混乱的历史记录,只需合并您的主题分支。

git fetch
git checkout master
git merge --ff-only origin/master
git merge topic/fix-potrzebie

如果您的软件质量组织擅长壁球合并

git checkout master
git merge --ff-only origin/master
git merge --squash topic/fix-potrzebie
... fix merge conflicts ...
git commit -m 'PROJ-1234 Fix potrzebie ...'
git push origin master

保留主题分支存在的证据,但将其折叠为单个提交。以艰难和冒险的方式做这件事看起来像

根据最新基线创建主题分支的新最终版本。

git fetch
git checkout -b topic/fix-potrzebie-final origin/master

将开发主题分支折叠到单个提交。

git merge --squash topic/fix-potrzebie
... fix merge conflicts ...
git commit -m 'PROJ-1234 Fix potrzebie ...'

将其合并回基线。

git checkout master
git merge topic/fix-potrzebie-final
git push origin master

但是没有理由再次进行所有的合并,这也带来了风险,您可能会将不同的代码合并到基线中而不是测试的代码中。已经合并并实际测试的代码可寻址为topic/fix-potrzebie^{tree},即与主题分支顶端的提交相关联的树对象。用一个代码是最后的树

git fetch
git checkout master
git merge --no-ff -m 'Integrate PROJ-1234' \
  $(echo 'PROJ-1234 Fix potrzebie ...' |
      git commit-tree topic/fix-potrzebie^{tree} \
        -p $(git rev-parse origin/master))

最后一个命令有一点魔法。它创造了形式的历史

$ git lola
*   df6bbc7 (HEAD -> master) Integrate PROJ-1234
|\
| * 0c180a8 PROJ-1234 Fix potrzebie ...
|/
| * 0156bc9 (topic/fix-potrzebie) Updates after testing
| * 0ae9d12 Potrzebie changes
|/
* 61993d0 (origin/master) PROJ-1233 Previous history ...

请注意,这git lola是一个非标准但非常有用的别名

git log --graph --decorate --pretty=oneline --abbrev-commit --all

另请注意,master 的新提示和主题分支之间不存在任何更改

$ git diff master topic/fix-potrzebie
[ no output, indicating no differences ]

但它们实际上是相同的,它们具有相同的 SHA-1 哈希,因此共享同一棵树。

$ git rev-parse master^{tree} topic/fix-potrzebie^{tree}
9a4fc1bb6230e80bc3a1928a00cb404da6424153
9a4fc1bb6230e80bc3a1928a00cb404da6424153

要理解该命令,请按从右到左的顺序阅读。

  1. echo $MSG2 | git commit-tree $TREE -p $PARENT是 git 管道,它创建一个新的提交,其树为$TREE,其父级为$PARENT,其提交消息为$MSG2.
    • 该树与已在主题分支的顶端提交的树相同。
    • 父级是origin/master当前基线,但从人类可读的 refname 转换为 SHA-1 哈希git rev-parse
    • 的输出git commit-tree是新提交的 SHA-1 哈希,它变成$COMMIT_HASH
  2. git merge --no-ff -m "$MSG1" $COMMIT_HASH将新提交合并到master. 尽管我们将其设计为快进,但该--no-ff开关仍保留了短暂的发散-然后合并凹凸作为历史上的人工制品。
    • 这里的解释从单引号变为双引号以保持一致,但我希望不要与来自环境变量的值混淆。

此时,您可以使用以下命令删除现已过时的主题分支

git branch -D topic/fix-potrzebie

产生形式的整洁历史

$ git lola
*   df6bbc7 (HEAD -> master) Integrate PROJ-1234
|\
| * 0c180a8 PROJ-1234 Fix potrzebie ...
|/
* 61993d0 (origin/master) PROJ-1233 Previous history ...

最后,通过以下方式与团队其他成员分享

git push origin master

推荐阅读