Home > Software engineering >  How to create a git diff from changes to file A and apply it to renamed File B
How to create a git diff from changes to file A and apply it to renamed File B

Time:10-05

In branch egg, file A:

Value = A

is changed to

Value = B

In branch orange:

$ git mv ./A ./B

Branch egg is left as a branch for many weeks. Branch orange is merged into the trunk. egg is now so hopelessly out of date there's no reasonable path forward to rebasing or merging, but we can still steal at least some of that work back to save time.

Normally, one could do that with:

$ git checkout origin/egg <filename> -p

This is super convenient, because you can patch/edit all the chunks into the current branch -- you lose some git history but this usually is not as important as getting the work done.

However, with the rename above the patch will fail.

Is there a git command that is able to tell git "Please create a patch by pretending file A in egg is actually file B that exists in the trunk". Bonus points for being able to use -p to apply it, but I'm willing to give that up for any solution.

This comes up a lot when combining work performed in parallel. This example is heavily simplified, but in real cases I might have many more complex patches to apply involving hundreds of changes across maybe two or three renamed files. For small stuff this isn't bad, but for the kinds of changes above it's a lot of manual effort to carry over changes.

CodePudding user response:

Is there a git command that is able to tell git "Please create a patch by pretending file A in egg is actually file B that exists in the trunk".

No.

Git will find renames on its own in some cases, when git diff has rename-finding enabled. But there's no way to forcibly tell Git that a file is to be considered "renamed". Presumably you're hitting this case, otherwise cherry-pick would be working for you.

If you use git format-patch to turn a commit into a patch file, you can manually edit the patch to claim a different file name. You could write your own program to do this too, but to achieve your ultimate goal (of being able to use git apply -p) you'd probably be better off writing your program to:

  1. make a new, temporary branch from the base commit (parent of the egg-branch commit that you want to copy);
  2. rename the file there and commit;
  3. cherry-pick the desired egg-branch commit into the new branch: Git will detect the rename and since the file's content still matches, will also complete the cherry-pick automatically
  4. use the new commit-pair to make a patch that you can feed to git apply, or pause here to run git checkout -p with the new commit at the tip of the temporary branch;
  5. delete the temporary branch.

(It's probably useful to make steps 1 and 5 separable so that you can do this over a range of commits.)

CodePudding user response:

For an individual file, you can also use the standard patch command :

git diff master...egg -- A > /tmp/A.patch
patch B A.patch
  •  Tags:  
  • git
  • Related