初心者がgit rebase使って格闘した記録

git便利だけど難しい。ということでrebaseをつかわざるを得ないタイミングが合ったので実践したメモ。
参考：https://qiita.com/ykawakami/items/0d6826c529ad7c7b37dd

# 現象
コミットにミスがあった。10個コミットがあったとして、コミット2はどこからか紛れ込んできたミスである。
邪魔なのでrevertするコミットを2回に分けて、コミット4、コミット5としてコミットした。
その後、コミット2が正しい開発内容でリリースしたら内容が反映されない。自分がコミット4とコミット5をrevertしたせいだ。
履歴がカオスになってきたので、コミット2の取り込みと、コミット4/コミット5のrevertの履歴自体を取り消す。

```
コミット10
コミット9
コミット8
コミット7
コミット6
コミット5 ←これ
コミット4 ←これ
コミット3
コミット2 ←これ
コミット1 
```

# 実践

git rebaseを使って直してみる。

```
$ git rebase -i [コミット1]
Interactive rebase already started
```

既にrebaseが始まっている？？開幕から思ってたのと違う感じに。一旦abortします

```
$ git rebase --abort
```

再度実行

```
$ git rebase -i [コミット1]
Press Enter or type command to continue

pick [コミット0] [bugfix]...

# Rebase 
#
# 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
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
```

rebaseコマンド叩いてから1分くらい待たされました。長いですね。
うまくいったっぽく見えたんですけど、pickに表示されてるコミット履歴が全部 [コミット1]よりも過去のもの。何か失敗したかな？一旦 `:q` でvimモードを脱出します。

```
$ git log --oneline
コミット0
```

コミット1より上のコミットが全部消えました。ﾅﾝﾃｺｯﾀｲ
一旦reflogで戻ります

```
$ git reflog
$ git reset --hard HEAD HEAD@{1}
$ git log --oneline
コミット10
コミット9
...
```
よかった、戻りました。怖い怖い

調べてみたら、一旦ここでコミット1よりも前のものを取り込んでから、随時rebaseしていく感じらしいです。調べ不足でした。
再度リベンジ

```
$ git rebase --abort
$ git rebase -i [コミット1]

何もせず保存

Automatic cherry-pick failed.  After resolving the conflicts,
mark the corrected paths with 'git add <paths>', and
run 'git rebase --continue'
Could not apply ...
```

うわぁなんかコンフリクトしてますね。めんどくさい予感。
解決します。

```
$ git status
Not currently on any branch.

both modified: 
both added:    
```

なんか今いるブランチが不明扱いになってますね。怖くなってきた
とりあえず2件差分がでたので、コンフリクトを解消させます。
その後は、コメントに書いてある通りに `git rebase --continue` を実行

```
$ git rebase --continue
```

ここで再度めちゃくちゃコンフリクトがおきます。
思っていた挙動と違いますし、怖くなってきたので一旦またreflogで戻りました。

## なんか調べてた挙動と違うけど？
rebaseコマンドの表示されるコミットも、削除するためのdropコマンドもでてないんだけど。。
もしかして？と思ってversion確認

```
$ git --version
git version 1.7.1
```
やばい多分これめちゃくちゃ古いですね、適当にyumで入れた弊害がでてきました
調べてみたらgit version1.7.1 のリリースは 2010/04/24らしいです。これ使うの色々とよくないですね
gitの最新確認してみたら2.10～以降のバージョンがありました https://github.com/git/git/releases

バージョンアップを試してみます。 https://qiita.com/sirone/items/2e233ab9697a030f1335
怖いので、Dockerコンテナを1つ複製してgitの現状のコードをリモートリポジトリにアップしておきました。
これでぶっ壊れても安心だぜ！

自分の環境はCentOS6.6です。

```
$ sudo yum remove git
$ sudo yum install gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
$ wget https://www.kernel.org/pub/software/scm/git/git-2.2.0.tar.gz
$ tar -zxf git-2.2.0.tar.gz
$ cd git-2.2.0
$ make prefix=/usr/local all
$ make prefix=/usr/local install
$ git --version
git version 2.2.0                 
```

OK、再挑戦します

```
$ git rebase -i e9909a0

It seems that there is already a rebase-merge directory, and
I wonder if you are in the middle of another rebase.  If that is the
case, please try
        git rebase (--continue | --abort | --skip)
If that is not the case, please
        rm -fr "/var/www/smart/.git/rebase-merge"
and run me again.  I am stopping in case you still have something
valuable there.
```

また --abort が必要みたいですね。というかさっきよりメッセージが詳しくなってるｗ

```
$ git reset --abord
$ git log --oneline
コミット-10
```

なんかめちゃくちゃ前の履歴に戻されました？もう嫌だ・・・
諦めずにとりあえずreflogで戻ります。

再再挑戦

```
$ git rebase -i [コミット1]

pick git [コミット2]
pick git [コミット3]
...
pick git [コミット10]
```

うおおおおおおきたぞ！いらないコミットの行を削除して保存します。

```
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
```

コンフリクトしました。まぁこれは仕方ない。普通に修正します

```
vim ○○.pm # コンフリクト修正
git add ○○.pm
```

rebaseを再開します

```
git rebase --continue
```

またコンフリクトしました。

```
$ git status
deleted by them: hoge.pm
```

なんすかこれ・・・始めて見たステータス。
参考：https://qiita.com/yuya_presto/items/5d99499cf96c0ebb09f8

マージ元で削除された場合のコンフリクトパターンだとこのステータスになるらしいです。
関係ない話で申し訳ないですが、初めて知ったのでメモ。

```
$ git rm hoge.pm
```

continueします

そして…

```
Successfully rebased and updated [ブランチ名]
```

やったぜ。rebaseできました。 ログを確認します

```
$ git log --oneline
コミット10
コミット9
コミット8
コミット7
コミット6
コミット5
コミット3
コミット1 
```
うげ、コミット5を消し忘れました。
もう一回rebaseします。

```
$ git rebase -i [コミット6]
```

コミット5を消して保存。そしたら

```
The previous cherry-pick is now empty, possibly due to conflict resolution.              
If you wish to commit it anyway, use:                                                    
                                                                                         
    git commit --allow-empty                                                             
                                                                                         
Otherwise, please use 'git reset'                                                        
rebase in progress; onto 6c1d39e                                                         
You are currently rebasing branch 'feature/JIRA_2482_develop' on '6c1d39e'.              
                                                                                         
nothing to commit, working directory clean                                               
```

また新キャラ。前回のrebaseで空のcherry-pickがあるとか言ってきてますね。
とにかくコミットするなら(OKなら) `git commit --allow-empty` しろって言ってるので叩きます。

```
$ git commit --allow-empty
```

コミットできました。rebase続けます。 continue

```
Successfully rebased and updated [ブランチ名]
```

やったぜ。今度こそ完了です。

# 結論
gitのバージョンが古い場合は気をつけよう！