FTPアップロードのデプロイからGit pullのデプロイに変更する

タイトルの通り、この時代になって未だにFTPアップロードでデプロイしてるアプリの運用・保守を受け持つことになって2年程度経過してました。。
もちろんソース管理はすぐにGitにしたんですが、既にローンチされて時間も経っているのでデプロイは諦めてました。。

が、ある時、 

*諸事情によりサーバーを新しいネットワークに移行することになりましたー* 

との連絡が！

移行とありますが、実際にはゼロからVMを作り直すということだったんで

*いつやるの？今でしょ！！！！！！(時代とか関係なく本気で心の底から思ったので許して下さい)*

と思いgit pullのデプロイに変えました！

たぶん他にも同じ悩みを抱えてる人はまだまだいるのかなと思ったので今回やったことをまとめてみました。

# 参考にさせて頂いたサイト

Gitはそれなりに経験長いですが、オプションとか全然わかってなかったです。。のでとにかくググりまくって、最終的にこちらのサイトのおかげでなんとかなりました。

[既存ディレクトリにGitリモートリポジトリを適用](http://qiita.com/llhrkll/items/9b252348898d14ff90bf)
[既存のディレクトリ（フォルダ）にgit cloneして上書きしたい](http://blog.dksg.jp/2015/05/git-clone.html)
[初めてGitHubリポジトリにpushしたらrejectedエラーになったときの対応メモ](http://qiita.com/takanatsu/items/fc89de9bd11148da1438)

# 環境

CentOS6.9

# 事前作業

そもそもサーバーにGitが入ってなかったのでGitを入れました。
本記事の趣旨とは関係ないので説明とかは割愛します。
CentOS6.9だったのでこんな感じでインストールしました。

```shell-session
yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
cd /usr/local/src/
wget https://www.kernel.org/pub/software/scm/git/git-2.9.3.tar.gz
tar xzvf git-2.9.3.tar.gz
cd git-2.9.3
make prefix=/usr/local all
make prefix=/usr/local install
```

# 既存のディレクトリをGit管理する

いよいよ本題です。
前述の通り今回はサーバー移行だったので `だったら最初からcloneすればいいじゃん` って思われるかもしれません。
実際それでも良かったんですが、いかんせん台数が多くてそれぞれのリポジトリもけっこう大きかったので出来れば退避して戻して、とかやりたくなかったので既存ディレクトリそのままでGit管理下にするようにしました。

## ローカルリポジトリを作成してサーバーの状態を確認する

FTPデプロイのあるあるですが、Gitの内容とサーバーの内容が本当に合ってるのかどうかってこわいですよね？
ですので、まずはGitとサーバーにあがっているファイルの差分を確認します。

1. 対象ディレクトリにローカルリポジトリを作る

    ```shell-session
    $ cd /対象ディレクトリ
    $ git init
    $ git remote add origin 対象リポジトリURL
    ```

2. リモートリポジトリの情報を取得しておく

    ```shell-session
    $ git fetch
    ```
2. プッシュ用にユーザー設定をしておく

    ```shell-session
    $ git config --global user.email "test@test.com"
    $ git config --global user.name "デプロイユーザー"
    ```
3. gitignoreだけ先に適用して現時点のローカルリポジトリの情報をコミットしておく

    ```shell-session
    $ git checkout -b master
    $ git checkout origin/master -- .gitignore
    $ git add --all
    $ git commit -m 'gitignoreだけ先に適用して現時点のローカルリポジトリの情報をコミットしておく'
    ```

4. リモート上のmasterをマージしてみて、差分を確認してみる

    ```shell-session
    $ git merge --allow-unrelated-histories origin/master
    $ git status
    ```

    ここで、
    - コンフリクト分は全てリモートリポジトリの内容を優先する
    - 一部サーバー上の内容をプッシュしてリモートリポジトリの内容を書き換える
    
    のどちらにするのかを確認します

## リモートリポジトリの内容をそのまま反映させる場合の対応

1. `リモートリポジトリの内容をそのまま反映させる` の場合、マージしたものを一回リセットしてリモートの内容に上書きした状態にする

    ```shell-session
    マージを元に戻す(追加とかも全部戻すのでaddをしてから)
    $ git add --all
    $ git reset --hard ORIG_HEAD
    リモートの内容で上書き、コミット
    $ git checkout --theirs origin/master .
    $ git add --all
    $ git commit -m 'リモート優先でmasterを全上書き'
    ```

2. ローカルのmasterとorigin/masterを同期させる

    ```shell-session
    この状態でローカルとoriginのmasterを同期する為に `git push origin master` をやりたいのだが、
    $ git push origin master

    fatal: refusing to merge unrelated histories

    となってしまうので `--allow-unrelated-histories`でorigin/masterをマージしてからプッシュする
    $ git merge --allow-unrelated-histories origin/master
    $ git push origin master
    ```

## 一部サーバー上の内容をプッシュしてリモートリポジトリの内容を書き換える場合の対応

1. `一部サーバー上の内容をプッシュしてリモートリポジトリの内容を書き換える` 場合はマージした内容を良い感じに修正したうえでコミットするだけ。

    ```shell-session
    コンフリクト分を見ながら修正する
    ...略...
    修正した内容でプッシュ
    $ git add --all
    $ git commit -m 'origin/masterをマージしてあるべきmasterにした状態でコミット'
    $ git push origin master
    ```

## 最後に忘れずやること
ここまででサーバーへのGit導入は完了です。

最後に、デプロイする時に `git pull origin master`　でなく `git pull`　だけにしたいので、

```shell-session
$ git branch --set-upstream-to=origin/master master
```

をしておけば

```shell-session
$ git pull
```

でデプロイ完了出来ます。

# さいごに

今回使ったオプションはどれも使ったことないものばかりだったので、もっとスマートな方法もあるんだろうなと思います。
そういったご意見ありましたら是非コメント頂けますと幸いです:bow: