Merge two git repository histories

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:

  • How to know if git repository has changes that have not been synchronized with server (origin)?
  • Copy changes from an external untracked directory to separate Git working copy
  • SVN and revision numbers
  • How do you deal with configuration files in source control?
  • Diffing between two entire directories/projects?
  • CVS and Git Deletion with Extreme Prejudice
  • 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.

  • How to track directories but not their files with Git?
  • Pass Git SHA1 commit id for next build(s) in Jenkins
  • Git clone. key_load_public: invalid format Permission denied (publickey)
  • What are the differences between git remote prune, git prune, git fetch --prune, etc
  • Best strategy to deploy static site to s3 on github push?
  • Github ERROR: Repository not found (yes, another one)
  • 2 Solutions collect form web for “Merge two git repository histories”

    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

    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!

    Git Baby is a git and github fan, let's start git clone.