Introduction
I merged multiple Github repositories around one of my projects into a single one for the sake of integration this afternoon.
This post shows several ways to carry it out using local clones.
One of them is that I actually adopted and the others are perhaps good to know for some future :)
Environment
Version Control: Git 2.21.0
Overview
Here is a brief concept:
"repo1" as dest <----merge---- "repo2" as src
Also, here is an example directory overview in this tutorial:
%owner-dir%/
|
+--repo1/ # as dest
| |
| +--file1
| +--common-dir/
| | |
| | +--fileX
| |
| +--dir1/
| |
| +--...
|
+--repo2/ # as src
|
+--file2
+--common-dir/
| |
| +--fileY
|
+--dir2/
|
+--...
Tutorial
First, git clone
the dest repository:
git clone repo1
Let's go into the directory:
cd %owner-dir%/repo1
Then, on the whole, there are just 4 steps to carry it out:
#1. Add the src repository as a new remote
#1-1. Case of using url to specify the location of the src repository
git remote add repo2 git@github.com:%owner-dir%/repo2
# or
git remote add repo2 https://.../%owner-dir%/repo2
#1-2. Case of using path; For example, doing after `git clone repo2 %owner-dir%`
git remote add repo2 %owner-dir%/repo2
#2. Fetch the contents of the src repository
git fetch repo2
#3. Merge them
### Here choose an operation from below. ###
#4. Push the changes
git push origin master
Operations
They are options for "#3. Merge them" above.
I think 1)-2) are basic and the others, 3)-4), are optional.
Prefaces
With Git 2.9.0 and later, git merge
command for a different repository requires --allow-unrelated-histories
option in order to avoid fatal: refusing to merge unrelated histories
error.
The commit history in the src repository is preserved except 4).
1) Repository Merging
git merge repo2/master --allow-unrelated-histories
All files and directories of repo2 are added.
The Result:
repo1/
|
+--file1
+--file2 (+)
+--dir1/
+--common-dir/
| |
| +--fileX
| +--fileY (+)
|
+--dir2/ (+)
2) Subtree Merging
git merge -s subtree repo2/master --allow-unrelated-histories
Using this method, the subdirectories whose names are equal to those of the dest repo's and the files in the root directory are added.
Therefore, in this case, added are just 2 files, fileY
in common-dir
directory and file2
file in the root directory.
The Result:
repo1
|
+--file1
+--file2 (+)
+--dir1/
+--common-dir/
|
+--fileX
+--fileY (+)
3) Subtree Merging With Specifying A Subdirectory
git merge -X<option>
made me confused...
3)-1 Specifying the subdirectory which both the dest repo and the src one have
git merge -X subtree=common-dir repo2/master --allow-unrelated-histories
The files in the root directory and those in the specified subdirectory are added.
The Result:
repo1
|
+--file1
+--file2 (+)
+--dir1/
+--common-dir/
|
+--fileX
+--fileY (+)
3)-2 Specifying the subdirectory which only the src repo has
git merge -X subtree=dir2 repo2/master --allow-unrelated-histories
Just the files in the root directory are added.
The Result:
repo1
|
+--file1
+--file2 (+)
+--dir1/
+--common-dir/
|
+--fileX
3)-3 Specifying the subdirectory which only the dest repo has
git merge -X subtree=dir1 repo2/master --allow-unrelated-histories
The directory named as the specified one is created, and then all of the files and the directories in the src repo are added to it.
The Result:
repo1
|
+--file1
+--dir1/
| |
| +...
| +--file2 (+)
| +--common-dir/ (+)
| | |
| | +--fileY (+)
| |
| +--dir2/ (+)
|
+--common-dir/
|
+--fileX
4) Merging As A New Subdirectory
git read-tree --prefix=%new-subdir%/ repo2/master
git checkout -- .
git add .
git commit -m "commit messages"
The original commit history of the src repo isn't inherited.
The Result:
repo1
|
+--file1
+--dir1/
+--common-dir/
| |
| +--fileX
|
+--%new-subdir% (+)
|
+--file2 (+)
+--common-dir/ (+)
| |
| +--fileY (+)
|
+--dir2/ (+)
In Closing
For the information, these are official documents about the Git commands and strategies above:
Command | URL |
---|---|
git clone |
https://git-scm.com/docs/git-clone |
git remote |
https://git-scm.com/docs/git-remote |
git fetch |
https://git-scm.com/docs/git-fetch |
git merge |
https://git-scm.com/docs/git-merge |
Merge Strategies | https://git-scm.com/docs/merge-strategies |
git push |
https://git-scm.com/docs/git-push |
Thank you for your reading :)
Top comments (4)
I wouldn't bother with cloning both. Clone the first and add the second as a remote, you basically do that in your second step.
Jesse, thank you so much for your kind feedback.
I understood I had had not to clone the second in order to just merge it.
I have updated my post and made my post simpler thanks to you :)
Thank you for your post. I was able to merge 2 repos and set it as new subdirectory. Cheers!
Thank you for your giving me a good news.
I'm happy to know your merging was a success.
I remember I was really confused when I was studying about merging git repos... 🤯
Cheers 😄