How to consolidate code from two git repositories with same code in branch, but different history?

Viewed 82

I have two projects. One is the original OSS project. The other which we will incorrectly call "fork" is a copy of a branch of the original project.

The code in the fork was imported from a source zip from Github. (I am very much aware of the fact that this is not how you do things, but a team before me did it and I now have to deal with the fall out. I wish I was around when this decision was made to advise against it, but it is what it is and it needs to be fixed properly now).

The problem:

  • The code in the fork contains the code of original project for tag 1.2.0. The code in the fork is in it's master.

  • The fork has modifications that are not part of the original project.

  • As can be expected, the original project has also continued its life and it now has reached version 1.6.0.

I'd like to start off fresh and do the following:

  • (Really) Fork the original project (along with all its history).

  • Create a 1.2.0-modified branch which is based on the original 1.2.0.

  • Fetch the changes from the repository with the modifications and apply them to 1.2.0-modified. (I have tried rebasing, after some manual changes during the merge, I was able to get the code to build).

  • I would now like to know what the best course of action is, if I'd like to move forward and rebase to 1.6.0.

Please, keep in mind that there have been changes two both the original project and the "fork", so I'd like to be able to keep the history from both sides.

What is the proper way to do this?

Obviously, I have added both remotes to the new fork for the modifications and I've fetched them both.

The problem is that after rebasing the changes from the fork's 1.2.0, while I did get it to resolve the conflicts and build properly, when I try re-basing on to 1.6.0, it seems to be re-applying the same fixes all over again, which I believe is because the original branches were not based on 1.2.0-modified.

Is there a smart and easy way around this?

2 Answers

You have this situation (time flows left to right):

--o--2--o--3--o--o     original

       X--o--o--o      fork

If you know that the first commit X in your forked history matches (exactly or mostly) commit 2 (assume it's tagged v1.2.0), you can stitch the histories together with

git replace --graft X v1.2.0

This creates this fake history:

--o--2--o--3--o--o     original
      \
       X--o--o--o      fork

Now you can easily use git rebase to tie your changes to the original history. You get:

--o--2--o--3--o--o     original
                  \
                   o--o--o   fork

Now you can remove the graft with git replace -d (I'm not sure how to use this version, though).


Edit: marked some commit in original with 3 (assume that it is tagged v1.3.0) to address a comment.

The code in the fork contains the code of original project for tag 1.2.0. The code in the fork is in it's master.

If in your "bad fork", the initial commit is indeed exactly the same than the tag 1.2.0 and then AFTER, they started to build on it and create commits, then it should on be too difficult and you only have to do a:

git rebase <hash_of_root_commit> 1.2.0-modified --onto 1.2.0

it will rebase only your commits and you must have no conflicts.

After that, you should have your branch that you could "easily" rebase onto 1.6.0 (with conflicts, I imagine...)

If then have not done the initial commit without their modifications, you will have to play with the git replace --graft feature

Related