rebase -i でコミットをまとめる

複数のコミットを1つにまとめるとき、いつも [「5. rebase -i でコミットをまとめる」](http://www.backlog.jp/git-guide/stepup/stepup7_5.html) を参考にしてるんだけどメモしておく。

## rebase -i

rebase -i でコミットを4コミット分まとめます。（~を4つ）

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

または

```bash
$ git rebase -i HEAD~4
```

するとテキストエディタ(たいていvim)が開き、HEADから4つ分のコミットが表示されます。

```bash
pick 8145f1c Fix screen rotation problem
pick d90db4a v1.2.4
pick 646bf79 Fix screen rotation problem
pick 71a6940 v1.2.4

# Rebase ed7420a..71a6940 onto ed7420a
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
```

ここでは同じコミットメッセージの「8145f1c」と「646bf79」、「d90db4a」と「71a6940」をまとめます。
順序変更を含めて次のように、`pick`を`s`または`squash`へ変更します（今回は`s`）。

```bash
pick 8145f1c Fix screen rotation problem
s 646bf79 Fix screen rotation problem
pick d90db4a v1.2.4
s 71a6940 v1.2.4

# Rebase ed7420a..71a6940 onto ed7420a
...
```

するとコミットメッセージを統合するためのエディタが2回開きます。

例えば1つ目は次のように、修正します。

```
# This is a combination of 2 commits.
# The first commit's message is:

Fix screen rotation problem

# This is the 2nd commit message:

Fix screen rotation problem

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Not currently on any branch.
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   app/src/main/java/jp/takke/datastats/LayerService.java
#
```

↓

```
Fix screen rotation problem
# ...
```

これでコミットがまとまりました。

## git log で確認

```bash
$ git log -2
commit 0fdbb3d37c0f793ed3f93f0600fdc3d90972f050
Author: takke <takke30@gmail.com>
Date:   Tue Mar 3 17:07:27 2015 +0900

    v1.2.4

commit 3735ff495d700822f237997f925c33746861438d
Author: takke <takke30@gmail.com>
Date:   Tue Mar 3 17:07:08 2015 +0900

    Fix screen rotation problem
```

このようにハッシュ値は新たな値が割り振られますが変更日時はpickのほう(各squashの1つ前のコミットのほう)になります。

## git push -f

あとはリモートリポジトリに push するわけですが、コミットハッシュが変わるので -f が必要です。

※言うまでもないですが共同開発のリモートリポジトリ・ブランチに安易に ```git push -f``` するのは御法度ですよ。

```bash
$ git push
...
To git@github.com:takke/TkTrafficMonitorSample.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:takke/TkTrafficMonitorSample.
git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

```bash
$ git push -f
...
Counting objects: 26, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (13/13), done.
Writing objects: 100% (15/15), 1.34 KiB, done.
Total 15 (delta 9), reused 0 (delta 0)
To git@github.com:takke/TkTrafficMonitorSample.git
 + d90db4a...0fdbb3d master -> master (forced update)
```

以上です。


## 参考文献

- [5. rebase -i でコミットをまとめる【チュートリアル3 コミットを書き換えよう！】 | サルでもわかるGit入門 〜バージョン管理を使いこなそう〜 | どこでもプロジェクト管理バックログ](http://www.backlog.jp/git-guide/stepup/stepup7_5.html)
- [gitのコミットの歴史を改変する(git rebase) 1 / 2 - けんごのお屋敷](http://tkengo.github.io/blog/2013/05/16/git-rebase-reference/)