git cherry-pick 在提交消息包含字符串/匹配正则表达式的范围内提交吗?

don*_*ote 1 git branch rebase cherry-pick

背景/场景

我有一个本地工作流程

  • 我总是在“本地”分支(“master”的祖先)上提交,使用以问题编号开头的提交消息,例如“#123: Some message”。
  • 我创建的功能分支也是“master”的祖先。
  • 然后我使用 rebase 和/或cherry-pick 将提交从本地复制到相应的功能分支。

例如,一种方法可以做到这一点:

git checkout local
git checkout -b 123-my-feature
git rebase -i master
Run Code Online (Sandbox Code Playgroud)

在交互式 rebase 编辑器中,删除消息不以 #123 开头的所有提交。这留下了一个特性分支 123-my-feature,它只包含来自问题 #123 的提交。

稍后,在分支 123-my-feature 已经存在之后,如果消息以 #123 开头,则还需要选择/复制本地上的后续提交到 123-my-feature 分支。这也可以通过交互式 rebase 或单独的cherry-picks 实现。但是过程很繁琐。

有没有办法用cherry-pick来做到这一点,并通过提交消息自动过滤?

例如

git checkout master
git checkout -b 123-my-feature
git cherry-pick master..local --commit-message-begins-with="#123"
Run Code Online (Sandbox Code Playgroud)

或者甚至是一个交互式的cherry-pick,我可以在其中手动删除不以“#123”开头的提交。

如果有另一个命令可以实现这一点,为什么不呢。不一定非得挑剔。

tor*_*rek 5

不是直接的,不是——但是很容易编写一个脚本来做到这一点。

大多数其他 Git 命令背后的通用命令是git rev-list,它有一个巨大的选项列表git rev-list不过,首先要知道的是,它实际上与git log. 它们都采用相同的选项,并且做大部分相同的事情,除了git rev-list旨在为其他 Git 程序生成哈希 ID(主要是提交的 ID),同时git log旨在向您或其他人展示提交的内容。

由于git loghas--grep可让您根据消息选择要显示的提交,因此git rev-list--grep可让您选择提交。'^#123: '例如,使用 pattern将选择日志消息包含一行开头的提交123: (包括尾随空格——在此处选择您的模式并用于git log测试它)。

就像git loggit rev-list会从你给它的任何开始(或结束?)点向后工作,并永远继续,除非你也告诉它在哪里停止搜索。您需要选择一个停止点;通常这将是一个分支名称或标签,或者甚至是一个原始哈希 ID,以选择一个提交,Git 应终止其对提交的向后搜索。在这种情况下,该停止点可能是master。这个的一般语法就是你写的:(master..local或等效地,local ^master)。因此,您想要的提交列表是由以下生成的:

git rev-list --grep=... master..local
Run Code Online (Sandbox Code Playgroud)

(尝试运行这个,或者——甚至更好——git log先运行,然后运行git rev-list并观察差异)。

现在,还有一两个问题。第一个是git log,和几乎大部分 Git 一样,git rev-list从最新的提交开始并回到过去,向后工作。但是,当您挑选樱桃时,您往往必须从最早的时间点开始并向前推进。幸git log--reverse,所以git rev-list也有--reverse

最后一个明显的问题是git rev-list可能找不到提交。在这种情况下,您可以让git cherry-pick自己投诉,也可以检查并自己投诉。只是让git cherry-pick抱怨:

git checkout -b 123-my-feature master
git cherry-pick $(git rev-list --reverse --grep '^#123' master..local)
Run Code Online (Sandbox Code Playgroud)

(我已经将 的分支创建123-my-feature与其初始值的设置结合起来,指向与 相同的提交master,这样整个事情只是两行 shell 脚本。要以更高级的方式做到这一点,您可能会捕获在git rev-list输出第一,只有创建分支和运行樱桃采摘如果列表不为空)。