How to git cherry picks from related directories?

I would like to use git cherry-pick to apply fixation from one file to another without detecting renaming (many of these files lead to incorrect detections).

(master) directory1 / file

(master) directory2 / file

But I do not know how to say cherry-pick the corresponding directory.

I had another case where it worked perfectly with git-1.7.5.rc1 , which now supports the aka -Xsubtree=. merge strategies -Xsubtree=.

(master) directory1 / file

(branch) file

I called

 git cherry-pick --no-commit -Xsubtree=directory1 branch~95 

and it worked fine, accepting changes from the file (branch ~ 95) to the (master) directory1 / file without detecting renaming.

In the first case, I tried calling git cherry-pick with - Xsubtree=../directory1 , but that did not work. I guess I would have to tell git cherry-pick to somehow leave directory2, and then go to directory1 to apply the fixes.

Does anyone have a solution to this problem?

+7
source share
1 answer

Short review

git-recognize tree

In the subtrees I would look

 git read-tree -u --prefix dir1/ HEAD:dir2 

This will not lead to merging (git read-tree -merge does not support -prefix at the same time ...)

manual solution

Otherwise, the best you can do is perhaps

 basecommitish='HEAD^' git show "$basecommitish":dir1/a" > /tmp/a.orig git show HEAD:dir2/b > /tmp/b.new git merge-file dir1/a /tmp/a.orig /tmp/b.new 

This worked for my test repository, which led to the correct merge with the changes for both dir1/a and dir2/b .

Basic Version Detection

Unfortunately, finding the right source version for merging can be a problem, since git merge-base will not work for other object references than commit identifiers.

Search for the latest version where the files were identical

So, here is a snippet that will help you find the version in which both files are synchronized (looking only at the contents):

 git rev-list HEAD | while read sha1 do blob1=$(git rev-list --objects $sha1:dir1/a) blob2=$(git rev-list --objects $sha1:dir2/b) echo $sha1: $blob1 $blob2 if [ "$blob1" == "$blob2" ]; then echo Match; break; fi done 

Output to my testrepo:

 c5a6b97712d9ebd49146dad6523b2bbc33aea7c0: 4ce3b294e6408ace53b50127aafb2c9308caacf1 e913153db7650d7b8e947066652cf21388552812 7b75768fd3434c867d3741cf07044bf04ef1cc79: 03b82631ac519bf10c20bb12d3b1b03b872dd087 03b82631ac519bf10c20bb12d3b1b03b872dd087 Match 

You can easily incorporate any changes that may exist in other branches by replacing git rev-list HEAD with git rev-list --all .

Finding a pair of fixes in which the files were identical

A more advanced script that will look for matching content in non-matching versions, making nested loops, will

 function findblobs() { for path in " $@ "; do git rev-list HEAD | while read sha1 do echo $sha1 $(git rev-list --objects "$sha1:$path") done | uniq -f 1 done } 

Now you can find the same information by doing

 findblobs dir1/a dir2/b | sort -k2 | uniq -Ddf 1 // output on testrepo again: 7b75768fd3434c867d3741cf07044bf04ef1cc79 03b82631ac519bf10c20bb12d3b1b03b872dd087 7b75768fd3434c867d3741cf07044bf04ef1cc79 03b82631ac519bf10c20bb12d3b1b03b872dd087 // force multiple hits across several revisions: git show 7b75768fd3:dir1/a > dir2/b && git commit -am 'force synch with 7b75768fd3' findblobs dir1/a dir2/b | sort -k2 | uniq -Ddf 1 // output is now: 46b8748f121f8842d936994fa09ad1a81b35d3cc 03b82631ac519bf10c20bb12d3b1b03b872dd087 7b75768fd3434c867d3741cf07044bf04ef1cc79 03b82631ac519bf10c20bb12d3b1b03b872dd087 7b75768fd3434c867d3741cf07044bf04ef1cc79 03b82631ac519bf10c20bb12d3b1b03b872dd087 

Since sort(1) uses robust sorting, you can rely on the first commit hash matching dir1/a and the second on dir2/b in this call example (note the order in the findblobs call)

+4
source

All Articles