I am working with a number of different Git repos that will need to be merged together. The workflow would look like this:
git remote add fork1 ...
git remote add fork2 ...
git fetch fork1
git fetch fork2
git merge fork1/master fork2/master
This is all well and good, but I'd like to be able to pull a specific commit of each remote using tags:
git merge fork1/v1.0.0 fork2/v2.1.0
There should never be any merge conflicts, as each repo will have its changes confined to one subfolder, but even if there are, the octopus merge will cause the whole transaction to fail atomically.
The problem is with the tag references. As described in this blogpost (not mine), all tags are inexplicably dumped into a global namespace. There's no way to say fork1/v1.0.0
- it's just v1.0.0
, and if multiple repositories have the same tag, they squash each other.
Following this answer, I've been looking into using refspecs to work around this. So far, I've come up with the following:
git fetch fork1 refs/tags/*:refs/tags/fork1/*
This has the intended effect of making fork1's v1.0.0
tag arrive as fork1/v1.0.0
. Unfortunately, it also arrives as the un-namespaced v1.0.0
; git fetch
prints out twice as many lines in the tag-mapping section, and git merge v1.0.0
still merges with the pulled tag. I can't find good documentation on refspecs anywhere (Git's documentation on the topic is woefully useless).
How can I prevent tags from multiple repositories from conflicting with each other?
I'm also open to other workflow suggestions if I'm just going about this stupidly. I have one core repo that holds shared components and structure, and a number of module-repos that are full clones of the core with just their code added. My current plan is for each module to have a remote pointer to the core (to stay up to date on the shared parts) and to each other module that it relies on. The shared bits would merge because they're the same, and the module bits would merge because they're independent. Is there another pattern I should be following here? (I've avoided submodules, because (a) I've never heard anything good about them, and (b) the shared part is the top level in terms of project directory structure, which makes the repo structure extremely awkward.)