Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge two git repository histories

Tags:

git

svn

cvs

I want to combine a cvs and a svn repository into a new git repo, without loosing history of course. The catch is the svn repo is a direct continuation of the cvs repo historywise. Someone just created the svn repo and clumsily added the last state from cvs without keeping any history. The most recent sources are in svn. I don't want to keep the old repos.

The history in graphics:

CVS: A - B - C
SVN: D - E - F - G

What I want:

GIT: A - B - C - D - E - F - G

I made a git repo from cvs with cvs2git, and another git repo from svn with git svn clone as outlined in http://john.albin.net/git/convert-subversion-to-git but just can't figure out how to combine the two. I did this:

git clone cvs.git
cd cvs
git remote add svn ../../svn.git
git fetch svn

Now what? git merge -s ours svn/master seems to do what I want but does not create a linear history:

A - B - C - - - H'
               /
D - E - F - G /

Any experiments with git rebase didn't get me anywhere.

like image 671
mplwork Avatar asked Apr 17 '13 09:04

mplwork


People also ask

Does Git merge keep history?

In the Conceptual Overview section, we saw how a feature branch can incorporate upstream changes from main using either git merge or git rebase . Merging is a safe option that preserves the entire history of your repository, while rebasing creates a linear history by moving your feature branch onto the tip of main .

How do you resolve refuse to merge unrelated histories?

The alternative (and longer) way of fixing the fatal: refusing to merge unrelated histories issues is to unstage your current commits, stash them, clone your required remote repository, and then place your stashed branch contents into the new clone.


2 Answers

Use .git/info/grafts to connect histories and then git filter-branch to make it permanent. There is a some description how somebody done it: http://bugsquash.blogspot.co.uk/2010/03/stitching-git-histories.html

like image 112
kan Avatar answered Oct 22 '22 05:10

kan


Using what kan wrote I came up with this solution:

git clone cvs.git
cd cvs
git remote add svn ../../svn.git
git fetch svn

Use git log --all to find the unconnected histories:

...
|
* ab42f52 2011-09-14 06:03:07 +0000 |  [svnuser]
|
* 1985b93 2011-09-14 06:00:00 +0000 | Migration from CVS [svnuser]

* 12e0ed4 2011-09-14 05:58:10 +0000 | *** empty log message *** (HEAD, origin/master, origin/HEAD, master) [cvsuser]
|
* 5060a7f 2011-04-18 14:07:03 +0000 | *** empty log message *** [cvsuser]
|
...

Find the full SHA1:

git show 1985b93
git show 12e0ed4

Create the graft:

echo 1985b9305ebc819e760f7ecf8e2abe7963eac055 12e0ed4c3dd75cec396a2d228825702eab73ba19 > .git/info/grafts

Now the histories are connected but not yet permanent:

|
* ab42f52 2011-09-14 06:03:07 +0000 |  [svnuser]
|
* 1985b93 2011-09-14 06:00:00 +0000 | Migration from CVS (grafted) [svnuser]
|
* 12e0ed4 2011-09-14 05:58:10 +0000 | *** empty log message *** (HEAD, origin/master, origin/HEAD, master) [cvsuser]
|
* 5060a7f 2011-04-18 14:07:03 +0000 | *** empty log message *** [cvsuser]
|

Make it permanent as shown in http://bugsquash.blogspot.co.uk/2010/03/stitching-git-histories.html:

git branch svnmaster svn/master
git filter-branch -- 12e0ed4c3dd75cec396a2d228825702eab73ba19..svnmaster

This creates new commits but also leaves the original svn commits. git log --all will show it:

* 849278b 2013-04-15 16:31:44 +0000 | Java 6 in Eclipse.  Deployed. (svnmaster) [svnuser]
|
...
|
* c33f7cc 2011-09-14 06:03:07 +0000 |  [svnuser]
|
* 7acb3ed 2011-09-14 06:00:00 +0000 | Migration from CVS [svnuser]
|
| * b3d5413 2013-04-15 16:31:44 +0000 | Java 6 in Eclipse.  Deployed. (svn/master, refs/original/refs/heads/svnmaster) [svnuser]
| |
...
| |
| * ab42f52 2011-09-14 06:03:07 +0000 |  [svnuser]
| |
| * 1985b93 2011-09-14 06:00:00 +0000 | Migration from CVS (grafted) [svnuser]
|/
|
* 12e0ed4 2011-09-14 05:58:10 +0000 | *** empty log message *** (HEAD, origin/master, origin/HEAD, master) [cvsuser]
|
* 5060a7f 2011-04-18 14:07:03 +0000 | *** empty log message *** [cvsuser]
|

Remove the graft, the duplicate history will be gone:

rm -r .git/info/grafts .git/refs/original

Clean up:

git reset --hard svnmaster
git branch -D svnmaster

And push:

git push

All done!

like image 41
mplwork Avatar answered Oct 22 '22 05:10

mplwork