Skip to content

Timeline says a stacked PR merged "into main" when it merged into the branch below it #523

Description

@ethanmckean

When a stacked pull request is merged into its own base branch (the layer below it) rather than the stack's trunk, its timeline says it was merged into the trunk: "merged commit <sha> into main". The trunk never received the commit. GitHub records the merge correctly (MergedEvent.mergeRefName is the layer below), so only the displayed branch is wrong.

The effect is that an unmerged change looks like it landed on the default branch.

Reproduction

  1. Create a two-PR stack: PR A (feature-a → main) and PR B (feature-b → feature-a), with feature-b built on feature-a.

  2. Fast-forward the bottom branch to the top branch's head with a plain push (no force push, no gh stack):

    git push origin <feature-b head>:refs/heads/feature-a
  3. GitHub marks PR B merged within a second, and deletes feature-b if "Automatically delete head branches" is on.

Actual

  • PR B's timeline reads "merged commit <feature-b head> into main".
  • main does not contain that commit (GET /repos/{owner}/{repo}/compare/main...<sha> shows it ahead of main).
  • PR A is still open against main, so the stack is left with its top layer merged and its bottom layer open.

Expected

The timeline names the branch PR B was merged into, feature-a. GitHub already stores it:

query {
  repository(owner: "OWNER", name: "REPO") {
    pullRequest(number: 2) {                             # PR B
      baseRefName                                        # "feature-a"
      stack { baseRefName }                              # "main"
      timelineItems(itemTypes: [MERGED_EVENT], first: 1) {
        nodes { ... on MergedEvent { mergeRefName } }    # "feature-a"
      }
    }
  }
}

Public example

unicode-org/icu4x-docs#85, (taken from the stacked PRs feedback discussion) is the same case. It is the second layer of a stack whose trunk is main, and its base is script-improvements. It was marked merged when its base branch was pushed to include its head (base_ref_force_pushed in the same second as merged, and the recorded merge commit is the PR's head). Its timeline reads "merged commit b1ec50a into main", while MergedEvent.mergeRefName is script-improvements, and b1ec50a is not in main.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions