.gitignoreでローカルにファイルを残しつつgitには上げない方法

#この記事について
.gitignoreがどう動くのか、また何なのかを実際のBefore、Afterの状態をキャプチャして説明していきます。

#モチベーション
`.gitignore`を使用しないと、以下のようなことが起こる可能性があります。
- Git初心者が複数人で一つのアプリを開発する際、個々で毎回変わる設定ファイルを持つせいでマージする際にConflictが起きる
- Githubの無料アカウントを使用している場合に、全ファイルは公開されるため、サーバー情報を書いたファイルもGithubで公開されてしまう
そんな時に、この`.gitignore`が大事であることに気づいたのでまとめようと思いました（今までは誰かが`.gitignore`を常に作っていたので特に意識していなかったです。。）。

#手順
単純に、ルートディレクトリ配下に、`.gitignore`というファイルを作成し、そこに`Github`に載せたくない、または`git`で追跡したくないファイルを指定します。その前に、ファイルを既にpushしてしまっている場合、`git rm -r --cached ファイル名`というコマンドで、gitから指定ファイルを除外します。

#実装
CakePHPベースのアプリの`temp/cache`フォルダを除外します。

###現状
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/37156f37-67e7-8da7-64b9-0ea4d5779e49.png)
しっかり`cache`がGithubで確認できてます（本来ならアウト。。）。

###Step1: `git rm -r --cached ファイル名`でgitから指定ファイルを除外
以下、実際の実行結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/f692528d-f9ed-543c-c8ee-ec3ee6d9a2d7.png)
`git status`を見ると、しっかりuntrackされたように書かれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/d05b1c21-c603-9eba-b137-7e32bdf8143f.png)

###Step2: `.gitignore`をルートディレクトリ配下に作成し、この`temp/cache`を無視するよう以下のように記述
以下、実際の実行動作です。
![gitignore_1_demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/0503e1c9-424f-210f-54e8-464d62ed0baf.gif)
自分の場合、既に`.gitignore`を作成していたのですが、実行するコマンドは基本的には同じです。動画にあるように、最後に変更した内容を`commit`しましょう。

###Step3: `git push`でGithubに反映
Pushします。以下、実際の実行結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/2310b963-f379-e0fc-7df8-40fd035f1af2.png)

###実装後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/2d5fa228-6636-cbbd-df33-021d7713ffe9.png)
`tmp/cache`フォルダがGithubで消えていることが確認できます。

一方ローカルでフォルダを見てみると、`tmp/cache`フォルダが消えていないことが確認できます。つまりサーバー情報を載せたファイル等はローカルだけに保持するようなことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/f482991b-0031-3983-c1fd-757fd897d6f6.png)

#追記
※@htsignさんから指摘がありましたが、`git rm -r --cached ファイル名`では、最新のコミットからしかファイルが削除されません。なので、以下のように過去のコミット履歴をみると、削除したファイルが普通に存在してしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/541971e8-c061-e734-8f33-34349564eec0.png)
このファイル情報を見せたくない場合、`git filter-branch`等のコマンドで過去履歴からもファイルを削除する必要があります。
[Git リポジトリに上がっているファイルを履歴ごと消すには？](https://qiita.com/go_astrayer/items/6e39d3ab16ae8094496c)を参考に、実際に消してみます。
以下、実際の実行結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/c4cb619f-1593-8560-0351-b8cfa73b44fe.png)

次に、`git gc --aggressive --prune=now`でレポジトリを最適化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/bf75afbc-fd2d-6383-23bc-c552ab6eba14.png)

このままPushすると、コミット情報にコンフリクトがあるせいか、断られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/06236381-bd25-8cff-bcaa-2b418f186ce2.png)

`git push -f`で強制的にPushします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/8a374c28-a457-a1d4-ddf8-b4af57b53fa0.png)
うまくいきました。
※チームで開発を行う場合、このような強制的なPushを行うかは、慎重に検討しましょう。


#最後に
以上、`.gitignore`の動きについてまとめました。

#参考：
https://qiita.com/y_minowa/items/e3d8513dc31c1b378e0d
https://qiita.com/go_astrayer/items/6e39d3ab16ae8094496c
https://stackoverflow.com/questions/6403601/purging-file-from-git-repo-failed-unable-to-create-new-backup