外部のgitリポジトリを自前のRedmineのリポジトリ管理に追加する方法

![sync_git_repos.png](https://qiita-image-store.s3.amazonaws.com/0/282332/7aeb9e0d-821b-4b43-6fe2-0964592516dd.png)
Redmineのリポジトリ管理におけるリポジトリパスにはlocalhost上のパスしか設定できないため、リモートリポジトリが外部サーバにある場合は自サーバ上にクローンしなければならないが、二重管理は手間なのでこれを同期させることで、データベースでいうレプリケーション構成のスレーブ参照のような設定とします。

図でいう、左上が本来のリモートリポジトリです。上述のレプリケーションの例でいうマスタに相当します。左下は通常の開発におけるローカルリポジトリ。
一方、右上には別サーバ（Redmineのインストールしてあるサーバ）に同期されたリモートリポジトリです。例でいうスレーブに相当します。今回の記事の主役です。右下にはそこから取得したリポジトリがRedmineから常に最新常態で確認できるようになります。

ここでは便宜的に、左上のリモートリポジトリのサーバーをmaster.com、右上のリモートリポジトリのサーバーをslave.comと称します。
サーバーの操作アカウントは仮にreposとします（もちろんそれぞれのサーバーで異なっても構いません）。それぞれ実際のものに読み替えてください。

では構築例です。

### 1. SSH鍵ペアの用意
* master.com⇒slave.comの鍵
* slave.com⇒master.comの鍵

のふたつを用意しておきます。
なぜふたつ必要になるのかは追って説明します。
なお、同期を双方向のSSHプロトコルを介した自動化処理で実現する都合上、いずれも秘密鍵はパスフレーズなしで作成してください。

### 2. repos@slave.com
master.comへのSSH接続を許可するため、秘密鍵を設置します。

```
vi ~/.ssh/master.com.ppk
	slave.com⇒master.comの秘密鍵

chmod 0600 ~/.ssh/master.com.ppk
```

SSH接続をおこなうために必要な接続先ホストの固有な接続情報を定義します。

```
vi ~/.ssh/config
	host master.com
    user repos
    identityfile ~/.ssh/master.com.ppk

chmod 0600 ~/.ssh/config
```

master.comからSSH接続を許可するため、公開鍵を設置します。

```
vi ~/.ssh/authorized_keys
	master.com⇒slave.comの公開鍵

chmod 0600 ~/.ssh/authorized_keys
```

ここで一度手動でSSHログインをおこない、初回known_hostsへの登録時のプロンプトを通しておき次回以降は暗黙ログインができるようにしておきます。

```
ssh master.com
```

### 3. repos@slave.com
slave.comへのSSH接続を許可するため、秘密鍵を設置します。

```
vi ~/.ssh/slave.com.ppk
	master.com⇒slave.comの秘密鍵

chmod 0600 ~/.ssh/slave.com.ppk
```

上記秘密鍵を使った鍵認証方式でgitを操作するために読み込ませるスクリプトを用意します。

```
vi ~/.ssh/slave.com.sh
	#!/bin/sh
	exec ssh -o IdentityFile=~/.ssh/slave.com.ppk "$@"

chmod 0700 ~/.ssh/slave.com.ppk
```

上記スクリプトを自動で読み込ませる設定を追加します。

```
vi ~/.bashrc
	GIT_SSH=~/.ssh/slave.com.sh

. ~/.bashrc
```

SSH接続をおこなうために必要な接続先ホストの固有な接続情報を定義します。

```
vi ~/.ssh/config
	host slave.com
    user repos
    identityfile ~/.ssh/slave.com.ppk

chmod 0600 ~/.ssh/config

```

slave.comからSSH接続を許可するため、公開鍵を設置します。

```
vi ~/.ssh/authorized_keys
	slave.com⇒master.comの公開鍵

chmod 0600 ~/.ssh/authorized_keys
```

ここで一度手動でSSHログインをおこない、初回known_hostsへの登録時のプロンプトを通しておき次回以降は暗黙ログインができるようにしておきます

```
ssh slave.com
```

slave.com側にリモートリポジトリのクローンをつくっておきます。

```
mkdir ~/{slave.comのベアレポジトリの配置するディレクトリ}/
git clone --bare ssh://repos@master.com:22/home/repos/{master.comのベアレポジトリのパス}/
```

### 4. repos@slave.com
master.comのリモートリポジトリにpushされたら、hookスクリプトを通じてslave.comのリモートリポジトリからfetchさせることで同期できる設定をおこないます。

```
vi ~/{master.comのベアレポジトリのパス}/hooks/post-receive
	#!/bin/sh
	ssh -i ~/.ssh/slave.com.ppk repos@slave.com "cd ~/{slave.comのベアレポジトリのパス}/ && git fetch origin 'refs/heads/*:refs/heads/*'"

chmod 0770 ~/{master.comのベアレポジトリのパス}/hooks/post-receive
```

(パーミッションは環境にあわせて読み替えてください)

---

以上です。
これでslave.comのリモートリポジトリはmaster.comへのpushをトリガーに更新情報が同期され、master.comはそのままで、slave.com側のRedmineは最新のリポジトリ情報を参照することができるようになります。

4.がこの設定の要の部分なので、もう少し説明しますと、
まず、masterへのpushで自動実行されるpost-receiveで、slave.comにSSHログインします。この方向で「1. SSH鍵ペアの用意」で作成した「master.com⇒slave.comの鍵」を利用します。
次にログインしたslave.comから再びmaster.com側にSSH経由でgit fetchをおこないます。この方向で「1. SSH鍵ペアの用意」で作成した「slave.com⇒master.comの鍵」を利用します。
ベアリポジトリではgit pullが使えないため、git fetchでブランチ情報を更新するようにしています。

冒頭の図の左下にあたる、ローカルリポジトリからgit pushしてみてください。
すぐにRedmine側でもその更新内容が、画面から確認できるようになっているかと思います。

slave.com側のpost-receiveでも同様な設定を記述することで、双方向のデュアルマスタのような構成にもできるのではないかと思います。