Open1

git rebaseのconflictはgit mergeのとは一味ちがうぜ

TommyTommy

本文

  • まず実体験で、git rebaseの仕様を勘違いして作業がおじゃんになった話をする。

    作業していたブランチで操作していたファイルが、developブランチでも更新されていた。
    なので、git rebaseをしてコミットを綺麗に繋ぎ直したい。
    
    ここで、人生で初めてgit rebaseでconflictをするという経験をした。
    
    conflictなんてgit mergeでしかしたことがないから、ただただconflictを直していた。
    
    しかし、何か違和感があった。作業ブランチで加えた修正がところどころ反映されていなかったからだ。
    愚かな私は、違和感はあるものの、そのまま作業して正しく動くところまでコードを変更していった。
    

    この違和感の正体はというと、developとconflictを起こしていたのが、作業ブランチの1つ目のコミットであったということ。
    git mergeでは常に最新コミットでconflictを修正するようになっている。
    作業ブランチで4つほどのコミットをした後に、developとgit rebaseをすると、4つのうちの1つ目のコミットに戻った状態でconflictを直していたことになる。
    これが、git mergeとgit rebaseの違いである。

    つまり私はタイムスリップして「developtとのconflictを直す作業」+「元の作業ブランチで4つ中3つの同じ作業」をしていたこととなる。

    ここで、私はgit abortしてgit rebaseを中断してしまった。これまたやらかしである。この失態をどう言い訳しようか。まるで兄にゲームを貸してもらい途中でセーブせずに電源を切ってしまった時のような子供のように脳の全リソースを言い訳に割り当て考えた末、正直にgit rebaseの途中でgit abortしたら差分が全て飛びました。と報告を完遂した私である。
    そこはさすが我が上司。この上なくお人好しで知的で理知的なお方であるが故、「git rebaseでconflictしたことがなかったら、git mergeと勘違いしてcommitなんて意識しないですよね〜ww。いや〜、でもこれで勉強になりましたね。」
    ちょちょぎれんばかりの涙を堪えながら、変わることのないタスクの期日に怯え私は作業に戻るのである。

まとめ

git mergeとは違い、git rebaseではconflictした際にはconflictが起こったコミット時点まで戻った状態でconflictを直したらすぐにgit rebase --continueをしてコミットを更新するべき。

検証

実行するべきコマンドを列挙していきますが、先にその意図を書いておきます。
まず全ての起点のブランチを作ります。
そこから2つのブランチhoge、fugaを切り分けます。
それぞれで3つほどコミット(1,2,3,4,5,6)を作ります。
その後、fugaをhogeにrebaseします。
この時、ただのgit rebaseではなく、それぞれのコミットで止まるようにオプションをつけます。それが-iというオプションです。
すると、それぞれのコミットで実際のgit rebaseの操作が止まっていることが確認できるかと思います。

mkdir git_training 
cd $_
git init
vi main.txt
>> hello
git add .
git commit -m "first commit"

ここまでで大元になるブランチを作成

以下が各ブランチを作成

git checkout -b hoge
vi hoge.txt
>> hello hoge1
git add .
git commit -m "hoge1"
vi hoge.txt
>> hello hoge2
git add .
git commit -m "hoge2"
vi hoge.txt
>> hello hoge3
git add .
git commit -m "hoge3"

上記の一覧をfugaにしてもう一つのブランチを作成。

以下で、hogeにfugaをrebaseしていく

git rebase -i hoge
すると以下のような編集画面が出てくるので、'pick''edit'に変更する。
![](https://storage.googleapis.com/zenn-user-upload/082bffcacb86-20231103.png)

こうすることで、editとかいたコミットで修正を止めることができる。

-----
ここでeditと書き換えたコミットがgit rebaseする際にconflictが必要になったコミットと同じ現象である。