Onu*_*nur 2 git renaming git-rebase cherry-pick git-cherry-pick
我想挑选从分支到另一个分支的单一提交.我希望文件重命名很常见,但仍希望能够在没有人为干预的情况下应用更改.
由于内置的cherry-pick命令没有接缝来检测重命名(至少在我的测试用例中),特别是与修改重命名的文件结合使用时.
我尝试了一下,最后想出了一个涉及两个rebase操作的解决方案.
让我们假设我有一个名为target的分支指向我想要应用cherry-pick的提交.我想要挑选的提交由名为source的分支指向.
然后我执行以下命令:
git rebase --strategy="recursive" --strategy-option="rename-threshold=30" target sourceTemp (可能使用另一个阈值;测试文件非常小,因此更改相对较大)git rebase --onto target sourceTemp~ sourceTemp这仅适用于分支源中最后一次提交引用到目标的更改.
我也把测试放在github上:
https://github.com/fraschfn/cherry-pick
我想知道的是,如果这种方法是可行的,或者只是在我简单的测试设置中有效的话!
更新:替代方法
我将补丁重新绑定到源和目标的合并基础:
开始的情况
A - B <--- target
/
M
\
C - D <--- source
Run Code Online (Sandbox Code Playgroud)
我想樱桃挑选D到B.
创建新的分支补丁后,将D重新映射到M上
A - B <--- target
/
M - D' <--- patch
\
C - D <--- source
Run Code Online (Sandbox Code Playgroud)合并C和D'以获取源代码
合并B和D'以获取目标的修补版本
A - B <--- target
/ \
/ E <--- patched target
/ /
M - D' <--- patch
\ \
\ F <--- new source (same snapshot as source different history)
\ /
C - D <--- source (will be discarded)
Run Code Online (Sandbox Code Playgroud)优点是E和F现在可以合并而没有问题.替代方法:尽可能早地在层次结构中包含补丁,从而不创建D,而是直接D'并保存自己的rebase.
以前版本的优点是你可以合并两个分支"new source"和"patched target",它可以工作(如果源和目标的合并当然可以工作)并且不会引入相同的变更集两次,因为git知道由于合并操作将变更集引入两个分支.
rename-threshold对于您正在尝试的方法,您的方法是可行的.除非您的分支机构是永远不会合并的分叉项目,否则分支机构之间的常规樱桃选择永远不是一个可持续的工作流程.如果是这样的话,那就去吧,祝你好运.如果您曾期望将您的分支合并为一个有凝聚力的整体,我建议您更改代码流的方式.以下是一些很好的资源:
在分支之间定期进行樱桃采摘会产生相同的变化集,并具有不同的SHA1哈希值.在足够长的时间内缩放,跟踪代码变得困难,理解你的历史几乎是不可能的,并且合并分支会让你觉得你在MC Escher绘画中昏昏欲睡并醒来.这不是一个好时机.
根据您对此答案的评论,您的用例听起来像是一个可行的樱桃选择.在这种情况下,我建议将补丁集应用于重命名的文件的工作量略微减少:
git checkout branchB
git diff <commit>~1 <commit> |
sed 's:<path_on_branchA>:<path_on_branchB>:g' |
git apply
Run Code Online (Sandbox Code Playgroud)
这里<commit>是你想从移动提交branchA给branchB.使用此方法,您将无法获取提交元数据,即它只是应用更改,它不会提交它.但你可以轻松地操纵git format-patchwith sed和的输出git am.只取决于你想做什么.
这将为您节省生成临时分支,选择正确的重命名阈值和重新定位的麻烦.它永远不会像直线一样干净git merge,但我之前已经使用过它,一旦掌握它就很容易了.