I have a project which has multiple copies of some files in different places. For example:
src/location1/foobar.h
src/location1/foobar.cpp
src/location2/foobar.h
src/location2/foobar.cpp
I am extracting these into the own library. So I wish to end up with:
src/location3/foobar.h combining multiple versions of foobar.h
src/location3/foobar.cpp combining multiple versions of foobar.cpp
I've passed the first hurdle of removing all unwanted files using:
git filter-repo --path-glob \*foobar\*
Discovering in the process that filter-branch has recently been superceded by the superior filter-repo (worth repeating as filter-branch still appears in many top answers here).
I now want to combine the copies into one preserving all their histories.
The two candidates for this are merge
and merge-file
.
merge-file
requires the common ancestor of each file to be identified which is a pain as it was probably:
src/location3/foobar.h
which is somewhere unknown in the commit history.
We have git merge-base
to find the best common ancestor.
I'm not clear how to specify the file version for git merge-file I want to do:
git mv src/location1/foobar.h src/newlocation/foobar.h
git commit
git merge-file src/newlocation/foobar.h src/location3/foobar@<commitid> src/location2/foobar.h
...
git merge-file src/newlocation/foobar.h src/location3/foobar@<commitid> src/location3/foobar.h
This is quite painstaking and has to be repeated for each file. Another way is to create multiple temporary branches:
git checkout -b newlibbranch
git mv src/location1/foobar.h src/newlocation/foobar.h
git mv src/location1/foobar.cpp src/newlocation/foobar.cpp
git commit
git checkout oldversion
git checkout -b v2
git mv src/location2/foobar.h src/newlocation/foobar.h
git mv src/location2/foobar.cpp src/newlocation/foobar.cpp
git commit
git checkout newlibbranch
git merge --allow-unrelated-histories v2
This is also quite painstaking. Though it is possibly scriptable. There is also a practical problem as the merge is "rename/rename" conflict rather than a merge of the actual files. This seems to be solved by adding --allow-unrelated-histories
So my questions are:
Regarding the task:
- Is there a better way? perhaps a merge tool I am unaware of like I was unaware of filter-repo
- I am correct in thinking the multiple merge branches way is better than git merge-file?
Regarding merge-file:
- how do I specify a particular version of a file for git merge-file
- Is there a command or script which finds the common ancestor automatically. Something like:
git merge-file-wrapper location1 location2 -->
base = `git merge-base location1 location2`
git merge-file location1 $base location2
Could it be that this does not exist because there are some hidden pitfalls?