[英]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
分支的原始提交。 到目前为止一切都很正常。
现在,我想做的是让M
与Y
和Z
一起进入master
。 但这里有一个警告——我不希望W
或X
在 master 中。 为什么? W
和X
是类似“Bump to our hotfix release version”的提交,它们在master
中没有位置。 所以最后,我希望master
成为A - B - C - D - Y - Z - M
。
如果我在M
上git cherry-pick
,我只会得到M
并且我会丢失Y
和Z
的历史。 这就是我正在做的事情,但后来我在git blame
中失去了功能,并且作者最终被隐藏了(因为 GitHub 提交了由合并它的人而不是原始提交者编写的合并)。
如果我在M
上git merge
,我会得到我不想要的整个分支,包括W
和X
。
如何实现?
让我再向我的 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 分支,新的提交( B
、 C
、 D
)已添加到我们的 Master 分支中。
现在,这是我的问题的症结所在:我想获取该拉取请求的整个历史记录——来自 Alice 的原始提交( Y
和Z
)和来自 Bob 的合并细节(通过合并提交M
)——到我们的master
分支.
我很高兴选择合并,但由于 GitHub 处理 PR 合并的方式的特殊性,这意味着如果我这样做,Alice(和她的提交)的所有痕迹都会丢失。 这是我们要避免的。
您的图表缺少A
和Y
之前的历史记录(即提交),但通常要做的是将错误修复直接合并到所有受影响的分支中。 所以在这里你会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
结尾。) 那么,如何在不拉入标记为W
和X
的提交中的仅版本更改的情况下做到这一点? 这里有2种方法:
X
中合并,但您使用-s ours
选项放弃更改。 然后你合并到release
。 除了W
和X
的变化之外,最终结果将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
合并不寻常,因为它完全忽略了所有合并的更改,因此我建议您在第一次合并时在提交消息中添加评论,说明“合并并忽略发布版本更改”的效果,所以它是明确合并的目的。
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.