简体   繁体   中英

Git - merge two repositories with common ancestor

Let's say I used to have a repository Z and created two repositories (A and B) based on it.

I made them mutually exclusive. What I mean is files in A should not be in B and viceversa. So, I deleted the some files in A and also files in B.

These two repositories kept growing over time.

Now, due to some management decision, I need them back as a single repository. I tried doing a merge as indicated in How to use the subtree merge strategy , but it gives me too many conflicts and the merge itself was very dirty. I understand this is an uncommon and difficult task.

Have any of you faced the same problem, how did you fix it?

I have my doubts about this being a good idea, but it sounds like it doesn't really matter whether it is or not.

So you had a single repo with, I'll assume, two projects in it. They shared a history, and it seems you need to get back to that state - one master branch with all the files.

You've apparently gotten as far as bringing all the objects into one repo. For example, perhaps you added one repo as a remote of the other, and fetched its master ref; so let's say you have

A -- B -- C -- X1 -- X2 -- X3 <--(master)
           \
            Y1 -- Y2 -- Y3 <--(repoB/master)

You try

git checkout master
git merge repoB/master

and you get conflicts and other messiness, and probably understanding that messiness will help understand what to do instead. The conflicts could be as simple as "file was deleted here and modified there", which is pretty easy to resolve, but other things can be going on as well.

For example, if you were splitting up two projects, then you might have moved a bunch of stuff from what was a project sub-directory up to the work tree root. Or you might have created a file in one repo, with the same path/name as an existing file in the other repo. Or whatever.

So the first thing I would do is to make sure each repo's worktree is laid out as a subset of the combined worktree you want going forward. If it's already the case - ie you didn't move the files around after splitting the repos, there no path/filename that exists in both repos, and the desired worktree is just what you'd get by cd ing to one repo's worktree and cp -R ing the other repo's worktree - then you can skip ahead past this step.

But otherwise, you could

git checkout master

and then mv files as needed so that you have a subset of the desired worktree, and commit. Then

git checkout repoB/master
git checkout -b repoB

and again mv things around as needed and commit.

A -- B -- C -- X1 -- X2 -- X3 -- X <--(master)
           \
            Y1 -- Y2 -- Y3 -- Y <--(repoB)

You could get by without this, but it gives us simpler options for the next step than what we would have otherwise.

Next we probably want to start a merge. We don't want the default merge result, which means we're creating what might be called an "evil" merge; but in my view it's not as bad since the merge would, by default, conflict - so in a sense, there is no default merge result.

Anyway, we want to put git in a "merge-in-progress" state, but its default merge algorithm isn't much use here; so

git checkout master
git merge -s ours --no-commit repob

Now we need to add the files from repob , which will work smoothly because none of them are at the same path as a file we already have.

git checkout repob -- .

Verify that the worktree now looks right. Then

git commit

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM