Gitでコードを共有するのにリモートレポジトリを作成したいがGithubへのアクセスや社内のGitlabサーバはない、そんなときはふつうのLinuxマシンにベアレポジトリを作ってリモートレポジトリにしてしまいましょう。
レポジトリの作成手順
はじめに
ソースファイル共有をするだけならもちろんftpやsamba、rsyncを使ってもいいのですが、Gitならではの利点があります。
- バージョン管理ができる
- (特にWindows向けに)改行コードの違いを吸収。Gitの設定で、WindowsではCR+LF、LinuxではLFへ自動的に変換してくれるのでユーザは意識する必要がない
- ポートはSSHさえ開いていれば大丈夫
作成にあたっては、ここのサイトを参考にさせて頂きました。
やっているのは、ノンベアレポジトリからベアレポジトリをクローンし、ベアレポジトリをリモートレポジトリとして共有させる、という仕掛けを作ることです。
複数のコマンドを打たなければならず、やや複雑で間違えやすいので、ここではAnsibleを使って自動化することにしました。リモートレポジトリにしたいLinuxサーバ上でAnsibleを動かして設定していきます。
ベアではなくノンベアレポジトリをリモートレポジトリにすることも、不可能ではありませんが推奨されていません。簡単に壊せるからでしょうかね。
Ansibleにはレポジトリを管理するgitモジュールがありますが、やりたい使い方が違うのでここではすべてshellモジュールで処理しています。
下準備
以下リモートレポジトリを作成する予定の、サーバ側での作業です。
前提条件となるSSH(OpenSSH server)、Ansible、Gitをインストールしておきます。以下はCentOSでの例です。
また、既存のものを使い回したくない場合には、別途専用のユーザを作成しておいて下さい。
1 2 3 4 5 6 7 8 9 | $ sudo yum install git $ sudo yum install epel-release $ sudo yum install ansible # 動作確認 $ ansible --version ansible 2.3.1.0 config file = /etc/ansible/ansible.cfg configured module search path = Default w/o overrides python version = 2.7.5 (default, Nov 6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] |
Ansibleで実行するため、後半に掲載するPlaybook一式をコピーするなどして作成しておいて下さい。
レポジトリ管理フォルダの作成
Gitレポジトリで利用する予定のユーザでログインします。
localhost.yml
に所望の設定を記載したあと、setup.yml
で記述したPlaybookを実行します。
Playbook一式は長いので後でまとめて記載しますが、ここでは動作を解説しておきます。
1 | $ ansible-playbook setup.yml |
このPlaybookで設定しているのは、レポジトリを配置するための管理ディレクトリの作成です。
パスはどこでもいいのですが、ここでは例としてrepos
という名前でホームディレクトリの直下にディレクトリを作成します。後ほど、各レポジトリ用のサブディレクトリをこのディレクトリの直下に作る予定です。
ローカルレポジトリを作成するGitユーザがアクセスできるようパーミッションを設定しておきます。
レポジトリの作成
前のセクションで作成した管理ディレクトリの下に、レポジトリ用のディレクトリを作ります。レポジトリが必要になったときに都度実行する想定です。
次のように、up_repo.yml
にオプションrepo_name
を渡すことで、レポジトリ名を指定します。それ以外の設定を指定する必要はありません。
1 | $ ansible-playbook up_repo.yml --extra-vars "repo_name=myproject" |
この例では、管理ディレクトリrepos
の下に、ノンベアレポジトリmyproject.git
とベアレポジトリmyproject.remote.git
の二つのディレクトリが作成されます。
1 2 3 4 | ~/repos : 管理ディレクトリ ├─myproject.remote.git: ベアレポジトリ └─myproject.git: ノンベアレポジトリ └─placeholder: レポジトリに追加された最初のファイル |
リモートレポジトリの利用
ベアレポジトリ(myproject.remote.git
)をクローンすることで、複数のクライアントからベアレポジトリ(=リモートレポジトリ)を共有できます。クライアント側でgit clone
を実行して下さい。
1 | $ git clone ssh://(user name)@(server name or address):(port)/home/(user name)/repos/myproject.remote.git myproject |
レポジトリには最初のファイルとしてplaceholder
ファイルが追加されていますが、実際のコードを作成していく際には削除して構いません。
あとは通常のリモートレポジトリと同様に使えますが、パスワード入力を省略するには、クライアント側でssh-copy-id
コマンドを使ってコピーするか、またはサーバ側の~/.ssh/authorized_keys
ファイルに追記することで公開鍵を登録しておきます。
下記はクライアントでの例です。
1 2 | $ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa $ ssh-copy-id (user name)@(server name or address) -p (port) |
ベアレポジトリのmaster
ブランチへのプッシュをフックして、ノンベアレポジトリが更新されるように設定されています。ノンベアレポジトリには、以降各クライアントからプッシュしたmaster
ブランチと同じソースコードが格納されているはずです。
サーバ側でCI用のテストを動かす、バックアップを作成するなど平文のソースコードが必要な場合はノンベア(からコピーしたもの)を使います。
Playbook一式
Playbookと必要な設定ファイルを、任意のディレクトリに次のような構成として格納しています。
1 2 3 4 5 6 7 8 | (playbook directory) ├─assets │ ├─placeholder: 各レポジトリに最初に追加されるファイル │ └─post-receive: フック作成用シェルスクリプト ├─host_vars │ └─localhost.yml: 設定ファイル ├─setup.yml: レポジトリ管理ディレクトリ作成Playbook └─up_repo.yml: レポジトリ作成Playbook |
管理ディレクトリ作成:setup.yml
管理ディレクトリを作成するPlaybookファイルです。設定ファイル(localhost.yml
)を参照しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 | - name: prepare git repo on localhost hosts: localhost connection: local tasks: # tasks for configuring git - name: initial config for git (user) shell: git config --global user.name {{ git_user }} - name: initial config for git (email) shell: git config --global user.email {{ git_email }} - name: create directory (repository) file: path={{ repo_base_dir }} state=directory mode=755 |
レポジトリ作成:up_repo.yml
各レポジトリを作成するPlaybookファイルです。設定ファイル(localhost.yml
)を参照しているので、前のsetup.yml
ファイル実行時と同じ値になるように注意して下さい。
Playbookの中でrm
コマンドを呼んでいるタスクがありますがレポジトリの重複を防ぐためのものです。トリッキーですが、同じ名前を持つディレクトリがすでに存在した場合、Playbookを停止させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | - name: configure custom repository hosts: localhost connection: local max_fail_percentage: 0 vars: path_to_repo: '{{ repo_base_dir }}/{{ repo_name }}.git' path_to_bare: '{{ repo_base_dir }}/{{ repo_name }}.remote.git' tasks: - stat: path={{ path_to_repo }} register: repo_path - name: check directory exists shell: rm {{ path_to_repo }} when: repo_path.stat.exists # create local nonbare repository - name: create directory (local) file: path={{ path_to_repo }} state=directory mode=755 - name: send placeholder copy: src=assets/placeholder dest='{{ path_to_repo }}/placeholder' - name: modify placeholder lineinfile: >- dest={{ path_to_repo }}/placeholder regexp='repository_name' line='repository_name: {{ repo_name }}' - name: initialize git repository (local) shell: > git init; git add .; git commit -m "initial commit {{ repo_name }}"; args: chdir: '{{ path_to_repo }}' creates: '{{ path_to_repo }}/.git/config' # clone as bare repository - name: create directory (bare) file: path={{ path_to_bare }} state=directory mode=755 - name: git clone as bare repository shell: git clone --bare {{ path_to_repo }} . args: chdir: '{{ path_to_bare }}' # add remote - name: git add remote shell: git remote add origin {{ path_to_bare }} args: chdir: '{{ path_to_repo }}' # configure auto pull - name: configure auto pull from bare to local copy: src='assets/post-receive' dest='{{ path_to_bare }}/hooks/post-receive' mode=755 - name: modify post-receive script lineinfile: >- dest='{{ path_to_bare }}/hooks/post-receive' regexp='change' line='cd {{ path_to_repo }} || exit' |
設定ファイル:localhost.yml
repo_base_dir
に管理ディレクトリを作成する先のパスを記載しておきます。setup.yml
実行時に作成されるので、予め実在するパスである必要はありません。
1 2 3 | git_user: gituser git_email: gituser@domain.net repo_base_dir: ~/repos |
フック用スクリプト:post-receive
ベアレポジトリ側に設定されるスクリプトです。
1 2 3 4 | #!/bin/sh change unset GIT_DIR git pull origin master |
最初のファイル:placeholder
レポジトリが作成される際に最初のファイルとして追加されるファイル。内容は何でも良いのですが、Playbook(up_repo.yml
)内で値を書き換えているので、この記載にしておけば動作が確認できます。
必要に応じて.gitignore
などにしても便利かも知れません。
1 2 | this is a placeholder. remove after actual assets added repository_name: none |