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)