Git入門編(エンジニア向け)

分散型バージョン管理システムgitについてまとめます。GitHubやBitbucketに使われているのでエンジニアさんにとって必須なものです。

__特にプログラミングを勉強するなら初めにgitを覚えた方が効率よく勉強ができます。__

今回はローカル環境でgitを使うことを目指しています（初心者向け）

# 環境

Mac El capitan(v10.11.3)
homebrew導入済み
brewにてgit導入済み

#gitの説明ざっくり

gitを使わない場合は、過去の内容を参照するには前もって名前を付けて保存していました。このような管理だと見にくく管理しにくいです。
作業用ディレクトリを作成することで、gitコミット(保存)することで自動的に過去の内容を保存、管理しやすくなるので便利です。(説明が下手なので実際に使ってみると便利だと実感します)

gitの管理は

1. 作業用ディレクトリ
2. ステージングエリア（インデックス）
3. リポジトリ (ローカル、リモート)

で行われます。


#gitの設定

必須

```
$ git config --global user.name "名前"
$ git config --global user.email "メールアドレス"
```

上の設定は保存した時の必須情報です。

SSLの証明書のチェックをしないようにする設定

```
git config --global http.sslVerify false
```

他の設定(gitコマンド色分け)

```
$ git config --global color.ui true
```

gitの設定確認

```
$ git config -l
user.name=ebisennet
user.email=ebisennet@gmail.com
color.ui=true
```

#コミット(ファイルの保存のようなもの)

まず作業用ディレクトリを作成し移動

```
$ mkdir git_lessons
$ cd git_lessons
```

gitの配置

```
$ git init
Initialized empty Git repository in /Users/ebisennet/work/git_lessons/.git/
```

ではファイルを作成しgitで管理します。
作業用ディレクトリで以下の内容を保存

```vim:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <title>git練習</title>
</head>
<body>
  <p>初めてのコミット</p>
</body>
</html>
```

上のファイルをステージングエリアに保存します。(1から2)
addすることでどのファイルをコミットするか選択することができます。

```
$ git add index.html
```

ステージングエリアからリポジトリにコミット(保存)します(2から３)

```
$ git commit
```

すると以下のような画面になり、コメントを書いてくださいと言われます。コミットした内容を説明するコメントを書きましょう(１行目)

```vim:
initial commit↲
# Please enter the commit message for your changes. Lines starting↲
# with '#' will be ignored, and an empty message aborts the commit.↲
# On branch master↲
#↲
# Initial commit↲
#↲
# Changes to be committed:↲
#»--new file:   index.html↲
#↲
```

コメントを保存したら以下の内容が表示されます。

```
[master (root-commit) cdaf7f4] initial commit
 1 file changed, 9 insertions(+)
 create mode 100644 index.html
```

コミットができました。履歴を確認するには

```
$ git log
commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

#git logの見方

上の例で説明します。

```
$ git log
# 下の文字列はユニークなID
commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2 
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

`git log`のオプション

```
$ git log --oneline
cdaf7f4 initial commit
```

変更点の表示

```
$ git log -p
commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit

diff --git a/index.html b/index.html
new file mode 100644
index 0000000..83c9cc2
--- /dev/null #今回は何もないところから作成した。
+++ b/index.html
@@ -0,0 +1,9 @@ #変更された行数
+<!DOCTYPE html>
+<html lang="ja">
+<head>
+  <title>git練習</title>
+</head>
+<body>
+  <p>初めてのコミット</p>
+</body>
+</html>
```

どのファイルが何ヶ所変わったか

```
$ git log --stat
commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit

 index.html | 9 +++++++++
 1 file changed, 9 insertions(+)
```

#現在の状況の把握

先ほど作成した`index.html`を編集します。

```vim:index.html
<!DOCTYPE html>↲
<html lang="ja">↲
<head>↲
  <title>git練習</title>↲
</head>↲
<body>↲
  <p>初めてのコミット</p>↲
  <p>２番目のコミット</p>↲
</body>↲
</html>↲
```

現状確認

```
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html #変更されたファイル

no changes added to commit (use "git add" and/or "git commit -a")
```

今回は上に書いてある。
`to discard changes in working derectory`は作業用ディレクトリの変更を破棄しると書いてあるコマンドを使い変更した内容を元に戻します。

```
$ git checkout -- index.html
$ cat index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <title>git練習</title>
</head>
<body>
  <p>初めてのコミット</p>
</body>
</html>
```

先ほど追加したパラグラフがなくなりましたね。

#差分の確認(どこがどう変わったか)

もういちど`<p>２つめのコミット</p>`を追加します。

差分を表示します。（ステージングエリアにあげてないもの）

```
$ git diff
diff --git a/index.html b/index.html
index 83c9cc2..71fb52b 100644
--- a/index.html
+++ b/index.html
@@ -5,5 +5,6 @@
 </head>
 <body>
   <p>初めてのコミット</p>
+  <p>２つめのこみっと</p>
 </body>
 </html>
```

ステージングエリアに上がったものについて差分を表示させます。

```
$ git add index.html
```

```
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   index.html

```

ステージングに上がっていることがわかります。

ステージングに上がっている時の差分は

```
$ git diff --cached
diff --git a/index.html b/index.html
index 83c9cc2..71fb52b 100644
--- a/index.html
+++ b/index.html
@@ -5,5 +5,6 @@
 </head>
 <body>
   <p>初めてのコミット</p>
+  <p>２つめのこみっと</p>
 </body>
 </html>
```

#gitのファイル操作

まず先ほどステージングエリアに上げたものを取り下げます。

```
$ git reset HEAD index.html
Unstaged changes after reset:
M	index.html
```

次に変更前の状態にします。

```
$ git checkout -- index.html
```

元の状態に戻りました。

次にindex.htmlに`<p>２つ目のコミット</p>`を追加します。

```
#現在の作業ディレクトリ以下をステージングエリアに上げる。
$ git add .
```

gitで管理されているファイルの移動、削除は

```
$ git rm ファイル名
$ git mv ファイル名
```

#git管理に含めない設定

ログファイルなど含めたくない場合

```
$ ls
error.log	index.html
```

作業ディレクトリ上に`.gitignore`ファイルを作成し載せたくないファイル名を記載する。

```vim:.gitignore
*.log
```

すると

```
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

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

	.gitignore

no changes added to commit (use "git add" and/or "git commit -a")
```

となりlogファイルが対象になっていないことがわかる。

#直前のコミットを変更

前回の状態から

```
$ git add .
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   .gitignore
	modified:   index.html

```

ステージングエリアからリポジトリにコミットするとき、コメントが必要となりますが、１行だけのコメントの場合

```
$ git commit -m "コメント"
```

でコミットすることができて便利です。

```
$ git commit -m "２つ目のコミット"
[master 5034a90] ２つ目のコミット
 2 files changed, 2 insertions(+)
 create mode 100644 .gitignore
```

```
$ git log
commit 5034a909699bc44c6ae265e5f65f7519c6e81d19
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 17:04:18 2016 +0900

    ２つ目のコミット

commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

コミットされていることがわかりました。

先ほどコミットした内容にちょっとした変更をしたい場合など、コミットするとたくさんのログが生成されてしまします。

ちょっとだけ変更したい場合(今回は`<p>２つ目のコミット!!!</p>`と変更)は、

```
$ git commit --amend
[master 184663f] ２つ目のコミット!!!
 Date: Mon Mar 21 17:04:18 2016 +0900
 2 files changed, 2 insertions(+)
 create mode 100644 .gitignore
```

```
$ git log
commit 184663f1620909adc2e3537b9fc7767bfb2a756f
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 17:04:18 2016 +0900

    ２つ目のコミット!!!

commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

logの内容が変更されていますね。

#過去のバージョンに戻る!

先ほどの状態から、`index.html`を変更する

```vim:index.html
<!DOCTYPE html>↲
<html lang="ja">↲
<head>↲
  <title>git練習</title>↲
</head>↲
<body>↲
  <p>初めてのコミット</p>↲
  <p>２つ目のコミット</p>↲
  <p>gitむずかしい？</p>↲
  <p>gitおもろいで!</p>↲
</body>↲
</html>↲
```

これをステージングエリアに上げたが、
現在の作業ディレクトリとステージングエリアを直前(HEAD)の状態に戻したい時

```
$ git reset --hard HEAD
HEAD is now at 184663f ２つ目のコミット!!!
```

すると

```
$ git log
commit 184663f1620909adc2e3537b9fc7767bfb2a756f
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 17:04:18 2016 +0900

    ２つ目のコミット!!!

commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

となり戻っていることがわかります。

さらに`2つ目のコミット!!!`が気に入らない場合は更に

```
$ git reset --hard HEAD^
HEAD is now at cdaf7f4 initial commit
```

または

```
$ git reset --hard コミットID
```

ちなみに`^`キャレットはひとつ前の意味でHEADからひとつ前つまり`initial commit`部分を指しています。

#やっぱり変更した内容にしたい(前回の内容だけ)

```
$ git reset --hard ORIG_HEAD
HEAD is now at 184663f ２つ目のコミット!!!
```

#ブランチを使う

ブランチとは、分岐、枝分かれとも言われ別々のバージョンを平行に開発したい場合など

git作成時、masterブランチになっている。

現在のブランチを確認するには

```
$ git branch
* master
```

masterブランチになっていることが分かりました。

新しい機能など追加したい場合などに、新しいブランチを作成します。

```
$ git branch hoge
$ git branch
  hoge
* master
```

ブランチを切り替える(スイッチ)には

```
$ git checkout hoge
Switched to branch 'hoge'
$ git branch
* hoge
  master
```

hogeブランチ状態で以下のファイルを作成、コミットする。

```
$ echo "alert();" > myscript.js
$ git add .
$ git commit -m "script added"
[hoge d718d3a] script added
 1 file changed, 1 insertion(+)
 create mode 100644 myscript.js
$ git log
commit d718d3a0c702f3e234dc687604dc7dffca67dfe6
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 18:57:13 2016 +0900

    script added

commit 184663f1620909adc2e3537b9fc7767bfb2a756f
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 17:04:18 2016 +0900

    ２つ目のコミット!!!

commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

この状態からmasterにスイッチする。

```
$ git checkout master
Switched to branch 'master'
$ git log
commit 184663f1620909adc2e3537b9fc7767bfb2a756f
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 17:04:18 2016 +0900

    ２つ目のコミット!!!

commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

#ブランチのマージ(結合)

hogeの内容をmasterに反映させる(マージ)

現在は

```
$ git branch
  hoge
* master
```

masterになっています。

```
$ git merge hoge
Updating 184663f..d718d3a
Fast-forward
 myscript.js | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 myscript.js
```

とするとmasterに反映されていることがわかります。

```
$ ls
error.log	index.html	myscript.js
$ git log
commit d718d3a0c702f3e234dc687604dc7dffca67dfe6
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 18:57:13 2016 +0900

    script added

commit 184663f1620909adc2e3537b9fc7767bfb2a756f
Author: ebisennet <ebisennet@gmail.com>
Date:   Mon Mar 21 17:04:18 2016 +0900

    ２つ目のコミット!!!

commit cdaf7f4359c7d83159dd96f9b15a0e73aa9137e2
Author: ebisennet <ebisennet@gmail.com>
Date:   Sun Mar 20 18:35:54 2016 +0900

    initial commit
```

hogeブランチがいらなくなったので

```
$ git branch
  hoge
* master
$ git branch -d hoge
Deleted branch hoge (was d718d3a).
$ git branch
* master
```

後で書く
マージの衝突(重要)
gitコマンドの補完設定