この記事は最終更新日から1年以上が経過しています。

@mikene_koko

初心者が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 が必要みたいですね。というかさっきよりメッセージが詳しくなってるw

$ 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のバージョンが古い場合は気をつけよう!

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
mikene_koko
言語絞らずなんでも投稿しているのでカオスです

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
Azure IoTに関する記事を投稿しよう!
~
Qiita 10周年記念イベント - 10年前の自分に伝えたい、勉強しておきたかった技術
~