GregariousJB
GregariousJB

Reputation: 169

Git Merge two repositories that are years apart with thousands of conflicts

Repository A: The old fork we're working on now, but with hundreds of recent commits based on 3-year-old code from B. The history is long gone - it only goes back a few months when the repository was first uploaded to Github.

Repository B: The new, current one we don't have access to. Years of history. Would like to keep updated with it's Master branch when finished.

At some point ~3 years ago, repository A was a fork of B and then never kept up-to-date with B. We'd like to change that. We want to be Repository B with all of our changes from A.

The pseudocode of what I think needs to happen:

  1. Clone B into a new project with a [Master] branch.
  2. Make an [Old] branch containing all of A.
  3. Merge [Old] branch into [Master] branch and fix thousands of conflicts (How would we keep history from A?)
  4. Set up an Upstream remote for Repo B in order to keep up-to-date from now on.

I'm hoping for some advice, clarification, and/or a translation of the above pseudocode and how it might work.

Thanks!

Upvotes: 1

Views: 267

Answers (2)

Flo
Flo

Reputation: 2778

You might end up with an import similar to the situation in How to import existing Git repository into another?.

Sounds to me like you want to to something like Jörg suggests in his answer (https://stackoverflow.com/a/1684435/47392) which is actually based on Linus Torvald's "Coolest Merge EVER".

Upvotes: 1

chepner
chepner

Reputation: 531075

Conceptually, what you want to do is quite simple; the only complicating factor is the sheer number of expected conflicts. One thing you can do to mitigate that is to try merging older commits from B into A first. Say that after you git clone B Blocal, you have something like this:

*---......-----*  A/master

*---......-----*  Blocal/master

Instead of trying to merge B/master into A/master all in one go, merge in small chunks.

git remote add Blocal
git fetch
git merge  <some old commit in Blocal/master>

which, after fixing potentially many fewer conflicts, you'll have

           M1
*--...---*-* A/master
          /
*--....--*--...........................--* Blocal/master

where M1 here (and Mi in general below`) is a merge commit.

Then, repeat with a slightly newer commit in Blocal/master.

           M1         M2
*--...---*-*--------*-* A/master
          /          /
*--....--*--......--*--.....................--* Blocal/master

Keep this up, with a chuck of Blocal/master at a time, until you can finally run

git merge Blocal/master

to get something like

           M1         M2       M3          Mn
*--...---*-*--------*-*--..--*-*--.....--*-* A/master
          /          /        /           /
*--....--*--......--*--................--* Blocal/master

This way, you don't have to deal with all the merge conflicts at once. You may be able to, by examining Blocal/master' history, find good places to do merges that result in fewer merge conflicts.

Once you've completed the merge, you can set A/master to track the real B instead of your local clone.

git branch --track B/master

Upvotes: 1

Related Questions