More than 1 year has passed since last update.

git で手元でバージョン管理してるのにいちいち git-archive で差分を出して
展開して、FTPで持って行って上書きなんてめんどくさいなぁ・・・

コマンドだけででうまくできないものかと思った時に使える技。
SSHが使える場合とFTPのみ使える場合とで2パターン用意しました。

WindowsがメインPCなのでWindowsでも使える手順となります。
使うgitはオーソドックスにmsysgitです。


SSHが使える場合

昨今のレンタルサーバーではSSHを利用できるオプションがあります。

git は ssh:// をリモートリポジトリに設定してやるとSSH経由で操作を行えるのでこいつを使います。
今回はロリポップ!を使った場合を想定して進めます。

リモートリポジトリの準備をする

まずpushするリモートリポジトリを用意します。
SSHでログインし、適当な場所でベアリポジトリを作成してください。
公開する必要はないので公開領域とは別の場所にしておくのがいいでしょう。

ロリポップ!ではルートディレクトリの web 配下が公開領域になるので
そのとなりに git を作成しました。この配下にサイト毎にリポジトリをポコポコ置いていきます。
とりあえず下記を想定しました。

/ (ルートディレクトリ)
┣ web (公開領域)
┃ ┗ example.xyz
┃   ┗ www (www.example.xyz … 本番環境)
┃   ┗ dev (dev.example.xyz … ステージング環境)
┃
┗ git (リポジトリを置く場所)
  ┗ example.xyz

というわけで作りましょう。

# ホームディレクトリに移動
cd ~/

# リポジトリ置き場のディレクトリを作成
mkdir git
cd git

# example.xyz 用のディレクトリを作成
mkdir example.xyz
cd example.xyz

# example.xyz をベアリポジトリとして初期化
git init --bare

これで push 先の準備が出来ました。

post-receive を設定する

ベアリポジトリにはイベントフックの機能があり、具体的には今回
リモートにpushした後に実行して欲しいコマンドを設定しようと思います。
この設定は作成したベアリポジトリの hooks ディレクトリに post-receive を作成することで可能です。

このファイルはサーバーのシステムで実行できればなんでも構いませんが
今回はオーソドックスにシェルスクリプトで書きました。
作成するファイルは下記のように配置します。

/
┗ git
  ┗ example.xyz
    ┗ hooks
      ┗ post-receive (作成するファイル)

hooksの内部には他にもフック処理のサンプルファイルが含まれているので
覗いてみると勉強になります。多分。

post-receive の中身は下記のようにしました

#!/bin/bash

# ステージング環境
cd ~/web/example.xyz/dev
git --git-dir=.git pull origin dev:dev

# 本番環境
cd ~/web/example.xyz/www
git --git-dir=.git pull origin master:master

ステージング環境と本番環境を分けて設定しています。
それぞれのディレクトリに移動して、originからそれぞれのブランチを指定してpullしています。
--git-dir=.git はこれがないとうまく動いてくれないので指定しました。

あとは忘れずに post-receive に実行権限を付与します。

# ファイルと権限を確認
ls -la ~/git/example.xyz/hooks/post-receive

# 実行権限を付ける
chmod -x ~/git/example.xyz/hooks/post-receive

# 実行権限が付いているはず
ls -la ~/git/example.xyz/hooks/post-receive

公開領域の準備をする

post-receive に指定したように公開領域でpullする必要があるので
公開領域のディレクトリもgitリポジトリにする必要があります。
こちらはワーキングディレクトリを公開するファイルとするので
ベアリポジトリにする必要はありません。

サクッと git init で初期化し、リモートを先ほど作成した
ベアリポジトリに設定していきます。

# ステージング環境の公開領域の設定
cd ~/web/example.xyz/dev
git init
git remote add origin ~/git/example.xyz

# 本番環境の公開領域の設定
cd ~/web/example.xyz/www
git init
git remote add origin ~/git/example.xyz

これでpushすると中身を更新するように設定出来ました。

実際にpushしてみる

ローカル側からpushすればサーバーにあるファイルが更新されるはずです。
ローカルのリポジトリのリモート設定にレンタルサーバーの設定を追加します。

ロリポップの場合はユーザー管理画面からSSH接続設定を確認して下さい。

# ロリポップの管理画面から確認できるSSH設定が下記の場合
# アカウント: main.jp-hoge
# サーバー : ssh001.lolipop.jp
# ポート  : 2222

ssh://main.jp-hoge@ssh001.lolipop.jp:2222/~/git/example.xyz

あとは実際に git push してみてください。

自分はpost-recieveで設定したとおり、
dev と master の2つのブランチを用意し git-flow よろしく下記の手順をとっています。

  1. ローカルの dev ブランチであれこれ更新
  2. 適当なタイミングで git push origin dev:dev しステージング環境を更新
  3. ステージング環境で動作に問題がないことを確認
  4. dev ブランチを master にマージ
  5. git push origin master:master して本番環境の更新

備考

SourceTreeではSSH経由でログインする時にちゃんとパスワード認証ダイアログが出たのですが
GitExtentionsを使うときはPuTTY経由だとうまく認証できませんでした。
そういう場合にはOpenSSHを利用してやるとうまくいきました。


FTPは使える場合

SSHが使えるレンタルサーバーはいいもののFTPしか無いとか、
SSHを使えるようにするだけで上位プランにするのはちょっと...という場合もあると思います。
そういった場合には git-ftp が使えます。

git-ftp とは

http://git-ftp.github.io/git-ftp/

gitで管理した内容をftpでアップロードするための拡張コマンド。
これを追加すると git ftp push でサーバーに差分をアップロードできるようになります。

git-ftp の導入

導入時の設定は Git Bash から行います。一度済ませれば大丈夫。
任意のディレクトリでgit-ftpを clone します。

git clone git@github.com:git-ftp/git-ftp.git

そのあとは clone した場所にPATHを通すか、
clone したファイルのうち git-ftp を /bin にシンボリックリンクを設定します。

自分は後者を選択しました。
git-ftpに実行権限があるかも念のため確認しておいてください。

ln -s path/to/git-ftp /bin

ls -la /bin/git-ftp

導入はこれで終わりです。プロンプトで git ftp と叩いて下記のような出力が得られればOKです。

$ git ftp
git-ftp <action> [<options>] <url>

git-ftp の設定

git-ftpの設定はSSHを使う場合と比較してシンプルです。
サーバー側でフックしたり、pullしたりできないのですべてローカルでまかないます。

設定はお馴染み git config から行います。
git ftp を叩きたいリポジトリで下記をそれぞれ設定します。

git config git-ftp.url ftp://<ホスト名>/<公開ディレクトリまでのパス>
git config git-ftp.user <FTPユーザー名>
git config git-ftp.password <FTPパスワード>

git-ftp.url の設定ではセキュリティを考えて、FTPSが利用できる場合には
スキーマを ftp:// でなく ftpes:// を指定して接続するのが望ましいでしょう。

また公開ディレクトリまでのパスはFTPクライアントで接続した時のパスを指定します。
ココで指定したディレクトリにファイルが展開されるようになります。

git-ftp でのリモートの初期化と更新

git-ftp で更新をかける際には初回のみ git ftp init をして
FTPサーバー側の初期化をしてやる必要があります。

実際は今いるブランチの最新のコミットのファイルをアップロードして
.git-ftp.logというファイルをリモートに作成してコミットIDを記録している様子。

# 初期化コマンド
git ftp init

# 進捗が気になる人はこっちで初期化
git ftp init -vv

これでOK。あとはおもむろに git ftp push するとその時点の最新のコミットまでの差分が
FTP経由でサーバーに反映されるようになります。

git ftp push

これでFTPしかなくても安心してgitで更新管理ができるようになりました。
なお注意する点はgit-ftpでアップロードした時には
リポジトリの情報そのものはアップロードされないという点です。

「FTPでリモートリポジトリアップしてるからだぁいじょうぶだぁっはっはーん」などといって
ローカルのリポジトリを安易に消したりしないよう注意しましょう。

GithubBitbucket にpushしておくのも手かと思います。

SSHの時みたいにステージングと本番を分けたい

git-ftpには service といって環境ごとに設定を分けることができる仕組みがあります。
使い方は簡単で git-ftp の設定の時に git config を下記のように設定してやります。

# ステージング環境
git config git-ftp.dev.url ftp://<ホスト名>/<公開ディレクトリまでのパス>
git config git-ftp.dev.user <FTPユーザー名>
git config git-ftp.dev.password <FTPパスワード>

# 本番環境
git config git-ftp.www.url ftp://<ホスト名>/<公開ディレクトリまでのパス>
git config git-ftp.www.user <FTPユーザー名>
git config git-ftp.www.password <FTPパスワード>

git config git-ftp.<任意の文字列>.url とかで指定するといいみたいです。

またこの設定を利用してgit ftp initgit ftp pushするときは下記のようにします。

git ftp init -s dev # ステージング環境の初期化
git ftp init -s www # 本番環境の初期化

git ftp push -s dev # ステージング環境の更新
git ftp push -s www # 本番環境の更新