⚙️

[GitHub] 勝手にmergedに切り替わるPRについて

2024/12/13に公開

GitHubを使った開発フローの中で、

「自分はマージを押した覚えがないのに、なぜか私がマージしたことになっているPRがある!」

ということがありました。

📘 現象の再現方法

  1. ブランチとPRを作成

    • test1 ブランチを作成し、コミットを追加してPushします。
    • さらに、test1を元にしてtest2ブランチを作成し、こちらにもコミットを追加してPushします。
    git checkout -b test1
    git commit --allow-empty -m "test1"
    git push
    git checkout -b test2
    git commit --allow-empty -m "test2"
    git push
    
  2. PRを作成

    • test1test2 それぞれのブランチについてPull Request (PR) を作成します。
  3. PRのマージ

    • test2のPRをマージすると、なぜかtest1のPRも自動的にmerged状態になることが確認されます。

🤔 なぜ自動的にマージされるのか?

この現象の理由は、Gitの仕組みとGitHubのPRの動作仕様にありそうです。

  • test2test1の「その後の状態のブランチ」であるため、test2main(もしくは対象のブランチ)にマージされると、test1の変更内容もすでに取り込まれたとみなされるからです。
  • その結果、GitHubは「test1のPRもすでにマージされた状態だ」と判断し、mergedの状態に自動的に切り替えます。

このとき自動で切り替わったPR1のマージの実行者には、PR2のマージを実行した人が記録されます。
そのため「自分はPR1をマージしていないのに、なぜかマージしたことになっている」と感じることがあります。

⚙️ GitHub Actionsの動作への影響

この仕様が面倒なのは、GitHub Actionsにも影響を与えるからです。

たとえば以下のようなYAML設定がある場合、PRがマージされたタイミングでtest1,test2それぞれを対象にしたアクションが2つ起動してしまいます。

on:
  pull_request:
    types:
      - closed
    branches:
      - main

jobs:
  # マージされたときのみ動くようにする
  check-merge:
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged == true
    steps:
      - name: Do something only if the PR was merged

「自動的にmergedに切り替わった」ことを判断するContext変数も探したのですが、現時点では存在しないようです。

そのため複数のActionが走るのが致命的な場合も、原則は運用でカバーするしかなさそうです。

Discussion