假设如下所示:
HEAD/master
|
A<--B<--C<--D<--E<--F<--G<--J
^
official
其中official
是一个分支
我想挑选2个提交到official
分支,例如E
和J
这两个提交都是影响相同3个文件的修复
当我做git cherry-pick E
时,一切都很顺利,但当我做了git cherry-pick J
时,我遇到了一些冲突
通过查看diffs,我意识到我还需要挑选commit F,它在这3个文件中的两个文件中进行了更改,该更改基本上是方法定义的更改,而J
是在此基础上完成的
所以只需执行git cherry-pick F && git cherry-pick J
就可以很容易地解决问题:
如果我不知道这些文件中所做的更改,并且提交F是一个巨大的提交,更改了许多文件:有没有其他方法可以确定我们试图挑选的提交依赖于哪一个提交,而无需手动对文件执行git日志并逐个提交?
有没有其他方法可以确定我们试图挑选的提交依赖于哪个提交,而无需手动对文件进行git日志并逐个提交?
是的,我写了git-deps
来精确地自动化这项任务。由于它目前接受一系列提交进行分析,在您的示例中,您需要向它传递一个只包含提交J
的单例范围,并告诉它排除official
:中已经存在的任何依赖项
git deps --exclude-commits official J^!
在幕后,该工具将查看J^
与J
的差异,然后在删除或修改的任何行上运行git blame
,再加上周围上下文的可配置行数。这将导致它发现J
删除或修改的一个或多个行来自提交F
,因此它将输出提交F
的SHA1。
git-deps
不仅可以发现单个提交或一系列提交的依赖关系,还可以递归整个依赖树。因此,您所描述的整个樱桃采摘场景可以自动化为一个命令:
git deps --recurse --exclude-commits official J^! |
tsort |
tac |
xargs -t git cherry-pick
请注意,这只是保证cherry picks将全部干净地应用,而不是保证它们在语义上是正确的。因此,生成的分支头仍然需要仔细检查和测试其正确性。
更方便地在分支之间移植提交是git-deps
最明显(但不是唯一)的用例,因此,我专门在README中专门介绍了这个用例。它甚至包括一个YouTube视频,向你展示如何使用它
如果你想了解更多细节,你可能会对我介绍的几个关于这个和其他相关工具的演讲感兴趣:
- 给Git伦敦用户组的演讲
- 在OpenStack开发者会议上发表的演讲
我还在中谈到了该工具GitMinutes播客第32集。
我遇到了一些[合并]冲突。。。有没有其他方法可以确定我们试图挑选的承诺取决于哪一个承诺。。。
不是,不是。
。。。而不手动对文件执行git日志并逐个提交?
即使这样也不一定能做到——至少,在没有真正考虑问题的情况下。考虑以下C代码位:
void f(int x) {
int i;
/*
* additional lines here, enough to mess with git context
* since that only looks at +/- 3 lines around each patch
* segment
*/
for (i = 0; i < x; i++)
do_something(i);
}
假设一个中间提交引入了一个额外的变量j
,然后随后的提交将do_something(i)
更改为do_something(j)
。如果您在以后的提交中只选择,Git将很高兴地更改行而不会发生冲突,但代码将不再编译,因为函数f
中没有int j
。
也就是说,可以编写一个工具来解析每个中间提交的git show
输出,计算出哪些行发生了更改(相对于工作树中的版本,而不是使用每个diff中的实际数字,因为这些数字可能取决于以前跳过的diff),并将您指向修改冲突区域的提交。但我不知道有什么这样的工具。