Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

combining unrelated git repositories retaining history/branches

Tags:

git

we're having 3 separate git repositories (each with some branches) which we'd like to combine into one keeping full history and the ability to access the branches, like so:

so this is what we have. 3 repos:

/A/.git
/B/.git
/C/.git

and we'd like to have one super-repo with 3 subdirectories:

super/.git
super/A
super/B
super/C

and say when switching to branch feature1 (which was originally in repo B, introduced at a time that repo C didn't exist yet) we'd expect the result to be:

super/.git
super/A
super/B

we've read Combining multiple git repositories but had troubles using git-stitch-repo which basically worked as advertised only that quite a large number of commits were missing in the super-repo (without any error messages that would point to a problem).

any idea what we could be doing wrong here?

EDIT we are aware of submodules and subtree-merging, but both are not an option. this is supposed to be a one time operation. we need the repos joined once and forever.

EDIT probably a simpler way to put basically the same question: say we have one repo with 3 totally unrelated branches. we can merge them without a conflict to one branch (since they share no files). now when looking at the history we see 3 unrelated branches of commits and the one point where they come together. but what we'd like to see is one branch made up of the interleaved (by date/time) commits of all 3 branches.

like image 949
joreg Avatar asked Sep 27 '11 20:09

joreg


2 Answers

You don't want submodules as you will pull your hair out with all the git submodule update commands you will be issuing. You will also have to issue 3 git log commands instead of one to see what has happened in a certain amount of time.

Bring all of the histories into one repo. Use filter-branch to reset the directories that each repos history resides in. There is no need to stitch. You can simply merge at any point once you do the filter branch.

Essentially repoA/master, repoB/master and repoC/master will exist in the new repo you make (although you can just start with one of them). After you apply filter branch, each tree in each commit will have a new root node that will be a directory (A for repoA branches, B for repoB branches, etc).

OR

git checkout -b newbranch --root
git log --all --format=%ad%H | sort | cut -c10- | xargs -n 1 git cherry-pick

adjust the cut so it only takes the hash. Haven't tried this but let me know how it works. You may need to flatten out history first with rebase. You can't interleave the different branches and merges from the 3 different histories.

hope this helps.

like image 78
Adam Dymitruk Avatar answered Sep 18 '22 15:09

Adam Dymitruk


splice_repos is a tool I wrote that interleaves commits from different repositories into a new repository, so that same-named branches get merged histories (as though they were committed to in historical order), rather than just being merged at the end with separate histories on different branches. There's a blog entry describing the rationale behind it.

like image 29
David Fraser Avatar answered Sep 22 '22 15:09

David Fraser