I'd like to cherry-pick single commits from on branch to another. I expect file renames to be quite common but still want to be able to apply changes without human intervention.
Since the built-in cherry-pick command doesn't seam to detect renames (at least in my test cases), especially when combined with modification to the renamed file.
I tried a bit and finally came up with a solution involving two rebase operations.
Let's assume I have a branch named target pointing at the commit I want to apply the cherry-pick to. The commit I want to cherry-pick is pointed to by a branch named source.
I then execute the following commands:
- create branch sourceTemp pointing at the same commit as source (since I want to retain the branch source )
git rebase --strategy="recursive" --strategy-option="rename-threshold=30" target sourceTemp
(maybe use another threshold; the test file was quite small and the changes therefore relatively large)git rebase --onto target sourceTemp~ sourceTemp
This applies only the changes introduced by the last commit in branch source to target.
I also put my test on github:
https://github.com/fraschfn/cherry-pick
What I like to know is, if this approach is feasible or if it only worked in my simple test setting!
Update: Alternative method
I rebase the patch to the merge base of source and target:
start situation
A - B <--- target
/
M
\
C - D <--- source
I want to cherry-pick D onto B.
rebase D onto M after creating a new branch patch
A - B <--- target / M - D' <--- patch \ C - D <--- source
merge C and D' to obtain a replacement for source
merge B and D' to obtain the patched version of target
A - B <--- target / \ / E <--- patched target / / M - D' <--- patch \ \ \ F <--- new source (same snapshot as source different history) \ / C - D <--- source (will be discarded)
The advantage is that E and F can now be merged without a problem. Alternative way: Include the patch as early as possible in the hierarchy thus not creating D but directly D' and saving yourself the rebase.
The advantage above the previous version is that you can merge the two branches "new source" and "patched target" and it will work (if the merge of source and target would work of course) and not introduce the same changeset twice since git knows due to the merge operation which introduced the changeset into both branches.