简体   繁体   中英

git merge two repositories into a new one, one should be a branch

I want to bring to repositories together, but the second repository should go into a branch

A - B - C - D -  E -  F - G - H Repo1

           A1 - B1 - C1 Repo2

Crete new repo reponew

git init reponew

Add a remote for and fetch the old repo Repo1

git remote add -f Repo1 ..\..\output\Repo1

Merge the files from Repo1/master into new/master

git merge Repo1/master --allow-unrelated-histories

The new repository reponew looks like:

A - B - C - D -  E -  F - G - H master

Now I've created a new branch on specific commit and checkout

git branch branchX 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74
git checkout branchX

Add a remote for and fetch the old repo Repo1

git remote add -f Repo2 ..\..\output\Repo2

Merge the files from Repo1/master into new/master

git merge -Xtheirs Repo2/master --allow-unrelated-histories

And now the new repository repnew looks like this:

                 A1 - B1 - C1 branchX
                                     \
A - B - C  - - - - - - - - - - - - - -
          \
           D - E - - - - - F - G - H master

It looks like that this is caused by the merge request which has a merge date of now

But I owuld like that it look like this:

A - B - C - D - E - - - - - F - G - H master
          \
            - - - A1 - B1 - C1 branchX

The main way to "move" commits AFTER an existing history is to use rebase . Merge can only add a new commit with both histories as parents.
But rebase will not really move the commist but replay them after the specified onto . So, if there is still a reference (branch or tag) on the old commits, they will stay available in the whole commit history.

In your case you want to rebase the history of Repo2/master onto the commit C .

So the solution is:

git branch branchX --no-track Repo2/master
git rebase -Xtheirs 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74 branchX

You should get the result you want.


Suggested by @torek, there is also filter-branch . filter-branch allows you to rewrite a commit history by applying a filter on each rewritten commit. It's mainly used to remove wrongly committed sensitive data (such as password), to remove large files from history, or to change the root folder of a repository. The advantage of filter-branch is that it will also move the tags.
It will also filter commits with empty message.

With filter-branch , there is a --parent-filter that allow you to change the parent(s) of a commit while filtering.
It will filter all the references listed, so to move tags, we have to list all tags in current branchX : git tag --merged branchX , then filter them as-is with --tag-name-filter cat .

So the command will be:

git branch branchX --no-track Repo2/master
git filter-branch \
    --parent-filter 'test $GIT_COMMIT = <FULL-commit-id-of-A1> && echo "-p 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74" || cat' \
    --tag-name-filter cat \
    -- branchX $(git tag --merged branchX)

Then you will have the rewritten history, but still the old one available with references prefixed by refs/original/ .

If it's OK, you can remove the original references ( rm -rf .git/refs/original/ ), otherwise you can restore them ( cp -r .git/refs/original/refs .git && rm -rf .git/refs/original/ ).

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