github / github/gh-stack

Design: separate a stacked PR's merge target from its base

Open
#157 0 comments 2 reactions 0 assignees View on GitHub
feature request topic: ui
Dominant language
Go
Stars
1.5k
Forks
70
Avg merge
1d 8h
Merged PRs (30d)
7

Description

From [Overview / What Is a Stack?](https://github.github.com/gh-stack/introduction/overview/#what-is-a-stack):

> A pull request stack consists of two or more pull requests in the same repository where:
>
> - The first (bottom) pull request targets the main branch (e.g., main).
> - Each subsequent pull request targets the branch of the PR below it.
```
┌── feat/frontend → PR #3 (base: feat/api-endpoints) ← top
┌── feat/api-endpoints → PR #2 (base: feat/auth-layer)
┌── feat/auth-layer → PR #1 (base: main) ← bottom
main (trunk)
```

[endquote]

_Merging to the base branch is fundamentally wrong for this._ In your example here, `api-endpoints` is not logically *part of* `auth-layer`, so should not merge to it. You should separate "base" and "target" (e.g. `main`, `super-feature`, etc). Normally all branches in a stack will merge to the same target.

You already track "target" as distinct from base - your own [Overview](https://github.github.com/gh-stack/introduction/overview/#what-is-a-stack) states each PR is evaluated for rules and protections using "its final target branch (e.g., `main`), not the branch it directly targets." So the concept exists; it's just confined to rule evaluation and discarded everywhere else. Promote it to a first-class merge destination.

Result should be something like:

```
$ git log --all --graph --decorate --pretty=oneline --abbrev-commit
* 043bf03 (HEAD -> main) Merge pull request #2 from username/feat/2
|\
| * 88624f8 (feat/2) Feature 2
* | 39f3460 Merge pull request #1 from username/feat/1
|\|
| * 0f1e961 (feat/1) Feature 1
|/
* 04a9dac Initial commit
```

Related, I made the [same point to Git Butler](https://github.com/gitbutlerapp/gitbutler/issues/10936), but they're constrained by the existing GitHub implementation. But you are GitHub, now deciding the next implementation - not constrained.

Along with this, the implementation should display and enforce "below" branches in the stack as prerequisites. `feat/2` should be blocked from merging until `feat/1` has merged. You'll have to make this explicit, instead of just a side effect of merging to the base branches.

Contributor guide

Open the contributing guide

Research direction

Start with the linked Overview / What Is a Stack? description and trace how gh-stack currently represents final targets, base branches, and merge behavior. Define the separate merge destination and explicit prerequisite behavior for stacked branches, then verify that the resulting history matches the example and that upper branches cannot merge before lower ones.

Written by the indexing model from the issue text.

Assessment

Tech stack
github, go
Domain
cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.