最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

git merge - Multiple conflicts when merging two Git repositories with similar structurecontent - Stack Overflow

programmeradmin0浏览0评论

I need to merge two Git repos, Repo1 and Repo2, into a new single repository MonoRepo. The two repos have almost identical folder structures, and many files are very similar or even the same between the repos (the ultimate goal here is to unify and de-duplicate code). If that matters, both were originally created as branches in SVN, with Repo2 initially a copy of Repo1.

To merge them keeping the commit history, I am following 2 examples: example 1 and example 2.

The basic steps I follow are:

  1. Prepare Repo1 and Repo2 by creating top-level folders ("Repo1" and "Repo2", respectively) and moving everything into them with git mv. This ensures that the repos have parallel folder structures without any overlap. Thus, Repo1's folder structure is transformed from:

    dir1/
        file1
    dir2/
        file2
    ...
    

    to:

    Repo1/
        dir1/
            file1
        dir2/
            file2
        ...
    

    and similarly Repo2 has "Repo2" as the top folder.

  2. Create empty MonoRepo

  3. Bring Repo1 and Repo2 in as remotes:

    git remote add -f Repo1 ../Repo1
    git remote add -f Repo2 ../Repo2
    
  4. Merge them in using the --allow-unrelated-histories flag:

    git merge Repo1/main --allow-unrelated-histories
    git merge Repo2/main --allow-unrelated-histories
    

The problem is that merging in Repo2 creates a ton of rename/delete, modify/delete and rename/rename conflicts, for example:

    CONFLICT (rename/rename): dir1/file1 renamed to Repo1/dir1/file1 in HEAD and to Repo2/dir1/file1 in Repo2/main.

Naively, I thought that since the folder structures of Repo1 and Repo2 are strictly non-overlapping, there should be no conflicts. However, it seems Git is keeping track of directory renaming, or is otherwise attempting to match directories that seem to have been renamed -- git merge output starts with:

    Performing inexact rename detection: 100% (1037700/1037700), done.

I am guessing this matching is particularly problematic in my case: the content of the repos is so similar that Git may think that many parts of Repo2 have been renamed from Repo1.

Based on a post "Renaming and Deep Directory Hierarchies in Git" I have tried 2 things to overcome the conflicts:

  1. Set the merge.directoryRenames setting from default ("conflict") to "true" which would seem to allow to "just have such files moved to the new directory" with git config --local merge.directoryRenames true

  2. Create an empty top-level "Repo1" folder in the Repo2 repo, so that Git does not think that "Repo2" is a rename of "Repo1":

    Repo1/
        .gitkeep
    Repo2/
        dir1/
            file1
        dir2/
            file2
        ...
    

Neither of these workarounds worked -- I am still getting hundreds of CONFLICT messages.

Any suggestions for this seemingly straightforward merge of two repos with parallel folder structures and similar content?

Thank you

I need to merge two Git repos, Repo1 and Repo2, into a new single repository MonoRepo. The two repos have almost identical folder structures, and many files are very similar or even the same between the repos (the ultimate goal here is to unify and de-duplicate code). If that matters, both were originally created as branches in SVN, with Repo2 initially a copy of Repo1.

To merge them keeping the commit history, I am following 2 examples: example 1 and example 2.

The basic steps I follow are:

  1. Prepare Repo1 and Repo2 by creating top-level folders ("Repo1" and "Repo2", respectively) and moving everything into them with git mv. This ensures that the repos have parallel folder structures without any overlap. Thus, Repo1's folder structure is transformed from:

    dir1/
        file1
    dir2/
        file2
    ...
    

    to:

    Repo1/
        dir1/
            file1
        dir2/
            file2
        ...
    

    and similarly Repo2 has "Repo2" as the top folder.

  2. Create empty MonoRepo

  3. Bring Repo1 and Repo2 in as remotes:

    git remote add -f Repo1 ../Repo1
    git remote add -f Repo2 ../Repo2
    
  4. Merge them in using the --allow-unrelated-histories flag:

    git merge Repo1/main --allow-unrelated-histories
    git merge Repo2/main --allow-unrelated-histories
    

The problem is that merging in Repo2 creates a ton of rename/delete, modify/delete and rename/rename conflicts, for example:

    CONFLICT (rename/rename): dir1/file1 renamed to Repo1/dir1/file1 in HEAD and to Repo2/dir1/file1 in Repo2/main.

Naively, I thought that since the folder structures of Repo1 and Repo2 are strictly non-overlapping, there should be no conflicts. However, it seems Git is keeping track of directory renaming, or is otherwise attempting to match directories that seem to have been renamed -- git merge output starts with:

    Performing inexact rename detection: 100% (1037700/1037700), done.

I am guessing this matching is particularly problematic in my case: the content of the repos is so similar that Git may think that many parts of Repo2 have been renamed from Repo1.

Based on a post "Renaming and Deep Directory Hierarchies in Git" I have tried 2 things to overcome the conflicts:

  1. Set the merge.directoryRenames setting from default ("conflict") to "true" which would seem to allow to "just have such files moved to the new directory" with git config --local merge.directoryRenames true

  2. Create an empty top-level "Repo1" folder in the Repo2 repo, so that Git does not think that "Repo2" is a rename of "Repo1":

    Repo1/
        .gitkeep
    Repo2/
        dir1/
            file1
        dir2/
            file2
        ...
    

Neither of these workarounds worked -- I am still getting hundreds of CONFLICT messages.

Any suggestions for this seemingly straightforward merge of two repos with parallel folder structures and similar content?

Thank you

Share Improve this question edited Feb 7 at 8:32 dani-vta 6,9207 gold badges49 silver badges65 bronze badges asked Feb 6 at 17:35 user2690051user2690051 1751 gold badge1 silver badge9 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

If your goal is to bring the history of two repositories (I assume their master branch) into a third new repo, you could use a different approach that relies on merging with the -X subtree=<path> option. This flag allows you to prefix or strip a subfolder to make the trees match.

In your case, you could enter:

# create repository monorepo
mkdir monorepo
cd monorepo
git init

# create mock files to track and inlcude the subfolder paths in the repo.
# This step step is important to let subtree accept the paths.
mkdir repo1
mkdir repo2
echo "readme repo1" >> repo1/README.md
echo "readme repo2" >> repo2/README.md
git add .
git commit -m "init commit to include repo1 and repo2 paths in the repo"

# add remote for repo1 and fetch its master branch
git remote add origin_repo1 <repo1>
git fetch origin_repo1 master

# add remote for repo2 and fetch its master branch
git remote add origin_repo2 <repo2>
git fetch origin_repo2 master

# merging repo1 into the subfolder repo1
git merge --allow-unrelated-histories -s ort -X subtree="repo1/" origin_repo1/master

# merging repo2 into the subfolder repo2
git merge --allow-unrelated-histories -s ort -X subtree="repo2/" origin_repo2/master
发布评论

评论列表(0)

  1. 暂无评论