みの雑多ブログ

勉強したことをアウトプットしたり、しなかったり

コンフリクト解消するときに競合したブランチの修正内容が反映されてしまう

ブランチ

  • main
  • dev
  • ops/test_a
  • ops/test_b

手順

f:id:yamami78651:20210219024104p:plain

  • mainからブランチを切ってdev、ops/test_a、ops/test_bを作成
  • ops/test_bでファイルの追加、既存ファイルの修正
  • ops/test_bの変更をコミット&プッシュ
  • プルリク&マージ dev ← ops/test_b
  • ops/test_aでファイルの追加、既存ファイルの修正(bと同じファイル)
  • ops/test_aの変更をコミット&プッシュ
  • プルリク dev ← ops/test_a // conflict発生
  • conflictの解消(※)&マージ
  • プルリク main ← ops/test_a

(※)の詳細な手順

競合発生するのでweb editorリンク or resolve conflictsをクリック
競合しているファイルを修正
競合発生
Files Changedを確認すると、ops/test_aで追加・修正したファイル、競合ファイルが差分として表示される

競合が解消されてるので、このままコミット

ops/test_aを見ると、ops/test_bで追加したファイルが追加されている

困ったこと

  • (※)のコンフリクト解消時にops/test_bの対応が含まれないようにしたいが、conflictの解消をGitHubから行うとops/test_bの修正内容も含まれてしまう
  • 混在していることに気づかない(気づけない)

なぜ含まれるか、なぜ気づけないか

conflictの解消をGitHubから行うととしているが、別にGitHubで作業していることが原因ではない。
conflictの解消を行う作業として、ops/test_aにdev(マージ先)をマージしている。
※マージしに行く前に、相手の最新の状態を自分に取り込んでおいてマージする

この時に、devに既にマージされているops/test_bの情報が取り込まれてしまう
プルリクのFiles Changedにもdevとops/test_aにops/test_bに関する差分がないので、もちろん表示されず
仕組みを理解していないと思わぬものが混在してしまう

解決策

ひとまずの対応

プルリク main ← ops/test_aまでにこの事象に気づかず、ops/test_a、ops/test_bどちらも数回変更が加わり、devにプルリク&マージしていた。
revertしてもエラーになってうまくいかず、乏しいGItの知識と差し迫るリリース時間に焦り、以下のようにした。

  • ops/test_aは諦める
  • conflictの解消前(ops/test_aの変更をコミット&プッシュしたとき)のコミットでブランチ(ops/test_c)を切る
  • ops/test_aで変更した内容をops/test_cに加える
  • プルリク main ← ops/test_c

イケてないので、できればconflict解消後にすぐ修正しておくか、そもそも修正内容が混ざらないようにしたい。

競合解決をローカルで実施

ローカルでdevをマージ

$ git merge dev
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
CONFLICT (add/add): Merge conflict in files/testa/index.html
Auto-merging files/testa/index.html
Auto-merging files/index.html
CONFLICT (content): Merge conflict in files/index.html
Automatic merge failed; fix conflicts and then commit the result.

エディタでtestbが見つかる(混入に気づける)
f:id:yamami78651:20210219002745p:plain
コマンドのほうでももちろん気づける

$ git status
On branch ops/test_a
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:
        modified:   files/testa/index.html
        new file:   files/testb/index.html

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   files/index.html
        both modified:   index.html

正しく修正する

~~~~コミット~~~~

混入せずに、マージできるが、ops/test_bの修正内容は当然消える。
ので、再度ops/test_bの修正内容をコミットする必要がありそう。
これで気づかずにマージしてしまうことは防げそうなので、GitHubでコンフリクト解消するよりも、そもそもローカルで解消するほうがよさそう。
わかっていれば、GitHubでもよきかな。

(追記)混在したマージコミットをrevertする

そもそもマージコミットさえrevertできれば、よかったと気づいた

$ git revert -m [1or2] [マージコミットのハッシュ値] 

1と2間違えたな~って時は以下で元に戻す

$ git reset --hard HEAD~

revertできなかった理由は、①SourceTreeを使っていたことと②マージコミットであったことが原因そう
SourceTreeでrevertをすると、コマンドを自動生成してくれるけど、通常コミット用のrevertコマンドのようでうまくいかない。
マージコミットには普通のコミットと違って親コミットが2つあるから、どっちの方をrevertするんだい!ってなってしまう。
SourceTreeをうまく使えばできるのかもしれないが、やっぱりコマンドがよさそう。