[画像付き解説]Github初学者が、gitignoreについてまとめてみた

#概要
最近、とあるエンジニアさんに成果物のコードレビューをお願いした際に、「githubにpushしたファイルが多すぎて確認出来ない！共同開発する場合はgitignoreを活用した方がいい」と教えて頂いたのですが、gitignoreって何?状態だったので、調べて学んだことをまとめてみました。
まだご存知でない方のスキル向上に繋がればと思い共有させて頂きます。

##.gitignoreとは
Githubのリモートリポジトリで管理しないファイル/ディレクトリを宣言することが出来るファイルのことです。
.gitignoreファイルに指定したファイル/ディレクトリは、git addコマンドの対象から除外されるようになり、その後pushしてもGithubのリモートリポジトリに送信されなくなります。

###どんなメリットがあるの?
①不要なデータがpushされないため、第三者がコードを見る時に確認しやすくなる
②公表したくない情報をGit管理の対象外とすることでセキュリティ面を向上させることが出来る　
　
###どんなものに使うべき？　
　・OSや各自ローカル環境で自動生成されるもの(ex. Macの.DS_storeファイル)
　・ローカル環境で使うがリモート環境には必要のないもの(ex. テストでしか使用しない画像)
　・コンパイル、ビルドした時に作成されるデータや実行形式ファイル(ex. プロジェクト個別に導入したgemファイル群)
　・端末固有の設定情報が記載されたもの(ex.ログイン情報を入れた環境変数ファイル)

などなど。たくさんの人が見る環境だからこそ、gitignoreで適切に管理することが重要なんですね！

##実際に試してみた

###実行環境
　・MacOS: Mojave   10.14.6
　・Ruby: v2.5.1
　・Ruby on Rails:  v5.2.4
　・テキストエディタ: Atom
  

今回は既存のrailsプロジェクトでインストールしたgemファイルを例に検証していきます。 
まずはgitignoreを使わずGithubにpushしていきます。　
(githubのアカウント登録、リポジトリの作成は既に済んでいるものとします)

railsプロジェクトのブランチ上で、`bundle install --path vendor/bundle` を実行し 
gemをインストール(--pathオプションで gemのインストール先をvendor/bundleに指定しています)

git statusコマンドで、Git管理の状態を確認してみます。

```
git status

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	vendor/bundle/

nothing added to commit but untracked files present (use "git add" to track)

```
実行すると 「untracked files」と表示されているのがわかります。
上記について正しく理解するため、ファイルのステータス状況を示す「トラッキング」について以下のようにまとめました。　
　
・トラッキング状態 : 既にステージングエリアに登録されており、commitされていないファイル
・アントラッキング状態　： まだステージングエリアに登録されていないファイル
　

つまり、インストールしたgemはまだステージングエリアに登録されていないことになります。
git addコマンドは、ファイルやディレクトリをステージングエリアに登録してまとめておく(トラッキング状態に変更させる)ことでリモートリポジトリに送信する準備を行うコマンドです。 
 
２. git addコマンドを実行
実行した後のファイルの状態がこちらです。

```
git add vendor/bundle   # vendor/bundleディレクトリ配下のファイルを指定
git status

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   vendor/bundle/ruby/2.5.0/bin/bootsnap
	new file:   vendor/bundle/ruby/2.5.0/bin/byebug
	new file:   vendor/bundle/ruby/2.5.0/bin/chromedriver-helper
	new file:   vendor/bundle/ruby/2.5.0/bin/chromedriver-update
	new file:   vendor/bundle/ruby/2.5.0/bin/listen
	new file:   vendor/bundle/ruby/2.5.0/bin/nokogiri
	new file:   vendor/bundle/ruby/2.5.0/bin/puma
	new file:   vendor/bundle/ruby/2.5.0/bin/pumactl
	new file:   vendor/bundle/ruby/2.5.0/bin/rackup
	new file:   vendor/bundle/ruby/2.5.0/bin/rails
     ・
　　　・
　　　以下gemファイル群の記述が続く
```
「changes to be commited」とあるように、コミットの準備が整っている状態(＝トラッキング状態)になったことがわかります。

3.commit、pushしローカルリポジトリの内容をリモートリポジトリに送信します。

```
git commit -m "gemのインストール1"
git push
```
![git1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/5e9ce667-2be1-c096-84ac-f1cabcf33245.png)


当然、gemファイルの差分が大量に保存され、結果として[file changed]欄が5,000以上も表示されています。

###.gitignoreを使ってみる

では、gitignoreを使ってvendor/bundleの中身のファイルがリモートリポジトリに保存されないようにしてみましょう！

先程のgemファイルに追加でpry-byebugをインストールする作業を例に検証します。

` gem install pry-byebug `を実行しインストール

ルートディレクトリに配置されている.gitignoreファイルを開いて記述していきます。
筆者の実行環境の場合プロジェクトで自動生成されていましたが、ない場合はtouch .gitignoreでファイルを作成してください。

.gitignoreの書き方は以下の表のとおりです。

やりたいこと|指定方法|　　　例　　　
:-:|:-:|:-:
|同名のファイル/ディレクトリを全て除外|ファイル or ディレクトリ名|file.rb
|同名のディレクトリ以下のものを全て除外|末尾に / をつける|directory/
|特定のファイル or ディレクトリを除外|末尾以外に / をつける|/directory/file.rb
|相対パスで指定したディレクトリの<br>中身を全て除外|先頭と末尾両方に<br> / をつける|/dirctory/
|特定の拡張子を除外|先頭に*をつける|*.txt
|特定のファイル or ディレクトリを対象に設定|先頭に ! をつける|!dirctory/file.rb
|コメントを入れる|先頭に # をつける|#comment
※指定出来る範囲は.gitignoreを置いているディレクトリ以下の階層に限る
尚、.gitignoreは複数ディレクトリに配置出来ます。上の階層から順に読み込まれ、条件が重複した場合は階層がより深いファイルの記述が上書き/反映されます。

今回はvendor/bundleの中身を全て除外したいので、以下のように記述します。

```
/vendor/bundle/
```
この状態でvendor/bundleのバスを指定してgit addを実行

```
git add vendor/bundle

The following paths are ignored by one of your .gitignore files:
vendor/bundle
Use -f if you really want to add them.
```
.ignoreさんからそのパスは除外しろって言われてるよ、と。
プロジェクト全体の変更をステージング対象とするgit add -Aで再度実行

```
git add -A

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   .gitignore

```
コード変更を行った　.gitignoreはステージングエリアに登録されましたが、やはりvendor/bundleは登録されていません。

```
git commit -m "gemのインストール2"
git push
```

結果
![gitignore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/d1625dc3-bb9b-204e-4a80-cc064787373a.png)

vendor/bundleを除外させ、リモートリポジトリをスッキリさせることが出来ました！

###既にGithubへpushしている場合の対応
.gitignoreを活用するうえでのポイントは、既にリモートリポジトリへ保存されているものは、そのまま.gitignorに書き込んでも効かないということです。
既存のプロジェクト等、途中から除外したい場合はリモートリポジトリ上のキャッシュを削除する必要があります。(キャッシュ=次回同じようなリクエストが発生したときのレスポンスでそのコンテンツを再利用するためのデータ)

以下のどちらかを実行、キャッシュを削除。 
・リモートリポジトリ上のデータのみ削除

```
git rm -r --cached vendor/bundle
```

・リモートリポジトリ、ローカルリポジトリどちらのデータも削除

```
git rm -r vendor/bundle
```

キャッシュを削除した後に.gitignoreを書き、再度add,commit,pushの手順を踏むことで除外することが出来ます。

結果
![vendor:bundle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/5990b227-efcf-b80a-ba6d-602236c4e6d5.png)

リモートリポジトリからキャッシュが削除され、pushした後もvendor/bundleが保存されないように設定することが出来ました！

#最後に
個人開発だけだとなかなか実感出来ないことですが、効率/セキュリティ面を向上させる技術としてまたひとつ基礎を積み上げることが出来ました。
実務でよく活用されることと聞きましたので、積極的に活用していきたいと思います。
また、少しでも私と同じ初学者の方の力添えになれば幸いです。
もし誤った記載などがありましたら、コメントでご指摘いただけると嬉しいです。