プログラミングの学習経過をgit管理できるようにする

## はじめに
プログラミングの勉強としてライブラリのチュートリアルをやったり、参考書に乗っているサンプルアプリを作ったりとソース書く機会は多いです。
こうした勉強中に書いたソースもgitで管理していくと、自分がいつ何を勉強したのか、いつどんなエラーで悩んだのかを記録できておすすめです。
今回はプログラミングを勉強したての新人プログラマーに向けて各種チュートリアルをgit管理しながら取り組める環境構築の手順をメモとして残します。

## Git関連のツールを準備する
### Gitのインストール
まずはPC（ホストOS）にGitをインストールします。
次のサイトを参考にお使いのWindows, MacにGitをインストールしてください。
https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

### Sourcetreeのインストール（任意）
GitのGUIクライアントツールであるSourcetreeをインストールします。
次のサイトからダウンロードしてください。
https://ja.atlassian.com/software/sourcetree
セットアップの途中でAtlassianアカウントが必要になりますので、作成がまだの方は作成してください。

### GitHubアカウントの作成
GitHubのアカウントを作成してください。FreeプランでOK。
https://github.com/


## 仮想サーバー（ゲストOS）を建てる
今回はLinuxの仮想サーバーを建て、そこでプログラミング言語をインストールしたり、プロジェクトを作成したり、ウェブサーバーを起動したりといった環境を作ります。
### VirtualBoxのインストール
次のサイトから入手してください。
http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html?ssSourceSiteId=otnjp

### Vagrantのインストール
次のサイトから入手してください。
https://www.vagrantup.com/downloads.html

### 仮想サーバー作成する
1つのホストマシン上に複数の仮想サーバーを作成することが可能です。
このとき「1つの仮想サーバー」と「PC上の1つのディレクトリ」が1対1に対応します。
つまり、新しい仮想サーバーを作成する場合は新しくディレクトリを作成する必要があります。
今回はDocumentsディレクトリ配下に仮想サーバー用のディレクトリを作成します。
以下ターミナル（windowsではコマンドプロンプト）で作業します。

```bash
# Documentsディレクトリに移動
$ cd ~/Documents

# 仮想サーバー用のディレクトリを作成（今回はvagrantという名前）
$ mkdir vagrant

# ディレクトリを移動
$ cd vagrant
```

仮想サーバーを建てるための設定ファイルを作成します

```bash
$ vagrant init
```

現在のディレクトリに Vagrantfile という設定ファイルが作成されるので、こちらを編集していきます。

```bash
$ vi Vagrantfile
```

Box の設定箇所を書き換えます。Box とは OS の元となるものです。
今回は [CentOS 7](https://app.vagrantup.com/centos/boxes/7) のBoxを使用します。
これ以外の OS を使用したい場合はこちらのウェブサイトから探します。
https://app.vagrantup.com/boxes/search

```ruby:Vagrantfile
   # config.vm.box = "base"  # 15行目あたりのこの行を削除
   config.vm.box = "centos/7"  # この行を追加
```

ホストOSとゲストOS（仮想サーバー）でフォルダを共有するために次の箇所も書き換えます。

```ruby:Vagrantfile
   # config.vm.synced_folder "../data", "/vagrant_data"  # 46行目あたりのこの行を削除
   config.vm.synced_folder ".", "/vagrant", type: "virtualbox"  # この行を追加
```

次にvagrantでVirtualBoxを使用する際にパフォーマンスを上げてくれるプラグインをインストールします。

```
$ vagrant plugin install vagrant-vbguest
```

インストールしたら仮想サーバーを起動します。
初回は時間がかかります。

```bash
$ vagrant up
```

起動できたらまずは SSH の設定を確認します。

```
$ vagrant ssh-config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/{user_name}/Documents/vagrant/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL
```

仮想サーバーにSSH接続する際にはこちらの情報を使用します。
`PasswordAuthentication no` となっているためパスワードでの認証がこのままではできません。
`IdentityFile` に認証鍵のパスが記載されているので認証の際にはこちらを使用するようにします。

それでは仮想サーバーにSSH接続します。

```
$ vagrant ssh
```

プロンプトが `[vagrant@localhost ~]$ ` に変わったら接続が成功しています。

### サーバーにいろいろインストール

まずはインストール済みのパッケージをアップデートします。

```
$ sudo yum -y update
```

よく使うコマンドをインストールします。

```
$ sudo yum -y install wget
$ sudo yum -y install unzip
$ sudo yum -y install yum-utils
$ sudo yum -y install mlocate
$ sudo updatedb
```

epel, remi レポジトリを追加します。

```
$ sudo yum -y install epel-release
$ sudo rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
$ sudo yum-config-manager --enable epel remi
$ yum repolist all
```

### provisionファイルの作成
たった今vagrantで仮想サーバーを立ち上げた後に諸々のコマンドを実行しましたが、これらを一つのシェルスクリプトにまとめて起動時に自動で実行してくれるような構築をしていきます。
こうすることで、他人に自分の開発環境の状態を簡単に再現してもらうことが可能になりますし、仮想サーバーをもう1台作成したいという場合にも楽に同じ環境を作ることができるようになります。

仮想サーバーに接続した状態の場合はexitで抜けておきます。

```bash
$ exit
```

Vagrant fileに次の1行を追加します。

```bash
$ vi Vagrantfile
```

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  # ~~~省略~~~

  # この行を追加
  config.vm.provision "shell", :path => "provision.sh"
  
  # ~~~省略~~~
end
```

provision.shファイルを作成し、中にLinuxで実行したいコマンドを書いていきます。

```bash
$ vi provision.sh
```

```bash:provision.sh
# インストール済みのパッケージをアップデート
sudo yum -y update

# よく使うコマンドをインストール
sudo yum -y install wget unzip yum-utils mlocate
sudo updatedb

# epel, remi リポジトリを追加して有効化
sudo yum -y install epel-release
sudo rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
sudo yum-config-manager --enable epel remi
sudo yum repolist all
```

vagrantの起動時、または `vagrant provision` コマンドで今作成したシェルスクリプトを仮想サーバーで実行します。
今後サーバー側で何かをインストールした際には `provision.sh` にそのときのコマンドを記載するようにします。
こちらのファイルは後ほどgitで管理するようにするため、サーバーにいつ何がインストールされたかをgitで管理できるようになります。

## ローカルリポジトリを作成する
ここまでの作業をgitにコミットします。
コマンドラインを使う方法とSourcetreeを使う方法の2種類を紹介します。

以下、ホストPC上で作業しますので、仮想サーバーからはexitしてホストPCのターミナルを開いた状態にしてください。

### コマンドライン編

まずは設定をします。大体はお好みなので任意ですが、ユーザ名とメールアドレスの登録だけは必須です。

```bash
# 現在の設定を確認
$ git config --list

# ユーザ名とメールアドレスを登録（commit時に表示される名前）
git config --global user.name "username"
git config --global user.email "username@example.com"

# 色を付けて見やすくする
$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto

# commitのテンプレート作成
$ git config --global commit.template $HOME/.gitmessage.txt

# UTF-8問題を解決（mac向け）
$ git config --global core.precomposeunicode true

# 日本語ファイル名が表示されるように
$ git config --global core.quotepath false

# 現在の設定を再確認
$ git config --list
```

vagrantのディレクトリでローカルリポジトリを作成し、コミットします。

```bash
# ローカルリポジトリの作成
$ git init

# カレントディレクトリのすべての変更をstagingに追加
$ git add .

# 変更とstagingへの追加状況を確認
$ git status

# stagingされた変更をメッセージ付きでコミット
$ git commit -m "initial commit"
```

### Sourcetree
![スクリーンショット 2018-02-25 3.12.34.png](https://qiita-image-store.s3.amazonaws.com/0/237863/ede828ae-1864-c089-3708-1d5bde63ac1a.png)
![スクリーンショット 2018-02-25 3.13.40.png](https://qiita-image-store.s3.amazonaws.com/0/237863/6a8bc85a-ae10-5c0d-598b-b1f613c540ab.png)
![スクリーンショット 2018-02-25 3.14.37.png](https://qiita-image-store.s3.amazonaws.com/0/237863/83ec9402-c600-359f-3f3e-90598bcaeee6.png)
![スクリーンショット 2018-02-25 3.16.32.png](https://qiita-image-store.s3.amazonaws.com/0/237863/e8f133cb-73c2-72ad-97ff-331fb21fb93a.png)
![スクリーンショット 2018-02-25 3.17.36.png](https://qiita-image-store.s3.amazonaws.com/0/237863/c62bad9b-8ce6-a162-f6c9-6a206ccf1a12.png)
![スクリーンショット 2018-02-25 3.19.40.png](https://qiita-image-store.s3.amazonaws.com/0/237863/a799eaf5-a3d2-47bc-635a-847c6817c762.png)
![スクリーンショット 2018-02-25 3.21.13.png](https://qiita-image-store.s3.amazonaws.com/0/237863/1c46a996-01a2-1f4a-26d4-8c9f36f84311.png)
![スクリーンショット 2018-02-25 3.21.30.png](https://qiita-image-store.s3.amazonaws.com/0/237863/7b3804d5-2674-b69a-6fd2-8a9636ea4545.png)
![スクリーンショット 2018-02-25 3.22.32.png](https://qiita-image-store.s3.amazonaws.com/0/237863/19476788-6057-4092-4e58-3d693857156e.png)
![スクリーンショット 2018-02-25 3.22.50.png](https://qiita-image-store.s3.amazonaws.com/0/237863/7b19103d-7897-2a2b-d045-082bae5956d1.png)
![スクリーンショット 2018-02-25 3.24.20.png](https://qiita-image-store.s3.amazonaws.com/0/237863/239a24fc-707b-d5ed-14c4-bd2b9b00547b.png)


## Githubでリモートリポジトリを作成する
![スクリーンショット 2018-02-25 4.38.26.png](https://qiita-image-store.s3.amazonaws.com/0/237863/7aeeee12-700b-df92-e0c5-bdc6ef0b9183.png)
![スクリーンショット 2018-02-25 4.38.57.png](https://qiita-image-store.s3.amazonaws.com/0/237863/27018a89-9092-5cd0-4e1a-1dfecca1d3bc.png)
![スクリーンショット 2018-02-25 4.39.13.png](https://qiita-image-store.s3.amazonaws.com/0/237863/42b04fda-6cfc-e55b-78a3-06161ff04cb4.png)


## リモートリポジトリにローカルリポジトリを紐付けてプッシュする

### コマンドライン編
GithubでURLをコピー

![スクリーンショット 2018-02-25 4.43.24.png](https://qiita-image-store.s3.amazonaws.com/0/237863/b849dbb6-1454-ece3-bc35-69566a1e6199.png)

リモートリポジトリを追加してプッシュ

```bash
$ git remote add origin https://github.com/rema424/tutorial.git
$ git push -u origin master
Username for 'https://github.com': {github_user_name}
Password for 'https://{user_name}@github.com': {github_password}
```

エラーが出た

```
To https://github.com/rema424/tutorial.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/rema424/tutorial.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

プッシュの前にプルしてくれと言われてるのでそうします

```
$ git pull origin master
```

プルでもエラーが出てる

```
fatal: refusing to merge unrelated histories
```

調べたらこれで解決できるよう

```
$ git pull origin master --allow-unrelated-histories
```

プルできたらプッシュ（マージコミットの際メッセージの入力求められるかも）

```
$ git push origin master
```

Githubにも反映されてる

![スクリーンショット 2018-02-25 5.26.37.png](https://qiita-image-store.s3.amazonaws.com/0/237863/a08a8c38-68db-112c-ba9f-44a22105fb19.png)


### Sourcetree編
#### リモートリポジトリを紐付け
右上の設定をクリック

![スクリーンショット 2018-02-25 4.42.26.png](https://qiita-image-store.s3.amazonaws.com/0/237863/a9fbb414-0a82-7705-2545-7d0d13ced45e.png)

リモートタブをクリック

![スクリーンショット 2018-02-25 4.42.34.png](https://qiita-image-store.s3.amazonaws.com/0/237863/a09fbf7d-3cf3-3f54-2c2f-f15b90060b7b.png)

追加をクリック

![スクリーンショット 2018-02-25 4.42.40.png](https://qiita-image-store.s3.amazonaws.com/0/237863/9ee76363-760f-ccd8-5340-a6038fcc2896.png)

リモートの名前は慣習的に「origin」と入力。
URLはGithubよりコピー。
入力が完了したらOKをクリック。

![スクリーンショット 2018-02-25 4.43.01.png](https://qiita-image-store.s3.amazonaws.com/0/237863/bebc8742-791f-8aba-713a-ccfeb2784811.png)

![スクリーンショット 2018-02-25 4.43.24.png](https://qiita-image-store.s3.amazonaws.com/0/237863/b849dbb6-1454-ece3-bc35-69566a1e6199.png)

![スクリーンショット 2018-02-25 4.50.17.png](https://qiita-image-store.s3.amazonaws.com/0/237863/96a79b6f-133f-89e3-2366-d43b8cc2fd69.png)

紐付け完了

![スクリーンショット 2018-02-25 4.44.09.png](https://qiita-image-store.s3.amazonaws.com/0/237863/f65f3076-ea53-21af-22ac-ed57fb79507a.png)

#### リモートリポジトリにローカルリポジトリでのコミットをプッシュ

上部メニューよりプッシュをクリック

![スクリーンショット 2018-02-25 4.44.59.png](https://qiita-image-store.s3.amazonaws.com/0/237863/fc606a35-94ab-9b6a-5587-fb46f7599562.png)

チェックボックスをクリックしてOK

![スクリーンショット 2018-02-25 4.45.07.png](https://qiita-image-store.s3.amazonaws.com/0/237863/192975bd-4a58-63b4-02b0-9e9f8d278eb3.png)

エラーが出た。先にプッシュの前にプルしてと言われてる。

![スクリーンショット 2018-02-25 4.45.14.png](https://qiita-image-store.s3.amazonaws.com/0/237863/2947548b-2f06-3162-0c4c-ce6355605c42.png)

上部メニューよりプルをクリック

![スクリーンショット 2018-02-25 4.45.30.png](https://qiita-image-store.s3.amazonaws.com/0/237863/70e6e6f3-5061-f479-e366-4e02063f4584.png)

ブランチの選択でmasterを選択

![スクリーンショット 2018-02-25 4.45.35.png](https://qiita-image-store.s3.amazonaws.com/0/237863/09da4a77-f6e4-ebd0-0826-9acd48242ae9.png)

OKをクリック

![スクリーンショット 2018-02-25 4.45.39.png](https://qiita-image-store.s3.amazonaws.com/0/237863/241bc267-1d86-f3a8-7a35-d06ef0363224.png)

プルができたらもう一度プッシュに挑戦

![スクリーンショット 2018-02-25 4.45.51.png](https://qiita-image-store.s3.amazonaws.com/0/237863/8df8d197-9774-4641-92eb-059324699e26.png)

できた

![スクリーンショット 2018-02-25 4.46.06.png](https://qiita-image-store.s3.amazonaws.com/0/237863/431f140d-afb4-ffa1-eca5-f8de87c6d778.png)

Githubも更新されてる

![スクリーンショット 2018-02-25 4.46.21.png](https://qiita-image-store.s3.amazonaws.com/0/237863/f1c33823-e6f8-564b-5dd3-3cf419a875ea.png)

## 終わりに
以上で次のような環境が構築できています。

1. VirtualBox+VagrantによるLinux仮想サーバー
2. ホストOSとゲストOSの双方向リアルタイム共有フォルダ
3. ローカルリポジトリの作成
4. リモートリポジトリの作成
5. ローカルリポジトリとリモートリポジトリの紐付け

今後学習を進めていく上での方針としては、

1. プログラミング言語やDBは仮想サーバーにインストールする
2. インストール時に使用したコマンドは `provision.sh` に記載するようにする
3. `provision.sh` を更新したらコミットをするようにする
4. プロジェクトを作成する際は仮想サーバー上の /vagrant ディレクトリ内に作成する
5. ホストOSの `~/Documents/vagrant` がフォルダとゲストOSの `/vagrant` フォルダが同期しているため、ソースの編集はホストOSの `~/Documents/vagrant` にあるファイルを編集する
6. 編集内容はコミットする

例えば `rails new` や `react-create-app` は仮想サーバー上で、ソースの編集やgit管理はホストマシン（Sourcetree）で行うことが可能になります。