【VSCode】コンフリクト解消でやったこと
最近参加したプロジェクトでmainブランチの変更を機能開発をしてたブランチに取り込んでおらず、開発を進めていたためfeatureブランチをマージする際にコンフリクトが起き、そのコンフリクトの解消対応を行いました。
正直なぜコンフリクトしているのか、どんなコードになってるのかも分からないのでコンフリクトを見てどの修正を取り込むべきなのかわからず、さすがに一人じゃ無理なので皆さんとなんとか頑張って解消しました。
まだ、6月から取り込んでいないだけで3ヶ月の差分なのでなんとかなった感はありますが、さらに前だったと思うと少し怖いですね。
コンフリクトをリグレッションなく解決するためのやり方は調べてもあまり出てこず、VSCodeを使って解消する際の気づきや分かったこと詰まったことなどを書き残して誰かの助けになればと思い書いているわけであります。 コンフリクトを解消するやり方は出てくるんですけどね、コンフリクトしている内容からどうやってその修正を取り込むべきなのかを考えたり調べたりするのがあまりない印象。
ワイはエディターにVSCodeを使用しているため、大体作業はVSCodeを使っています。 コミットを確認したりなどGit系のツールは拡張機能のGitLensを使っていますが、ちょっと長くなるのでまた別の記事にでも書こうかなと思ってます。
コンフリクト解消のためにやったこと
今回ワイはVSCodeだけでコンフリクトを解消していきました。
恥ずかしながら、今までずっと3-way mergeを知らずコンフリクトマーカー見て直せる量のコンフリクトだけだったので、コンフリクトマーカー消したりでなんとかしてました。
そのため3-way mergeなるものを初めて知り使いたいなと思っていたら、実はVSCodeでも3 way mergeが使えます。
そういえば確かにコンフリクト解消する時、右下に
Resolve Conflict
みたいなボタンがあったけどスルーしてた。
コンフリクトマーカーだけだとコードが全体的にどうなってるのかわかりづらいですが、3-way merge editorだとコンフリクトしている変更先と今の行そして、最終結果が下に表示されます。
画像は上記リンクの公式画像から取ってきました。
どちらの修正を適用させるのかまたCombinationは差分をいい感じに取り込んで反映してくれます。どんな原理で動いているのかは知らないですが
便利すぎるだろ、もっと早く知りたかった….となったのでまだ使ってない方は使ってみるといいかも。
あとは、3-way mergeを使いながら気合いで修正していきます。ワイは以下の流れで解消しました。
- すぐ治せそうなところから治す
- どんな意図で実装したのか探って何を残すべきか判断して直す
1. すぐ治せそうなところから治す
コンフリクトしているファイルをざっくり読んで、変更を取り込むだけで良い物など簡単に判断できそうなものから対応していきました。
判断基準は色々あると思いますが、書いてないと静的解析でエラーになったりするものに関してはそのまま必要だということがわかるためエラーにならないように追加するといった形ですね。
正直あまりそういうラッキーなコンフリクトがなかったんですが、そう言った形でいくつかコンフリクトファイルを最初に解消していきました。
2. どんな意図で実装したのか探って何を残すべきか判断して解消していく
「残すべきorそれとも上書きor消すべき、それとも良い感じに合わせるべき?」と、判断が難しいものはGitLensを使ってコミットやPRを見たりしながら最終的にどれを反映させるかを選んでいきました。
どちらのブランチでも機能追加をしている場合などどちらも残しておく必要があり、それに伴って変更しないといけない物がこれに当たるかなと思います。
主にどんな意図で実装したのかなんの修正をいつ行ったものかをVSCodeで確認していました。 ここからはどんな実装をしてきたかを確認するためにGitLensを使い、双方のコミットを見ていく作業が続きました。
コンフリクト解消時に悩んだこと特集
ファイルを修正しないといけない場合マージコミットに含めるべきなのか
コンフリクトを直していると、どうしてもコンフリクトマーカーを解消するだけでは動かないみたいな場合があります。
この時のファイル修正を別途切り出して修正すべきかどうかには結構悩みました。
私個人の意見としてはマージコミットに含めてもいいと思ってます。 というのもマージするのに当たって起きたコンフリクトでありそれはマージコミットないで完結させる話かなってのが主な理由です。
また、動いてない状態でマージコミットを作成するよりも動いている状態としてのコミットにするべきだと思うからです。
マージ終了後にリグレッションが起きてたり、エラーになってたりは別途修正コミットでもいい派。
どこまで修正したか何を修正したかわからない
コンフリクトを解消してステージに乗せていくとファイルが多いと何を修正したのかわからなくなります。
なんかあったらgit merge --abort
で戻せるので戻すのは楽なんですが、途中経過を知るのはむずい。
git pull origin main --rebase
での取り込みは微妙。
試してみたけど、これだと1つづつコンフリクトを解消していかないといけないし、当時の実装でコンフリクトが起きても最終的にどうなったかは分からなるので修正ごとに壊れそうであんまり良くない気がする。
そんなに大量にコンフリクトせずにマージコミットを作りたくないみたいな時に使うのが良さそう。
git rerere
を使って解決した結果を残すっててもあるんですが、その度に一度コミットして他のものは消したりしないといけないのでわかりづらい。
途中で記録みたいなのができないので休憩もできないため良いやり方あったら知りたい。
どっちが新しくてどちらを優先すべきかわからない
どちらかに上書きできるなら楽ですが、そういかない時もあると思います。 特に一番めんどくさかったのは片方ではコンポーネントを分割して修正し、もう片方では分割してないが修正はしている場合です。
コンポーネントが切り出されてそこで修正されてるブランチと、切り出されず修正されてるブランチだと変更差分を検出するのが難しかったりします。 そこら辺はコピー&ペーストして比較したりしてました。
どちらも修正しているからコンフリクトしてるけど何を優先して取り込むのか、combinationできない時どうするのか悩む。
書いてないとエラーになる変数とかだとわかりやすいのですが、フロントエンドだとコンポーネントで表示しているcssなどパッと見どちらを優先すべきなのかわかんないものなどが一番困りました。
コンフリクトを解消してもコンフリクトしてないところで壊れてることがある
これはGit的にコンフリクトではないので、そういうので壊れるのもあるのかとちょっと思いました。 たとえば、コンポーネントの引数を変えてたりすると使ってる側で修正してなければコンフリクトは起きないんですよね。
一応静的解析には引っかかるのでlint回せば見つかるかもしれないですが、気づかずbuildして初めて気づきましたね。
そのせいで、違うパラメーターに置き換わっていたり削除されていたりで勝手にリグレッションしてる場合がありました。
もはや、リグレッション不可避。
テストないと不安しかない
テストが特にないのでリグレッションを探すためには機能をすべて見ていかないといけないという不安感。
テストがないとリグレッションしているかすぐ分からないため改めてテストの重要性を認識できるいい機会でした。
今後テスト増やしていく予定なので、またこういう事態になった時テストがあるとどう感じるか楽しみです。
最終的には気合い
正直実装した本人でもなければ、テストがあるわけでもないのでリグレッションをなくすのは無理と割り切ってやるしかないのかもしれません。 そもそも定期的に変更を取り込むとかこんなにコンフリクトが起きる状態までほっとくのがよくないとは思います。
余談
世間はVSCodeのsticky scrollに沸いていますが、今diffEditorも熱いです。 試験的なためexperimentalでの設定になりますが、diff時にコードの折りたたみができたりとコンフリクトの差分見る時に便利だったのでよかったら使ってみてください。
"diffEditor.experimental.useVersion2": true,
"diffEditor.experimental.showEmptyDecorations": false, // 差分がないところを表示する
"diffEditor.experimental.showMoves": true, // 差分が移動したところを表示する
"diffEditor.hideUnchangedRegions.enabled": true, // 差分がないところを隠す
まとめ
VSCodeは色々できて楽しいですね。 使い慣れてきてもまだまだ発見があったりするのでワクワクするもっと公式みたらできること多そうだなって思います。 とにかく、アイコンだけあっても触らないことがほとんどだし検索しようにも単語を考えづらくてしんどい。もう少しコマンドにもホバーで説明やドキュメント紐づけてすぐにしれたら嬉しいな。
GitやVSCodeに精通してるわけではないのでもっと良いやり方があると思ってるのでぜひ何か思ったことあったらコメントしてください。 コメント欄どうやって出すのかわかりませんが。