It turns out that the answer is much simpler if you're simply trying to glue two repositories together and make it look like it was that way all along rather than manage an external dependency. You simply need to add remotes to your old repos, merge them to your new master, move the files and folders to a subdirectory, commit the move, and repeat for all additional repos. Submodules, subtree merges, and fancy rebases are intended to solve a slightly different problem and aren't suitable for what I was trying to do.
Here's an example Powershell script to glue two repositories together:
# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init
# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
git commit --allow-empty -m "Initial dummy commit"
# Add a remote for and fetch the old repo
# (the '--fetch' (or '-f') option will make git immediately fetch commits to the local repo after adding the remote)
git remote add --fetch old_a <OldA repo URL>
# Merge the files from old_a/master into new/master
git merge old_a/master --allow-unrelated-histories
# Move the old_a repo files and folders into a subdirectory so they don't collide with the other repo coming later
mkdir old_a
dir -exclude old_a | foreach { git mv $_.Name old_a }
# Commit the move
git commit -m "Move old_a files into subdir"
# Do the same thing for old_b
git remote add -f old_b <OldB repo URL>
git merge old_b/master --allow-unrelated-histories
mkdir old_b
dir –exclude old_a,old_b | foreach { git mv $_.Name old_b }
git commit -m "Move old_b files into subdir"
Obviously you could instead merge old_b into old_a (which becomes the new combined repo) if you’d rather do that – modify the script to suit.
If you want to bring over in-progress feature branches as well, use this:
# Bring over a feature branch from one of the old repos
git checkout -b feature-in-progress
git merge -s recursive -Xsubtree=old_a old_a/feature-in-progress
That's the only non-obvious part of the process - that's not a subtree merge, but rather an argument to the normal recursive merge that tells Git that we renamed the target and that helps Git line everything up correctly.
I wrote up a slightly more detailed explanation here.
Answer from Eric Lee on Stack OverflowIt turns out that the answer is much simpler if you're simply trying to glue two repositories together and make it look like it was that way all along rather than manage an external dependency. You simply need to add remotes to your old repos, merge them to your new master, move the files and folders to a subdirectory, commit the move, and repeat for all additional repos. Submodules, subtree merges, and fancy rebases are intended to solve a slightly different problem and aren't suitable for what I was trying to do.
Here's an example Powershell script to glue two repositories together:
# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init
# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
git commit --allow-empty -m "Initial dummy commit"
# Add a remote for and fetch the old repo
# (the '--fetch' (or '-f') option will make git immediately fetch commits to the local repo after adding the remote)
git remote add --fetch old_a <OldA repo URL>
# Merge the files from old_a/master into new/master
git merge old_a/master --allow-unrelated-histories
# Move the old_a repo files and folders into a subdirectory so they don't collide with the other repo coming later
mkdir old_a
dir -exclude old_a | foreach { git mv $_.Name old_a }
# Commit the move
git commit -m "Move old_a files into subdir"
# Do the same thing for old_b
git remote add -f old_b <OldB repo URL>
git merge old_b/master --allow-unrelated-histories
mkdir old_b
dir –exclude old_a,old_b | foreach { git mv $_.Name old_b }
git commit -m "Move old_b files into subdir"
Obviously you could instead merge old_b into old_a (which becomes the new combined repo) if you’d rather do that – modify the script to suit.
If you want to bring over in-progress feature branches as well, use this:
# Bring over a feature branch from one of the old repos
git checkout -b feature-in-progress
git merge -s recursive -Xsubtree=old_a old_a/feature-in-progress
That's the only non-obvious part of the process - that's not a subtree merge, but rather an argument to the normal recursive merge that tells Git that we renamed the target and that helps Git line everything up correctly.
I wrote up a slightly more detailed explanation here.
Here's a way that doesn't rewrite any history, so all commit IDs will remain valid. The end-result is that the second repo's files will end up in a subdirectory.
Add the second repo as a remote:
cd firstgitrepo/ git remote add secondrepo username@servername:andsoonMake sure that you've downloaded all of the secondrepo's commits:
git fetch secondrepoCreate a local branch from the second repo's branch:
git branch branchfromsecondrepo secondrepo/masterMove all its files into a subdirectory:
git checkout branchfromsecondrepo mkdir subdir/ git ls-tree -z --name-only HEAD | xargs -0 -I {} git mv {} subdir/ git commit -m "Moved files to subdir/"Merge the second branch into the first repo's master branch:
git checkout master git merge --allow-unrelated-histories branchfromsecondrepo
Your repository will have more than one root commit, but that shouldn't pose a problem.
How can you merge two repositories while keeping all commit and contribution history?
How can I combine three repositories without losing history?
git merge - How to combine two separate unrelated Git repositories into one with single history timeline - Stack Overflow
github - How to merge two git repositories without loosing the history for either repositories - Stack Overflow
Lets say I have projects A, B and C. Each project is currently in its own repository on git, but they are typically updated the same and are versioned the same. I want to combine them into a single repo by grouping B and C under A like so:
A \-> B \-> C
Can I do so without losing history?
I think you do it like this:
- git remote add [repo b]
- git fetch//get the repo b into repo a
- due to you want to keep the history like this: A0-A1-B1-B0-D1-C0-D0-E0-F0-G0-E1-H(from repo B)-HEAD (new repo A) you can first select the A0 as a start point, after that, use git cherry-pick one by one.
Hope this is useful for you.
Br, Tim
I did something similar (merge history from B into A) like this:
- go to your repo A
git fetch <ref to your repo B> master:new-branch-on-A(so, you have copied master branch of B into a new branch 'new-branch-on-A' into your repo A.git checkout new-branch-on-Agit rebase master(you rebase the new-branch-on-A with the master branch)- resolve conflicts if there are any
git checkout mastergit merge new-branch-on-Agit branch -d new-branch-on-A- Done :), your histories are merged. I think all commits from A are before commit from B in the new history (
git rebase -iis your friend if needed).
If both repos are on your machine, for example you have folders
A/.git
A/client-src
B/.git
B/server-src
simply go to one of them:
cd A
and type:
git remote add repo-b ../B
This creates a symbolic link from repo-a to repo-b ("repo-b" is just a symbolic name, you can choose anything you want) and then
git fetch repo-b
will combine the two repos. At this point, you will have both histories in one repository, but still in different branches. Branch "master" (the master of the folder you are in) will contain client code. Branch "repo-b/master" will contain the server code.
Then you only have to merge the two:
git merge repo-b/master --allow-unrelated
After this, you will have in Repo A a combined master branch. If you are sure there is no other meaningful information in Repo B (Tags, other branches), you can discard it and continue working with Repo A. Both histories will be intact.
For completeness, you should finally delete the now useless link from Repo-A to Repo-B:
git remote remove repo-b
Below are the steps
git clone <NEW REPO>
cd <NEW REPO FOLDER>
dir > README.MD --> this step is just to initiate the new repository.
git commit -m "initiate the new repository"
git remote add -f <RANDOM NAME A> <OLD BRANCH A>
git remote add -f <RANDOM NAME B> <OLD BRANCH B>
git pull origin master --allow-unrelated-histories
git push -u origin master
git merge --allow-unrelated <RANDOM NAME A>/master
git merge --allow-unrelated <RANDOM NAME B>/master
git push origin master
I believe this post should be of helpful for others.
Hey all. I've been wondering about this for a while now. I've found a couple ways of doing it creatively, like putting them in separate branches, using git mergetool, using git subtree, etc. but most of the time the solutions are convoluted and involve some sort of sacrifice (namely, the .git data of one of the repos.) I was curious to see if someone else has come up with an easy way of doing it, or if a tool exists for this purpose. It would be nice to be able to click that little "License" checkbox when making GH remotes for my local git repos. Thanks in advance. Cheers!
-ntolb