Git: How To Merge Repositories
Tags: git, repository, cli, tips
Published: 2019-04-16 16:01:38

---
title: Git: How To Merge Repositories
published: true
description: How to merge multiple git repositories.
tags: git, repository, cli, tips
series: Git tips
---

## Introduction

I merged multiple [Github](https://github.com/) 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](https://git-scm.com/) 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:

```config

%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:

```shell
git clone repo1
```

Let's go into the directory:

```shell
cd %owner-dir%/repo1
```

Then, on the whole, there are just 4 steps to carry it out:

```shell
#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

```shell
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

```shell
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

```shell
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

```shell
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

```shell
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

```shell
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 :)