繁体   English   中英

如何合并/挑选单个提交

[英]How to merge/cherry-pick a single commit

我有一个像这样的分支结构的项目(基于 GitHub)

master:   A - B - C - D
            \
release:      W - X - M
                    /
bugfix:       Y - Z

因此,一旦bugfix被合并, release将有A - W - X - Y - Z - M ,其中 M 是合并提交, Y & Z是来自bugfix分支的原始提交。 到目前为止一切都很正常。

现在,我想做的是让MYZ一起进入master 但这里有一个警告——我希望WX在 master 中。 为什么? WX是类似“Bump to our hotfix release version”的提交,它们在master中没有位置。 所以最后,我希望master成为A - B - C - D - Y - Z - M

如果我在Mgit cherry-pick ,我只会得到M并且我会丢失YZ的历史。 这就是我正在做的事情,但后来我在git blame中失去了功能,并且作者最终被隐藏了(因为 GitHub 提交了由合并它的人而不是原始提交者编写的合并)。

如果我在Mgit merge ,我会得到我不想要的整个分支,包括WX

如何实现?


让我再向我的 Y 澄清一下 X:

我们的项目完全基于 GitHub,使用 fork-and-PR 模型(在那里很正常)。

A 之前的内容无关紧要; 我们的发布分支基于 A,然后我们添加了 W 和 X 以进行发布(标签在 X 上)。

因此,随机贡献者 Alice 做了一个来自并针对我们的发布分支的错误修复。

release:      W - X
                    \
bugfix:               Y - Z

我们的团队成员 Bob 将该拉取请求合并到我们的发布分支中。

release:      W - X   - - -  M
                    \       /
bugfix:               Y - Z

重要的是,我,或项目中的任何人,一旦合并就无法触及错误bugfix 它在 Alice 的项目分支上,我们在 Release 分支中有这个:

A - W - X - Y - Z - M

并且由于我们创建了 Release 分支,新的提交( BCD )已添加到我们的 Master 分支中。

现在,这是我的问题的症结所在:我想获取该拉取请求的整个历史记录——来自 Alice 的原始提交( YZ )和来自 Bob 的合并细节(通过合并提交M )——到我们的master分支.

我很高兴选择合并,但由于 GitHub 处理 PR 合并的方式的特殊性,这意味着如果我这样做,Alice(和她的提交)的所有痕迹都会丢失。 这是我们要避免的。

您的图表缺少AY之前的历史记录(即提交),但通常要做的是将错误修复直接合并到所有受影响的分支中。 所以在这里你会git switch master然后git merge bugfix

(我还建议将分支名称作为实体放入,箭头指向当前在分支上的最后一个提交,因为这就是名称在 Git 中的实际工作方式。通过添加更多提交来更新分支只需将箭头移动到新的最后一次提交。如果您“将提交重置”,则将箭头向后移动(在 Git 中提交到提交箭头的方式)到较旧的提交,将较新的提交从末尾删除分支。)

好的,这不是一个真正的答案,而是原始樱桃挑选想法的解决方法。

hub pr提供了有关谁提交了 PR 的详细信息,所以至少,我可以更改 cherry-pick 提交以显示谁编写了 PR。 我想这已经足够了,因为很明显这永远不会像我希望的那样工作。

对于任何好奇的人,这是给 Jellyfin 的,这是我们用来将 PR 从发布分支反向移植回 master 的脚本,并进行了调整以显示 PR 的作者。 希望那么另一个项目不必对此视而不见。

https://github.com/jellyfin/jellyfin-build/blob/master/backport-prs#L82

首先澄清一下这个说法:

我不希望 W 或 X 在 master 中。 为什么? W 和 X 是类似“Bump to our hotfix release version”之类的提交,在 master 中没有位置。

通常,并不是您不希望master中的这些提交,而是您不希望master中的这些提交的更改 鉴于此,如果是我(并且我这样做),我会将release合并回master 有两种方法可以做到这一点,这样您就可以完成您想要的,并且仍然可以获得将整个release分支合并回master的所有其他好处,其中包括:

  • 假设这是一个非常糟糕的一天/一周,并且您在release分支上有 10 个错误修复。 你真的想将它们单独合并回来吗? (可能不是。)
  • 如果您不需要旧的发布分支,不必保留它们,这很好。 如果您能够将发布分支合并到master中,则可以删除它们。 您需要的有关任何先前版本的所有信息都包含在master中。
  • master可以访问实际发布的提交 ID,以及任何关联的标签。 (恕我直言,这是最重要的原因,这也是为什么我希望所有导致发布的提交都以master结尾。)

那么,如何在不拉入标记为WX的提交中的仅版本更改的情况下做到这一点? 这里有2种方法:

  1. 您可以进行两次合并。 首先,您在X中合并,但您使用-s ours选项放弃更改。 然后你合并到release 除了WX的变化之外,最终结果将release所有内容。 例如:
git switch master
git merge -s ours X # or the tag name you used here
git merge release

请注意, -s ours不应与-X ours (或theirs )混淆,后者是完全不同的东西,是关于自动冲突解决的。 我会认为-s ours合并不寻常,因为它完全忽略了所有合并的更改,因此我建议您在第一次合并时在提交消息中添加评论,说明“合并并忽略发布版本更改”的效果,所以它是明确合并的目的。

  1. 另一种方法是只对release分支进行一次合并,但在提交撤消版本更改之前停止。 这可以在脚本中轻松实现自动化。 例如:
git switch master
git merge release --no-commit
# now the version file changes will be staged, so unstage them:
git reset some-path/some-version-file
# now restore the version file to the version on the master branch:
git restore some-path/some-version-file
# repeat the reset and restore commands for all version files modified in W and X
...
# and finally complete the merge
git commit # or git merge --continue

我个人做这第二个选择。 (我的脚本撤消了由构建自动更新的 8 个版本文件。)我更喜欢选项 2 的原因是有时我的release分支上有多个构建,所以我需要多次进行双重合并,在-s ours之间交替-s ours的合并和实际合并将release分支的全部内容返回到master 但是,如果我总是像您描述的那样在开始时只有 1 个版本的 up-rev,我可能不会像我一样花时间自动撤消版本文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM