これまでgitは完全なローカル環境で使うか、Githubを使うかのいずれかでした。簡単なgitの使い方をまとめてそれなりに使っていましたが、プライベートサーバーがあるといいかなと思い始めました。
2種類のリポジトリ
Gitのマニュアルに従って作業しながら理解を進めてゆきます。
リポジトリ…。いまだにちゃんと理解できていないのですが、全ての変更履歴を記録したデータ置場という認識です。この中にあるファイルを更新して都度コミットする。そんな感じ。
これとは別にベアリポジトリというのがあるようです。このリポジトリは作業ディレクトリを持ちません。そしてこれこそがGitサーバーの肝になる(んだと思う)ディレクトリのようです。
作業用のリポジトリとベアリポジトリ。このふたつを区別して認識する必要があります。
Gitサーバーを立てる
このサイトのあるWebサーバーの片隅でGitサーバーを動かします。
と言ってもssh接続設定はできているしgitコマンドもインストール済みなので、特にこれといってインストールしたり設定したりする必要はありません。
ローカルリポジトリを作る
ローカルマシン上で作業用リポジトリを用意します。…特に用意しなくても、これまでローカルで管理していたリポジトリがあればそれを使えばいいんですが。新規に作るならgit initで。
$ mkdir project
$ cd project
$ git init
ローカルにベアリポジトリを作る
これをもとにローカルマシン上にベアリポジトリを作ります。先ほども書いたとおり、作業用リポジトリとは別の、作業ディレクトリを持たないリポジトリです。
これは作業用リポジトリから作られるクローンです。ただし–bareオプションを付けて。これにより作業ディレクトリを除いたコピーが出来上がります。(実際にはそれ以外の設定ファイルやディレクトリも作られる)
$ git clone --bare project project.git
ベアリポジトリ名は拡張子.gitを付けるものらしい。
サーバー上にベアリポジトリをコピーする
ローカル上に出来上がったベアリポジトリをssh接続でサーバー上にコピーします。
このときssh接続のセキュリティ都合、認証鍵やポートの設定をしているため、マニュアルの例に追加してオプション指定が必要になります。
$ scp -i ~/.ssh/id_ed25519 -P 20022 -r project.git user_name@server_address:/home/user_directory/
具体的には-iオプションによる鍵ファイルの指定と、-Pオプションによるポート番号の指定。ただし.ssh/configで設定してあれば省略できます。
これでサーバー上にベアリポジトリがコピーされ、複数マシンからのアクセスが可能になりました。
リモートリポジトリを設定する
ベアリポジトリをサーバーにコピーしただけではローカルリポジトリの参照先は変わりません。このままgit pushしてもローカルにあるベアリポジトリが更新されるだけです。変更内容をサーバーに反映するためにデフォルトのリモートリポジトリoriginの参照先をサーバー上のベアリポジトリに設定します。
$ git remote add origin user_name@server_address:/home/user_directory/project.git
確認結果は以下のとおり。
$ git remote -v
origin server_address:/home/user_directory/project.git (fetch)
origin server_address:/home/user_directory/project.git (push)
以後はcommit後にgit pushするとリモートリポジトリに反映されるようになります。
使ってみる
先ほど作ったベアリポジトリは忘れて、別マシンからサーバー上のデータを使ってみましょう。
ベアリポジトリのコピー時同様、sshの設定を変えているのでマニュアルの記述に対して少し手順の追加があります。
以前作ったsshのconfigファイルを少し手直しします。具体的には接続先サーバーの設定ラベル名にサーバーアドレスを併記します。
# Vultr VPS
Host vultr example.com
HostName example.com
User ssh
Port 20022
IdentityFile /Users/user/.ssh/id_ed25519
そのうえでサーバーのベアリポジトリから作業リポジトリをクローンします。
$ git clone user_name@server_address:/home/user_directory/project.git
これでローカルにprojectの作業リポジトリがコピーされました。
後は今まで通りこのリポジトリに対して作業をし、git pushすればサーバーと同期されます。
hookしてみる
Githubではgit pushするたびにTweetするような設定にしています。これはもともとgitが持っているhookという機能を使っているようです。
ベアリポジトリの中身を覗いてみるとhooksというディレクトリがあり、更にその中にいくつかのファイルがあります。これらはそれぞれのタイミングに応じて実行されるファイル群(ただし.sampleが付いていない場合)です。
$ ll project.git/hooks
total 31
-rwxr-xr-x 1 u0723005 1049089 478 6月 8 12:09 applypatch-msg.sample*
-rwxr-xr-x 1 u0723005 1049089 896 6月 8 12:09 commit-msg.sample*
-rwxr-xr-x 1 u0723005 1049089 189 6月 8 12:09 post-update.sample*
-rwxr-xr-x 1 u0723005 1049089 424 6月 8 12:09 pre-applypatch.sample*
-rwxr-xr-x 1 u0723005 1049089 1642 6月 8 12:09 pre-commit.sample*
-rwxr-xr-x 1 u0723005 1049089 1239 6月 8 12:09 prepare-commit-msg.sample*
-rwxr-xr-x 1 u0723005 1049089 1348 6月 8 12:09 pre-push.sample*
-rwxr-xr-x 1 u0723005 1049089 4951 6月 8 12:09 pre-rebase.sample*
-rwxr-xr-x 1 u0723005 1049089 3610 6月 8 12:09 update.sample*
ここにはありませんが、post-receiveという名前の実行ファイルがある場合、ローカルからgit pushされるとその内容が自動実行されるようになります。
というわけで、今回簡単なhtmlファイルをgitで管理しているので、pushされる度に本番環境に最新のファイルがコピーされるような自動デプロイ用のシェルスクリプトを書いてみました。
#! /bin/sh
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
REPOSITORY='/home/takeru/taipei36'
DOCROOT='/usr/local/www/travel/tour'
TARGET='/taipei36.php'
git -C ${REPOSITORY}/.git pull origin master
cp -p ${REPOSITORY}${TARGET} ${DOCROOT}${TARGET}
ここで注意が必要なのはgitコマンド。-Cオプションで作業リポジトリ内の隠しディレクトリ.gitを指定してやらないとエラーになって作業リポジトリ内のファイルが更新されません。
あとはちまちまとhtmlファイルを更新するだけ。内容を修正するたびに自動的にサイトの内容が更新されるようになりました!