Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Merging git repositories, putting one of them into a subdirectory

For this you need git-filter-repo installed (filter-branch is discouraged).

cd a
git filter-repo --to-subdirectory-filter a
cd ..
cd b
git remote add -f a ../a
git merge --allow-unrelated-histories a/master
git remote remove a
git remote add -f a ../a

being equivalent to:

git remote add a ../a
git fetch a

An example of merging 2 big repositories, putting one of them into a subdirectory: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731

How do you merge two Git repositories?
Merge two Git repositories without breaking file history
Merge bundler into rubygems repo
Understanding Git Filter-branch and the Git Storage Model
Integrating a submodule into the parent repository

#!/bin/sh
set -eux
mkcommit() {
local p=$1
touch "$p"
git add .
git commit -m "$p"
}
rm -rf sr sr2 r
(mkdir sr
cd sr
git init
mkcommit sr1
mkdir srd1
mkcommit srd1/sr2
git log --oneline --graph --decorate --all
git ls-files -s
)
git clone sr sr2
(cd sr2
git filter-repo --to-subdirectory-filter sr
git log --oneline --graph --decorate --all
git ls-files -s
git log -p --name-status --oneline
)
(mkdir r
cd r
git init
mkcommit r1
mkdir rd1
mkcommit rd1/r2
git log --oneline --graph --decorate --all
git ls-files -s
git remote add -f sr ../sr2
git merge --allow-unrelated-histories sr/master
git remote remove sr
git log --oneline --graph --decorate --all
git ls-files -s
git log -p --name-status --oneline
)
$ ./1.sh
+ rm -rf sr sr2 r
+ mkdir sr
+ cd sr
+ git init
Initialized empty Git repository in /home/yuri/_/git-filter-branch/sr/.git/
+ mkcommit sr1
+ local p=sr1
+ touch sr1
+ git add .
+ git commit -m sr1
[master (root-commit) 80775da] sr1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 sr1
+ mkdir srd1
+ mkcommit srd1/sr2
+ local p=srd1/sr2
+ touch srd1/sr2
+ git add .
+ git commit -m srd1/sr2
[master 5e600a4] srd1/sr2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 srd1/sr2
+ git log --oneline --graph --decorate --all
* 5e600a4 (HEAD -> master) srd1/sr2
* 80775da sr1
+ git ls-files -s
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sr1
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 srd1/sr2
+ git clone sr sr2
Cloning into 'sr2'...
done.
+ cd sr2
+ git filter-repo --to-subdirectory-filter sr
Parsed 2 commitsHEAD is now at ed5b46d srd1/sr2
New history written in 0.04 seconds; now repacking/cleaning...
Repacking your repo and cleaning out old unneeded objects
Completely finished after 0.07 seconds.
+ git log --oneline --graph --decorate --all
* ed5b46d (HEAD -> master) srd1/sr2
* a2c2449 sr1
+ git ls-files -s
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sr/sr1
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sr/srd1/sr2
+ git log -p --name-status --oneline
ed5b46d srd1/sr2
A sr/srd1/sr2
a2c2449 sr1
A sr/sr1
+ mkdir r
+ cd r
+ git init
Initialized empty Git repository in /home/yuri/_/git-filter-branch/r/.git/
+ mkcommit r1
+ local p=r1
+ touch r1
+ git add .
+ git commit -m r1
[master (root-commit) 5e6aaa3] r1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 r1
+ mkdir rd1
+ mkcommit rd1/r2
+ local p=rd1/r2
+ touch rd1/r2
+ git add .
+ git commit -m rd1/r2
[master b3768e7] rd1/r2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 rd1/r2
+ git log --oneline --graph --decorate --all
* b3768e7 (HEAD -> master) rd1/r2
* 5e6aaa3 r1
+ git ls-files -s
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 r1
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 rd1/r2
+ git remote add -f sr ../sr2
Updating sr
From ../sr2
* [new branch] master -> sr/master
+ git merge --allow-unrelated-histories sr/master
Merge made by the 'recursive' strategy.
sr/sr1 | 0
sr/srd1/sr2 | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 sr/sr1
create mode 100644 sr/srd1/sr2
+ git remote remove sr
+ git log --oneline --graph --decorate --all
* 148575f (HEAD -> master) Merge remote-tracking branch 'sr/master'
|\
| * ed5b46d srd1/sr2
| * a2c2449 sr1
* b3768e7 rd1/r2
* 5e6aaa3 r1
+ git ls-files -s
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 r1
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 rd1/r2
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sr/sr1
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sr/srd1/sr2
+ git log -p --name-status --oneline
148575f Merge remote-tracking branch 'sr/master'
b3768e7 rd1/r2
A rd1/r2
ed5b46d srd1/sr2
A sr/srd1/sr2
5e6aaa3 r1
A r1
a2c2449 sr1
A sr/sr1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment