don*_*ote 1 git branch 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”开头的提交。
如果有另一个命令可以实现这一点,为什么不呢。不一定非得挑剔。
不是直接的,不是——但是很容易编写一个脚本来做到这一点。
大多数其他 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 log,git 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输出第一,只有创建分支和运行樱桃采摘如果列表不为空)。