maya_shack
@maya_shack

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Git ブランチを複数のブランチにマージしようとしてコンフリクトが起きた場合にはマージできない

Q&A

Closed

Git ブランチを複数のブランチにマージしようとしてコンフリクトが起きた場合にはマージできない

いま動いているプロジェクトで、Git ブランチをこのように運用しています。

  • リポジトリは GitHub にある
  • main ブランチは本番環境にデプロイするためのもの
  • develop ブランチで開発する
    • 本番環境にデプロイするときには develop を main にマージし、main を本番環境にアップする

flow1.jpg

  • 必ず GitHub の PR を使ってマージする(c4 や c6)

  • develop ブランチの進行中に、急遽両方に適用したい修正が出た場合は、fix ブランチを作って main, develop の両方へマージする

    • fix ブランチは main, develop の共通の祖先から作る

flow2.jpg

flow3.jpg

flow4.jpg

  • その後 develop ブランチでの開発が完了したときに、develop を main にマージする。

    • develop には c8 が含まれていて、main にも c8 が含まれているが、同じ c8 であるため develop をマージしてもコンフリクトは起こらない(*1 と理解しています)
    • cherry-pick で両方に同じ修正を入れると、あとで develop を main にマージしたときコンフリクトが起きる(*2 と理解しています)ので、そうしていません

flow6.jpg

発生している問題・エラー

やりたいことは、c8 の増分だけを develop と main の両方に適用することです。のちに develop を main にマージしてもコンフリクトを起こさないように、です。

c8 の時点で fix を develop にマージしようとして、コンフリクトが発生したとします(c7 と c8 に同じ箇所への追記がある、など)。GitHub の Web 上の "Resolve conflicts" ボタンでの編集やコマンドラインでの解決は、develop ブランチを fix ブランチにマージしたのち fix を develop へマージします(*3 と理解しています)。

flow8.jpg

その後 fix ブランチから main ブランチへマージしようとすると、マージ元である fix ブランチには develop ブランチの内容が含まれており、c8 の差分だけを main にマージすることができません。main には開発中の develop の他の修正(c7)もマージされてしまいます。

  • PR でマージをするには、対象がブランチでなければならない(*4 と理解しています)

flow7.jpg

質問

  • *1 の理解は間違っているでしょうか?
  • *2 の理解は間違っているでしょうか?
  • *3 の理解は間違っているでしょうか?
  • *4 の理解は間違っているでしょうか?
  • 「両方のブランチに修正を適用したい場合、共通の祖先を持つコミットから fix ブランチを作る」という使い方は間違っているでしょうか?
  • コンフリクトの発生を回避することができない以上、「fix ブランチから複数のブランチに fix ブランチの修正だけをマージする」という使い方をするのは難しいのでしょうか?
  • これは「必ず PR でマージする」という制限がなければ可能なのでしょうか?
0

2Answer

develop には c8 が含まれていて、main にも c8 が含まれているが、同じ c8 であるため develop をマージしてもコンフリクトは起こらない(*1 と理解しています)

*1 の理解は間違っているでしょうか?

正しいです。

cherry-pick で両方に同じ修正を入れると、あとで develop を main にマージしたときコンフリクトが起きる(*2 と理解しています)

*2 の理解は間違っているでしょうか?

間違っています。
完全に同じ修正であれば、同じ場所に行われた修正はコンフリクトを起こしません。

GitHub の Web 上の "Resolve conflicts" ボタンでの編集やコマンドラインでの解決は、develop ブランチを fix ブランチにマージしたのち fix を develop へマージします(*3 と理解しています)。

*3 の理解は間違っているでしょうか?

正しいです。
GitHubのプルリクエストで作業すればそうなります。

PR でマージをするには、対象がブランチでなければならない(*4 と理解しています)

*4 の理解は間違っているでしょうか?

正しいです。

「両方のブランチに修正を適用したい場合、共通の祖先を持つコミットから fix ブランチを作る」という使い方は間違っているでしょうか?

完全に間違いとは言えません。どのような分岐のルールでレポジトリを運用するのかは自由です。
しかしgit-flowでは、mainブランチの最新コミットからhotfixブランチを作るルールになっています。

コンフリクトの発生を回避することができない以上、「fix ブランチから複数のブランチに fix ブランチの修正だけをマージする」という使い方をするのは難しいのでしょうか?

GitHubのプルリクエストでそれを実現することは難しいです。
GitHubのプルリクエストは1つのブランチから1つのブランチに修正をマージする機能です。

これは「必ず PR でマージする」という制限がなければ可能なのでしょうか?

はい。
gitコマンドで、developブランチにfixブランチをマージし、mainブランチにfixブランチをマージすることができます。

git checkout develop
git merge fix
git checkout main
git merge fix
2Like

Comments

  1. @maya_shack

    Questioner

    教えてくださりありがとうございます。

    追記:
    その後いろいろ試したり考えたりしてみて、私なりにこのような理解をしたという内容をまとめておきます。

    fix ブランチは main, develop の共通の祖先から作るしかしgit-flowでは、mainブランチの最新コミットからhotfixブランチを作るルールになっています。

    GitHubのプルリクエストを使ってhotfixをdevelopへマージしようとすると、これまでmainにマージしたコミットがhotfixブランチでの差分ではないのにPRにぶら下がってきます。
    →あとからPRを参照したときに、どのコミットがこのマージの修正なのかが分かりづらくなります。

    コンフリクトが発生してもPRでマージを継続すると、hotfixへのマージ+developへのマージになります。その後PRでhotfixからmainへhotfixのみをマージすることはできなくなります。(最初の質問に書いた内容と同じ)

    hotfixのコミットをdevelopへcherry-pickする

    developへのマージのプルリクエストを残すことができません。

    main用のhotfixブランチと、develop用のhoftixブランチを2つ作る(main用のhotfixブランチからcherry-pickする)

    どちらもGitHubのプルリクエストを使ってマージできますが、cherry-pickした部分の関係性が枝で表せず、graph上で関係が分かりづらくなります。

    回答に書いたやり方

    プルリクエストを残せますが、手順が面倒です。
    また、直接のpushを禁止しているブランチにはマージできません。

色々試して、以下の手順でプルリクエストを使ってできるできることがわかりました。

  • 前提
    関係するブランチは GitHub にプッシュされている(GitHub Web のプルリクエストで済むならそれで対応するルール)

  • GitHub Web から "New pull request" でプルリクエストを新規作成する
    "Can’t automatically merge." と言われても作る
    番号を控える

  • git コマンドでマージする

git switch develop
git merge --no-ff- fix // conflict が起きるマージ

編集して conflict を解消する

git add -u
git commit -m "Merge pull request #(番号) from fix"

conflict で一時中断しましたが、このコミットはマージコミットになります。

  • git コマンドで GitHub にプッシュする
git push

このプッシュにより、プルリクエストが Merged になります。
(Merged になる条件が、コミットメッセージに番号を振っているためか、Open なプルリクエストの対象ブランチと同じためか、定かではありません。)
いずれにしろ、あとで参照したときにコミットメッセージからプルリクエストを追えるよう、GitHub Web のプルリクエストで自動生成されるのと同様のコミットメッセージになるように書いています。

0Like

Your answer might help someone💌