# Functional Difference Between --downstack and --upstack in gh-stack rebase

> Understand the functional difference between gh-stack --downstack and --upstack rebase flags. Limit cascade-rebasing to specific branches and manage your stack efficiently.

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

---

**The `--downstack` flag rebases from the trunk up to and including your current branch, while `--upstack` rebases from your current branch up to the top of the stack, allowing you to limit cascade-rebase operations to specific portions of your branch stack.**

The `gh-stack` extension for GitHub CLI provides powerful stack-based workflows for managing dependent pull requests. When reorganizing your stack with `gh stack rebase`, understanding the functional difference between `--downstack` and `--upstack` lets you control exactly which branches get rebased without affecting the entire stack.

## What --downstack and --upstack Do

### Rebasing with --downstack

When you execute `gh stack rebase --downstack`, the command rebases **all branches from the trunk (the first branch in the stack) up to and including your current branch**. According to the source code in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) at lines 70-78, this implementation keeps `startIdx` fixed at `0` (the trunk position) while setting `endIdx` to `currentIdx + 1`.

### Rebasing with --upstack

Conversely, `gh stack rebase --upstack` rebases **your current branch and every branch above it to the top of the stack**. In [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) (lines 70-78), this sets `startIdx` to `currentIdx` while keeping `endIdx` at the full length of the stack slice.

### Default Full-Stack Behavior

If you supply neither directional flag, `gh stack rebase` processes the **entire stack** from trunk to top, using the full range of stack indices.

## Implementation Details in cmd/rebase.go

The core index manipulation logic resides in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) between lines 70-78. The implementation evaluates which directional flag is present and adjusts the slice boundaries accordingly:

- **With `--downstack`**: `startIdx` remains `0`, `endIdx` becomes `currentIdx + 1`
- **With `--upstack`**: `startIdx` becomes `currentIdx`, `endIdx` remains `len(stack)`

These flags are **mutually exclusive**; the command rejects simultaneous use of both options since they specify conflicting range constraints.

## Integration with --no-trunk

The directional flags respect the `--no-trunk` option (lines 77-80 in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go)). When combining `--upstack` with `--no-trunk`, the rebase starts from your current branch but skips rebasing onto the trunk itself, effectively shifting the start index forward by one position.

## Practical Usage Examples

The help text defined in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) (lines 64-68) provides these concrete examples:

```bash

# Rebase the entire stack (default behavior)

gh stack rebase

# Rebase only the "down-stack": trunk → ... → current-branch

gh stack rebase --downstack

# Rebase only the "up-stack": current-branch → ... → top-of-stack

gh stack rebase --upstack

# Combine with --no-trunk to avoid rebasing onto the trunk branch

gh stack rebase --upstack --no-trunk

```

Test cases in [`cmd/rebase_test.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase_test.go) verify that `--downstack` limits rebasing to branches up to the current branch and that `--upstack` correctly limits operations to branches from the current branch upward.

## Summary

- **`--downstack`** limits rebasing to the trunk through your current branch by setting the end index to `currentIdx + 1` while keeping the start at `0` in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go).
- **`--upstack`** limits rebasing to your current branch through the top of the stack by setting the start index to `currentIdx` while keeping the end at the stack length.
- Both flags override the default full-stack behavior and are mutually exclusive.
- When combined with `--no-trunk`, the start index shifts forward to skip the trunk branch (lines 77-80).

## Frequently Asked Questions

### What happens if I use both --downstack and --upstack together?

The flags are mutually exclusive, and `gh stack rebase` will reject this combination. The command logic in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) treats these as conflicting options since they specify opposite directional constraints on the rebase range.

### How does --no-trunk interact with these directional flags?

When `--no-trunk` is combined with `--upstack` or `--downstack`, the rebase range respects the directional limit but skips rebasing onto the trunk itself. This shifts the effective start index forward by one position, as implemented in lines 77-80 of [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go).

### Where is the stack index logic defined?

The stack indexing utilities, including the `IndexOf` method used to determine `currentIdx`, are defined in [`internal/stack/stack.go`](https://github.com/github/gh-stack/blob/main/internal/stack/stack.go). The rebase command imports these utilities to calculate slice boundaries in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go).

### Can I use these flags with other gh stack commands?

The `--downstack` and `--upstack` flags are specific to the `rebase` subcommand. They appear only in [`cmd/rebase.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase.go) and [`cmd/rebase_test.go`](https://github.com/github/gh-stack/blob/main/cmd/rebase_test.go), limiting their scope to cascade-rebase operations within the `gh-stack` workflow.