【问题标题】:git cherry-pick commits in range where commit message contains string / matches regex?git cherry-pick 在提交消息包含字符串/匹配正则表达式的范围内提交?
【发布时间】:2017-10-10 16:51:59
【问题描述】:

背景/场景

我有一个本地工作流程

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

例如一种方法:

git checkout local
git checkout -b 123-my-feature
git rebase -i master

在交互式变基编辑器中,删除消息不以 #123 开头的所有提交。 这会留下一个功能分支 123-my-feature,它仅包含来自问题 #123 的提交。

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

问题

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

例如

git checkout master
git checkout -b 123-my-feature
git cherry-pick master..local --commit-message-begins-with="#123"

或者甚至是交互式的挑选,我可以手动删除不以“#123”开头的提交。

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

【问题讨论】:

    标签: git branch rebase cherry-pick


    【解决方案1】:

    不直接,不,但很容易编写一个脚本来完成它。

    大多数其他 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 可以让您根据消息选择要显示的提交,git rev-list 也有--grep 可以让您选择提交。例如,使用模式 '^#123: ' 将选择日志消息中的一行以 123:  开头的提交(包括一个尾随空格 - 在此处选择您的模式并使用 git log 进行测试)。

    git log 一样,git rev-list 将从你给它的任何开始(或结束?)点向后工作,并且永远继续下去,除非你告诉它在哪里停止搜索。您需要选择一个停止点;通常这将是一个分支名称,或标签,甚至可能是一个原始哈希 ID,用于选择 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。)

    【讨论】:

      【解决方案2】:

      GIT_SEQUENCE_EDITOR 不是很知名,它在文档中只提到过一次(在 git 配置页面中,对于 sequence.editor),但它正是您正在寻找的。​​p>

      GIT_SEQUENCE_EDITOR='sed -i /^pick [^ ]* #123 /!d' git rebase -i master
      

      应该可以。

      【讨论】:

      • 如果这是一项相对罕见的任务并且很少有提交从 rebase 中删除,我会使用此方法,并且可能使用 git rev-list (我自己的答案)编写一个简短的脚本,如果它是一项频繁的任务,并且很少有提交可以从长链提交中挑选出来。但这绝对是一个很好的方法(并且被赞成)。
      猜你喜欢
      • 1970-01-01
      • 2015-06-30
      • 2015-06-16
      • 2013-03-19
      • 2012-11-05
      • 2021-01-18
      • 2016-04-11
      • 2018-04-17
      • 2012-05-21
      相关资源
      最近更新 更多