Merge disjoint branches with git

My current situation

I have 2 git repositories of the same software project, where one is the fork of the other:

fork:                A1 - B1 - C1 - ... - HEAD_FORK
                      :
       (Some changes done outside of git)
                      :
orig: A2 - B2 - C2 - D2 - E2 - ... - HEAD_ORIGINAL

These two histories are completely disjoint, they share no common commit. (as far as git is concerned)

However based on the timestamps and the fact that I know that fork was forked from orig (not using a VCS, but the usual dirty “just copy the files and create a new repository” way) I can find a point of “minimal difference” between the two:

A1 is based on D2 minus some files.

My goal

Merge this mess. I want fork with all the useful changes from orig after the fork.

I don’t care about the history of orig. One large commit on fork would be fine. (I could split and refactor that anyway)

My current battle plan

I already have a git repository which contains both histories as branches. What I plan to do:

  1. Create a branch orig-old where D2 is HEAD and a branch fork-old where A1 is HEAD.

    fork-old:                  A1 <- HEAD_FORK-OLD
                                :
                                :
    orig-old:   A2 - B2 - C2 - D2 <- HEAD_ORIG-OLD
    
  2. Merge fork-old and orig-old creating common-old

    fork-old:                  A1 <- HEAD_FORK-OLD
                                : \
    common-old:                 :  A3 <- HEAD_COMMON-OLD
                                : /
    orig-old:   A2 - B2 - C2 - D2 <- HEAD_ORIG-OLD
    
  3. Rebase fork on common-old

    fork:                         B1 - C1 - D1 - .... - HEAD_FORK
                                  /
    common-old:                  A3 <- HEAD_COMMON-OLD
                                 /
    orig-old:    A2 - B2 - C2 - D2 <- HEAD_ORIG-OLD
    
  4. Rebase orig on fork

    orig:                                E2 - F2 - ... - HEAD_ORIG
                                         /
    fork:         B1 - C1 - D1 - .... - X1 <- HEAD_FORK
                  /
    common-old:  A3 <- HEAD_COMMON-OLD
    
  5. Merge the rebased orig using merge –squash onto fork.

    orig:                         E2 - F2 - ... - K2 <- HEAD_ORIG
                                  /                \
    fork:  B1 - C1 - D1 - .... - X1 -------------- M1 <- HEAD_FORK
    
  6. Create a diff between the new HEAD of fork M1 and the old head (the HEAD of the forked repository) and apply it to the forked repository.

My question

Did anyone here try to do something similar and has some experience if that will work?
Since we are taking about quite a large undertaking here (multiple days at least), it would be nice to know if my plan is insanity before I start to merge all this.

I also considered just copying everything from orig and paste it over the files in fork
and then selectively add changes with “git add –patch” but I think for that there are just to much complex changes.

Thanks in advance!

  • Best way to reference an external library in multiple projects in a Visual Studio solution
  • Is it possible to completely alter git timestamp of files in a repository?
  • How to deal with other teams working directly in the production environment?
  • If git only records a “snapshot” of your files, then how does it undo a change?
  • Rollback to Previous Commit - Github for MAC (a revert is already in progress)
  • Set up a working copy under both Git and Svn version control
  • Git log output to XML, JSON, or YAML?
  • Import part of a SVN repository into an existing Git repo
  • One Solution collect form web for “Merge disjoint branches with git”

    It sounds like git-graft may help. Basically it allows you to manually stitch history.

    Here are couple of articles describing details procedure:
    http://bugsquash.blogspot.com/2010/03/stitching-git-histories.html
    http://ben.straubnet.net/post/939181602/git-grafting-repositories

    If you add a graft to make A1 a descendant of D2, git merge may do a passable job merging in the rest of the changes. If there’s substantial difference between A1 and D2, you may first do git merge -s ours A1 to tell git that those differences should be considered merged so they would not get in the way when you do git merge HEAD_FORK

    Actually, with git merge -s ours A1 you may not need any grafts at all as that fake merge will join the histories of two branches, though not at the exact point in history. Should not make much of a difference considering that there were no other merges across branches.

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