Merging multiple Git repositories with tags
Asked Answered
O

1

6

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.)

Okubo answered 29/7, 2013 at 21:23 Comment(2)
Is this something that needs to be automated or repeatable? Or is this a one-time event?Syncopated
Repeatable and automated. The modules are going to be maintained by separate teams, and should be able to change to rely on different versions of both each other and the core at any time in the future. I'd also like the relevant commands to be easily derivable from a config for our CI server.Okubo
N
7

Would it work to use --no-tags with:

git fetch fork1 refs/tags/*:refs/tags/fork1/* --no-tags

This would drop fork1's tags into refs/tags/fork1 without also dropping them in refs/tags.

Noticeable answered 30/7, 2013 at 13:18 Comment(1)
Lovely trick ❤️Belamy

© 2022 - 2024 — McMap. All rights reserved.