How do you merge two Git repositories?

后端 未结 23 3245
耶瑟儿~
耶瑟儿~ 2020-11-21 05:45

Consider the following scenario:

I have developed a small experimental project A in its own Git repo. It has now matured, and I\'d like A to be part of larger projec

23条回答
  •  渐次进展
    2020-11-21 05:53

    If you want to put the files from a branch in repo B in a subtree of repo A and also preserve the history, keep reading. (In the example below, I am assuming that we want repo B's master branch merged into repo A's master branch.)

    In repo A, first do the following to make repo B available:

    git remote add B ../B # Add repo B as a new remote.
    git fetch B
    

    Now we create a brand new branch (with only one commit) in repo A that we call new_b_root. The resulting commit will have the files that were committed in the first commit of repo B's master branch but put in a subdirectory called path/to/b-files/.

    git checkout --orphan new_b_root master
    git rm -rf . # Remove all files.
    git cherry-pick -n `git rev-list --max-parents=0 B/master`
    mkdir -p path/to/b-files
    git mv README path/to/b-files/
    git commit --date="$(git log --format='%ai' $(git rev-list --max-parents=0 B/master))"
    

    Explanation: The --orphan option to the checkout command checks out the files from A's master branch but doesn't create any commit. We could have selected any commit because next we clear out all the files anyway. Then, without committing yet (-n), we cherry-pick the first commit from B's master branch. (The cherry-pick preserves the original commit message which a straight checkout doesn't seem to do.) Then we create the subtree where we want to put all files from repo B. We then have to move all files that were introduced in the cherry-pick to the subtree. In the example above, there's only a README file to move. Then we commit our B-repo root commit, and, at the same time, we also preserve the timestamp of the original commit.

    Now, we'll create a new B/master branch on top of the newly created new_b_root. We call the new branch b:

    git checkout -b b B/master
    git rebase -s recursive -Xsubtree=path/to/b-files/ new_b_root
    

    Now, we merge our b branch into A/master:

    git checkout master
    git merge --allow-unrelated-histories --no-commit b
    git commit -m 'Merge repo B into repo A.'
    

    Finally, you can remove the B remote and temporary branches:

    git remote remove B
    git branch -D new_b_root b
    

    The final graph will have a structure like this:

提交回复
热议问题