【備忘用】綺麗なコミットを作るためのgitコマンド集

## 初めに
gitを用いてソースコードを編集する際に、プログラムの動確をしつつ、コミットの粒度や対応するコミットメッセージを書くのは大変です。
なので、ローカルリポジトリに対しては、ある程度ソースコードを変更して動確できたら、メッセージは適当で「コミット！」という場合があるかと思います。

しかし、いざプッシュするときには、コミットを綺麗にする必要があります。
今回はその際に使えそーなコマンドを、自分用の備忘録として記載しようと思います。
(どういうコミットが綺麗かという記事でありません)

## CASE1:適当なコミットを削除して、まとまったコミットを作る
以下に記載している変更前の3つのコミットを削除し、変更後のような1つコミットを作ります。
(既存のコミットをまとめる方法は、CASE3に記載)

* 変更前
	* ソース変更内容：機能1　コミットメッセージ:fix
	* ソース変更内容：機能2　コミットメッセージ:fix
	* ソース変更内容：機能3　コミットメッセージ:fix

* 変更後
	* ソース変更内容：機能1 機能2 機能3　コミットメッセージ:機能1,2,3を追加

**1.ワークディレクトリの内容はそのままでコミットだけを取り消す** 
変更前のコミット3件を、内容そのままでコミットを取り消します。

```bash:bash
$git diff # ステージされていることを確認
$git reset --soft HEAD~3 #「HEAD~3」で、頭から3つ目のコミットを対象に取り削除
$git reset # 上記のコマンドを反映
Unstaged changes after reset:
M	test.txt
$git diff # ワークディレクトリはそのままで、コミットだけ取り消されていることを確認
diff --git a/test.txt b/test.txt
index edd13ee..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,6 @@
 aaaa
 bbbb
 cccc
+機能1
+機能2
+機能3
```
**2.変更内容をステージ**

```bash:bash
$git add test.txt #機能1,2,3の内容をステージに上げる
$git diff # ステージされていることを確認
$
```
**3.変更内容をコミット**

```bash:bash
$git commit -m "機能1,2,3を追加"
[develop e9bd9fa] 機能1,2,3を追加
 1 file changed, 3 insertions(+)
```
**4.綺麗なコミットになっているか確認**

```bash:bash
$git log -p -1
commit e9bd9fa56cd0c494157379714f75751bb9f525f4 (HEAD -> develop)
Author: hoge <hogehoge@gmail.com>
Date:   Sun Apr 22 20:04:19 2018 +0900

    機能1,2,3を追加

$diff --git a/test.txt b/test.txt
index edd13ee..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,6 @@
 aaaa
 bbbb
 cccc
+機能1
+機能2
+機能3
```

## CASE2:適当なコミットを削除して、粒度を変えてコミットを作る
次はCASE1同様コミット削除後、粒度を変えてコミットを作ります。

* 変更前
	* ソース変更内容：機能1　コミットメッセージ:fix
	* ソース変更内容：機能2　コミットメッセージ:fix
	* ソース変更内容：機能3　コミットメッセージ:fix

* 変更後
	* ソース変更内容：機能1　コミットメッセージ:機能1を追加
	* ソース変更内容：機能2 機能3　コミットメッセージ:機能2,3を追加

**1.ワークディレクトリの内容はそのままでコミットだけを取り消す**
 
変更前のコミット3件を、内容そのままでコミットを取り消します。(CASE1の1.と同様)

```bash:bash
$git diff # ステージされていることを確認
$git reset --soft HEAD~3 ##「HEAD~3」で、頭から3つ目のコミットを対象に取り削除
$git reset # 上記のコマンドを反映
Unstaged changes after reset:
M	test.txt
$git diff # ワークディレクトリはそのままで、コミットだけ取り消されていることを確認
diff --git a/test.txt b/test.txt
index edd13ee..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,6 @@
 aaaa
 bbbb
 cccc
+機能1
+機能2
+機能3
```

**2.機能1をステージする**

```bash:bash
$git add -p
diff --git a/test.txt b/test.txt
index edd13ee..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,6 @@
 aaaa
 bbbb
 cccc
+機能1
+機能2
+機能3
Stage this hunk [y,n,q,a,d,/,e,?]? 
```
「e」を押すと、vimが起動します。

```vim:vim
  1 # Manual hunk edit mode -- see bottom for a quick guide.
  2 @@ -1,3 +1,6 @@
  3  aaaa
  4  bbbb
  5  cccc
  6 +機能1
  7 +機能2
  8 +機能3
  9 # ---
 10 # To remove '-' lines, make them ' ' lines (context).
 11 # To remove '+' lines, delete them.
 12 # Lines starting with # will be removed.
 13 # 
 14 # If the patch applies cleanly, the edited hunk will immediately be
 15 # marked for staging.
 16 # If it does not apply cleanly, you will be given an opportunity to
 17 # edit again.  If all lines of the hunk are removed, then the edit is
 18 # aborted and the hunk is left unchanged.
```
機能2,3の内容は、このコミットに入れないので、7行目と8行目を削除します。

```vim:vim
  1 # Manual hunk edit mode -- see bottom for a quick guide.
  2 @@ -1,3 +1,6 @@
  3  aaaa
  4  bbbb
  5  cccc
  6 +機能1
  7 # ---
  8 # To remove '-' lines, make them ' ' lines (context).
  9 # To remove '+' lines, delete them.
 10 # Lines starting with # will be removed.
 11 # 
 12 # If the patch applies cleanly, the edited hunk will immediately be
 13 # marked for staging.
 14 # If it does not apply cleanly, you will be given an opportunity to
 15 # edit again.  If all lines of the hunk are removed, then the edit is
 16 # aborted and the hunk is left unchanged.
```
「:wq」で保存して、vimを終了します。
「git diff」機能1がステージされていることを確認します。

```bash:bash
$git diff
diff --git a/test.txt b/test.txt
index 75df11b..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -2,3 +2,5 @@ aaaa
 bbbb
 cccc
 機能1 # 冒頭の「+」がなく、ステージされていることを確認
+機能2
+機能3
```

**3.機能1の追加をコミット**

```bash:bash
$git commit -m "機能1を追加"
[develop a508d3f] 機能1を追加
 1 file changed, 1 insertion(+)
```
コミットの内容を確認

```bash:bash
$git log -p -1
commit a508d3fed953e2acfbf50dc4aaa26c04f8802c44 (HEAD -> develop)
Author: hoge <hoge@gmail.com>
Date:   Sun Apr 22 20:59:34 2018 +0900

    機能1を追加

diff --git a/test.txt b/test.txt
index edd13ee..75df11b 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,4 @@
 aaaa
 bbbb
 cccc
+機能1
```
**4.機能2,3をステージする**

```bash:bash
$git diff # ステージされていない差分を確認
diff --git a/test.txt b/test.txt
index 75df11b..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -2,3 +2,5 @@ aaaa
 bbbb
 cccc
 機能1
+機能2
+機能3
$git add test.txt # 全てステージする
$
```

**5.機能2,3の追加をコミット**

```bash:bash
git commit -m "機能2,3を追加"
[develop acebca1] 機能2,3を追加
 1 file changed, 2 insertions(+)
```
**6.コミットの確認**

```bash:bash
$git log -p -2
commit acebca166dd8dac70ffd60ee9d9b2563a30dae78 (HEAD -> develop)
Author: hoge <hoge@gmail.com>
Date:   Sun Apr 22 21:07:04 2018 +0900

    機能2,3を追加

diff --git a/test.txt b/test.txt
index 75df11b..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -2,3 +2,5 @@ aaaa
 bbbb
 cccc
 機能1
+機能2
+機能3

commit a508d3fed953e2acfbf50dc4aaa26c04f8802c44
Author: hoge <hoge@gmail.com>
Date:   Sun Apr 22 20:59:34 2018 +0900

    機能1を追加

diff --git a/test.txt b/test.txt
index edd13ee..75df11b 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,4 @@
 aaaa
 bbbb
 cccc
+機能1
```


## CASE3:既存のコミットを利用して、まとまったコミットを作る
変更前、変更後内容は、CASE1と同様です。
既存のコミットを削除せずに、コミットをまとめます。
なので、CASE2の変更後のようなコミットも作成できます。(今回は省略します。)
既存コミットの粒度に問題がない場合は、このパターンを使うのが良いかと思います。
(変化がわかりずらい例で申し訳ありません。)

* 変更前
	* ソース変更内容：機能1　コミットメッセージ:fix
	* ソース変更内容：機能2　コミットメッセージ:fix
	* ソース変更内容：機能3　コミットメッセージ:fix

* 変更後
	* ソース変更内容：機能1,2,3　コミットメッセージ:機能1,2,3を追加

**1.コミット内容を確認**
変更前に記載したようなコミットになっています。

```bash:bash
git log -p -3
commit 134e1100bfdf67b908701c6cd6b9a2f75103af64 (HEAD -> develop)
Author: hoge <hoge@gmail.com>
Date:   Sun Apr 22 21:43:37 2018 +0900

    fix

diff --git a/test.txt b/test.txt
index fb97bfc..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -3,3 +3,4 @@ bbbb
 cccc
 機能1
 機能2
+機能3

commit 0bdb007a79a2bca3f88712daf240801f75e66be4
Author: hoge <hoge@gmail.com>
Date:   Sun Apr 22 21:43:23 2018 +0900

    fix

diff --git a/test.txt b/test.txt
index 75df11b..fb97bfc 100644
--- a/test.txt
+++ b/test.txt
@@ -2,3 +2,4 @@ aaaa
 bbbb
 cccc
 機能1
+機能2

commit a349c9b1f4cdca4cb31a5ede7197f623501dda27
Author: hoge <hoge@gmail.com>
Date:   Sun Apr 22 21:43:08 2018 +0900

    fix

diff --git a/test.txt b/test.txt
index edd13ee..75df11b 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,4 @@
 aaaa
 bbbb
 cccc
+機能1

```

**2.コミットをまとめてステージ**

```bash:bash
$git rebase -i HEAD~3
```

上記のコマンドを実行すると、vimが起動します。

```vim:vim
  1 pick a349c9b fix
  2 pick 0bdb007 fix
  3 pick 134e110 fix
  4 
  5 # Rebase f91c687..134e110 onto f91c687 (3 commands)
  6 #
  7 # Commands:
  8 # p, pick = use commit
  9 # r, reword = use commit, but edit the commit message
 10 # e, edit = use commit, but stop for amending
 11 # s, squash = use commit, but meld into previous commit
 12 # f, fixup = like "squash", but discard this commit's log message
 13 # x, exec = run command (the rest of the line) using shell
 14 # d, drop = remove commit
 15 #
 16 # These lines can be re-ordered; they are executed from top to bottom.
 17 #
 18 # If you remove a line here THAT COMMIT WILL BE LOST.
 19 #
 20 # However, if you remove everything, the rebase will be aborted.
 21 #
 22 # Note that empty commits are commented out
```

まとめたいコミットの前についている「pick」を「fixup」もしくは「f」に変更します。
ここでは、ソース変更内容が「機能1」のコミットに「機能2」「機能3」のコミットをまとめるため、2行目と3行目の修正を行います。

```vim:vim
  1 pick a349c9b fix
  2 f 0bdb007 fix
  3 f 134e110 fix
  4 
  5 # Rebase f91c687..134e110 onto f91c687 (3 commands)
  6 #
  7 # Commands:
  8 # p, pick = use commit
  9 # r, reword = use commit, but edit the commit message
 10 # e, edit = use commit, but stop for amending
 11 # s, squash = use commit, but meld into previous commit
 12 # f, fixup = like "squash", but discard this commit's log message
 13 # x, exec = run command (the rest of the line) using shell
 14 # d, drop = remove commit
 15 #
 16 # These lines can be re-ordered; they are executed from top to bottom.
 17 #
 18 # If you remove a line here THAT COMMIT WILL BE LOST.
 19 #
 20 # However, if you remove everything, the rebase will be aborted.
 21 #
 22 # Note that empty commits are commented out                                             
```
「:wq」で保存して、vimを終了します。
「git log -p -1」でコミットがまとめられているか確認します。

```bash:bash
git log -p -1
commit 41c7e22324b8c125c44e8629013f5ea330dcbdc3 (HEAD -> develop)
Author:hoge <hoge@gmail.com>
Date:   Sun Apr 22 21:43:08 2018 +0900

    fix

diff --git a/test.txt b/test.txt
index edd13ee..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,6 @@
 aaaa
 bbbb
 cccc
+機能1
+機能2
+機能3
```

**3.コミットメッセージを変更**
上記の通り、コミットメッセージがまだ「fix」なので変更を行います。

```bash:bash
$git commit --amend
```

またしてもvimが起動します。

```vim:vim
  1 fix
  2 
  3 # Please enter the commit message for your changes. Lines starting
  4 # with '#' will be ignored, and an empty message aborts the commit.
  5 #
  6 # Date:      Sun Apr 22 21:43:08 2018 +0900
  7 #
  8 # On branch develop
  9 # Your branch is ahead of 'origin/develop' by 1 commit.
 10 #   (use "git push" to publish your local commits)
 11 #
 12 # Changes to be committed:
 13 #       modified:   test.txt
 14 #
```

1行目の「fix」を削除して、コミットメッセージを書き換えます。

```vim:vim
  1 機能1,2,3を追加
  2 
  3 # Please enter the commit message for your changes. Lines starting
  4 # with '#' will be ignored, and an empty message aborts the commit.
  5 #
  6 # Date:      Sun Apr 22 21:43:08 2018 +0900
  7 #
  8 # On branch develop
  9 # Your branch is ahead of 'origin/develop' by 1 commit.
 10 #   (use "git push" to publish your local commits)
 11 #
 12 # Changes to be committed:
 13 #       modified:   test.txt
 14 #                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
```

「:wq」で保存して、vimを終了します。

```bash:bash
$git commit --amend
[develop 3bff337] 機能1,2,3を追加
 Date: Sun Apr 22 21:43:08 2018 +0900
```

「git log -p -1」でメッセージが変更されている確認します。

```bash:bash
$git commit --amend
[develop 3bff337] 機能1,2,3を追加
 Date: Sun Apr 22 21:43:08 2018 +0900
 1 file changed, 3 insertions(+)
takahashihoge:deploytest$git log -p -1
commit 3bff33745cf0c7becea0724380719886e989bf95 (HEAD -> develop)
Author: hoge <hoge@gmail.com>
Date:   Sun Apr 22 21:43:08 2018 +0900

    機能1,2,3を追加

diff --git a/test.txt b/test.txt
index edd13ee..f44ffcd 100644
--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,6 @@
 aaaa
 bbbb
 cccc
+機能1
+機能2
+機能3

```

## 参考
https://qiita.com/kansiho/items/2bacecdb95d752cb38b7

## 最後に
趣味プログラムでもコミットは綺麗にしてからプッシュしよ。。。