git cherry-pick 在提交消息包含字符串/匹配正则表达式的范围内提交?
git cherry-pick commits in range where commit message contains string / matches regex?
背景/场景
我有一个本地工作流程
- 我总是在 "local" 分支("master" 的祖先)上提交,使用以问题编号开头的提交消息,例如“#123: Some message”。
- 我创建了特征分支,它们也是 "master" 的祖先。
- 然后我使用 rebase and/or cherry-pick 将提交从本地复制到相应的功能分支。
例如一种方法:
git checkout local
git checkout -b 123-my-feature
git rebase -i master
在交互式 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"
或者甚至是一个交互式的 cherry-pick,我可以在其中手动删除不以“#123”开头的提交。
如果有另一个命令可以实现这一点,为什么不呢。不必是精心挑选的。
不直接,不——但是编写一个脚本来完成它很容易。
大多数其他 Git 命令背后的通用命令是 git rev-list
, which has a huge option list。不过,关于 git rev-list
首先要知道的是,它实际上与 git log
几乎是同一个命令。它们都采用相同的选项,并做大部分相同的事情,除了 git rev-list
旨在为其他 Git 程序生成哈希 ID——主要是提交的哈希 ID,而 git log
旨在向您或其他人展示提交的内容。
因为 git log
有 --grep
可以让你 select 承诺根据消息显示,git rev-list
也有 --grep
可以让你 select 提交。例如,使用模式 '^#123: '
会 select 提交其日志消息的行以 123:
开头(包括结尾的 space — 在此处选择您的模式并使用 git log
进行测试)。
像 git log
一样,git rev-list
会从你给它的任何开始(或结束?)点开始倒退,并一直持续下去,除非你告诉它在哪里停止 也在搜索。你需要选择一个停止点;通常这将是一个分支名称,或标签,甚至可能是一个原始哈希 ID,到 select 一个提交,其中 Git 应该终止其向后搜索提交。在这种情况下,停止点可能是 master
。这的一般语法正是您所写的:master..local
(或等效的 local ^master
)。因此,您想要的提交列表是由以下内容生成的:
git rev-list --grep=... master..local
(试试 运行 宁这个,或者 - 甚至更好 - 首先 运行 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)
(我将 123-my-feature
的分支创建与其初始值的设置结合起来,指向与 master
相同的提交,因此整个事情只是两行shell 脚本。要以更奇特的方式执行此操作,您可以先捕获 git rev-list
输出,并且仅在列表不为空时创建分支和 运行 cherry-pick。 )
GIT_SEQUENCE_EDITOR
不是很出名,它在文档中只提到过一次(在 git 配置页面中,对于 sequence.editor
),但这正是您要查找的内容对于.
GIT_SEQUENCE_EDITOR='sed -i /^pick [^ ]* #123 /!d' git rebase -i master
你应该做的。
背景/场景
我有一个本地工作流程
- 我总是在 "local" 分支("master" 的祖先)上提交,使用以问题编号开头的提交消息,例如“#123: Some message”。
- 我创建了特征分支,它们也是 "master" 的祖先。
- 然后我使用 rebase and/or cherry-pick 将提交从本地复制到相应的功能分支。
例如一种方法:
git checkout local
git checkout -b 123-my-feature
git rebase -i master
在交互式 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"
或者甚至是一个交互式的 cherry-pick,我可以在其中手动删除不以“#123”开头的提交。
如果有另一个命令可以实现这一点,为什么不呢。不必是精心挑选的。
不直接,不——但是编写一个脚本来完成它很容易。
大多数其他 Git 命令背后的通用命令是 git rev-list
, which has a huge option list。不过,关于 git rev-list
首先要知道的是,它实际上与 git log
几乎是同一个命令。它们都采用相同的选项,并做大部分相同的事情,除了 git rev-list
旨在为其他 Git 程序生成哈希 ID——主要是提交的哈希 ID,而 git log
旨在向您或其他人展示提交的内容。
因为 git log
有 --grep
可以让你 select 承诺根据消息显示,git rev-list
也有 --grep
可以让你 select 提交。例如,使用模式 '^#123: '
会 select 提交其日志消息的行以 123:
开头(包括结尾的 space — 在此处选择您的模式并使用 git log
进行测试)。
像 git log
一样,git rev-list
会从你给它的任何开始(或结束?)点开始倒退,并一直持续下去,除非你告诉它在哪里停止 也在搜索。你需要选择一个停止点;通常这将是一个分支名称,或标签,甚至可能是一个原始哈希 ID,到 select 一个提交,其中 Git 应该终止其向后搜索提交。在这种情况下,停止点可能是 master
。这的一般语法正是您所写的:master..local
(或等效的 local ^master
)。因此,您想要的提交列表是由以下内容生成的:
git rev-list --grep=... master..local
(试试 运行 宁这个,或者 - 甚至更好 - 首先 运行 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)
(我将 123-my-feature
的分支创建与其初始值的设置结合起来,指向与 master
相同的提交,因此整个事情只是两行shell 脚本。要以更奇特的方式执行此操作,您可以先捕获 git rev-list
输出,并且仅在列表不为空时创建分支和 运行 cherry-pick。 )
GIT_SEQUENCE_EDITOR
不是很出名,它在文档中只提到过一次(在 git 配置页面中,对于 sequence.editor
),但这正是您要查找的内容对于.
GIT_SEQUENCE_EDITOR='sed -i /^pick [^ ]* #123 /!d' git rebase -i master
你应该做的。