Ivan Danilov
Ivan Danilov

Reputation: 14787

git cherry-pick with target file renamed

I have two branches for different versions - one for current development and another is long-time support several years old. As a consequence they differ significantly. I have some file that exists in both branches, but was renamed in development. One of fixes was made in development branch originally, but later found to be required in support branch as well. But cherry-pick reports that the file does not exist in support branch (because it was renamed in development and in support it has different name).

Contents of this particular file is similar, so it seems patch should be applied fine - if I can direct git what file it should apply it to. Is there a way (preferably in command line) to manually direct git to do what I need?

Upvotes: 28

Views: 12620

Answers (2)

Yirkha
Yirkha

Reputation: 13868

The cherry-pick command is using the same merge strategies as the merge command. The default recursive merge strategy is able to detect renames under normal circumstances, but it can fail if the files have diverged too much like in this case.

Apart from the low level index hacking outlined in the other answer, it might be possible to make it work simply by fiddling with the strategy options, for example increase the threshold for considering a similar file to be a renamed version (default is 50%):

git cherry-pick -Xrename-threshold=20% <SourceCommitHash>

Otherwise you could also always do it the manual way, i.e.

git format-patch -1 <SourceCommitHash>

Then edit the created 0001-Commit-message-here.patch to change the file path and apply again on the target branch:

git am 0001-Commit-message-here.patch

It will retain all original commit messages, author names, dates etc. and might work as an easy one shot solution.

Upvotes: 36

Ivan Danilov
Ivan Danilov

Reputation: 14787

Remembered, where I have seen something similar. It was here. Linked script helps as well.

With the script you might do it with one-liner:

$ git merge-associate Old/Path/Original.txt :1:New/Path/Renamed.txt :3:New/Path/Renamed.txt

Same as if git merge-file supported :stage:filepath syntax without doing all the fuss around git show :1:New/Path/Renamed.txt > 1.txt; git show :3:New/Path/Renamed.txt > 3.txt described in Git FAQ.

Upvotes: 6

Related Questions