# How gh-stack Manages Stack Updates When Base Pull Requests Are Merged

> gh-stack automatically manages stack updates when base PRs merge, rebasing downstream branches to keep your linear stack in sync. Learn how it works.

- Repository: [GitHub/gh-stack](https://github.com/github/gh-stack)
- Tags: how-to-guide
- Published: 2026-08-03

---

**When a base PR in a gh-stack chain is merged, the tool automatically detects the merged state, skips closed ancestors, and rebases downstream branches onto the new base to maintain a linear stack.**

Merging the bottom pull request in a stacked chain traditionally forces manual rebasing for every subsequent branch. The `github/gh-stack` CLI solves this through automated detection and rebase logic that preserves stack integrity without manual intervention.

## Detecting Merged Base Pull Requests

The update process begins by refreshing the state of every PR in the stack via the GitHub API. In [`cmd/utils.go`](https://github.com/github/gh-stack/blob/main/cmd/utils.go), the helper function `stackNeedsRebase` inspects each pull request's metadata to determine if it requires updating.

The function specifically checks for the `NeedsRebase` flag and explicitly filters out any PRs that are already **merged** or **closed**. This prevents the tool from attempting to rebase branches that have already been integrated into the default branch, as implemented around line 1194 in [`cmd/utils.go`](https://github.com/github/gh-stack/blob/main/cmd/utils.go).

## Resolving the New Base After a Merge

Once merged PRs are identified, gh-stack must determine where to attach the remaining branches. The core logic resides in `resolveRebaseBase` within [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) (around line 192).

This function walks up the stack hierarchy looking for the first *non-merged* ancestor. When it encounters a merged PR, it treats that merged commit as the new effective base and continues ascending until it finds either the next unapplied PR or the repository's default branch. The algorithm ensures that downstream branches rebase onto the actual commit that entered the mainline, not onto the PR branch that no longer exists.

The test suite validates this behavior in [`cmd/rebase_test.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase_test.go) with `TestRebase_MergedBranch_UsesOnto` (line 633), confirming that merged ancestors are correctly skipped during the rebase target resolution.

## Executing Stack Updates via Rebase or Fast-Forward

After identifying the correct new base, gh-stack applies the changes through [`internal/modify/apply.go`](https://github.com/github/gh-stack/blob/main/internal/modify/apply.go). Around line 409, the apply logic distinguishes between fast-forward scenarios (where the merge was a simple fast-forward) and full interactive rebases.

The tool executes `git rebase` operations only for branches that are not already merged, ensuring that closed PRs remain untouched while active branches receive clean, linear history. This phase also handles branch pointer updates and conflict detection before rewriting history.

## Handling Merge Queue Integration

For repositories utilizing GitHub's merge queue, gh-stack respects queue ordering to prevent invalid states. The detection logic in [`internal/github/merge_async.go`](https://github.com/github/gh-stack/blob/main/internal/github/merge_async.go) (around line 207) identifies when a PR is managed by the merge queue via GraphQL API calls.

When a base PR is merged through the queue, subsequent PRs are rebased onto the *queued* target rather than the final merged commit. This ensures that the stack remains valid according to the merge queue's sequencing constraints, preventing premature rebases that could conflict with pending queue operations.

## Practical Examples: Updating Your Stack After a Base PR Merge

When the bottom PR of your stack merges into the default branch, use the following workflow to synchronize the remaining branches:

```bash

# Refresh the stack state from GitHub

$ gh stack sync

# Automatically rebase remaining PRs onto the new base

$ gh stack rebase

```

For programmatic usage within Go applications interacting with gh-stack internals:

```go
// Resolve the current stack configuration
stack, target, err := resolveMergeStack(cfg, client, []string{})
if err != nil { 
    log.Fatal(err) 
}

// Merge the target PR asynchronously; downstream PRs will be rebased automatically
res, err := client.MergeStackAsync(target.prNumber, "squash", github.MergeActionDirectMerge)

```

After successful execution, the stack metadata stored in `.git/gh-stack` is updated via [`internal/stack/stack.go`](https://github.com/github/gh-stack/blob/main/internal/stack/stack.go) to reflect the new branch relationships and base commit SHAs.

## Summary

- **Automatic Detection**: The `stackNeedsRebase` function in [`cmd/utils.go`](https://github.com/github/gh-stack/blob/main/cmd/utils.go) identifies merged or closed PRs and excludes them from rebase operations.
- **Smart Base Resolution**: `resolveRebaseBase` in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) walks the stack to find the first non-merged ancestor, using merged commits as the new rebase target.
- **Selective Rebase Execution**: [`internal/modify/apply.go`](https://github.com/github/gh-stack/blob/main/internal/modify/apply.go) performs rebases only on active branches, preserving merge queue order and avoiding rewritten history for closed PRs.
- **Merge Queue Support**: [`internal/github/merge_async.go`](https://github.com/github/gh-stack/blob/main/internal/github/merge_async.go) detects merge queue participation and adjusts rebase targets to respect queue sequencing.

## Frequently Asked Questions

### How does gh-stack detect when a base PR has been merged?

The tool queries the GitHub API during `gh stack sync` operations to refresh each PR's state. The `stackNeedsRebase` helper in [`cmd/utils.go`](https://github.com/github/gh-stack/blob/main/cmd/utils.go) examines the `merged` and `closed` status flags, returning early for any PRs that have already been integrated into the default branch.

### What happens to downstream PRs when the base is merged?

Downstream PRs are automatically rebased onto the new base commit. The `resolveRebaseBase` function identifies the merged PR's final commit SHA and treats it as the new base for subsequent branches, ensuring the stack remains linear and attached to the mainline history.

### Does gh-stack support GitHub's merge queue?

Yes. When [`internal/github/merge_async.go`](https://github.com/github/gh-stack/blob/main/internal/github/merge_async.go) detects that a PR is part of GitHub's merge queue, the rebase logic adjusts to target the queued merge commit rather than the current default branch head. This preserves queue validity and prevents conflicts with pending merges.

### Where does gh-stack store updated stack metadata?

After successful rebasing, the tool writes the new stack configuration—including updated base SHAs and branch relationships—to the local metadata file managed by [`internal/stack/stack.go`](https://github.com/github/gh-stack/blob/main/internal/stack/stack.go), typically located at `.git/gh-stack` within the repository root.