# What Is the Difference Between `gh stack submit` and `gh stack push`?

> Discover the difference between gh stack push and gh stack submit. Learn how push synchronizes branches while submit pushes branches and manages PRs and GitHub stacks.

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

---

**`gh stack push` only synchronizes local branches to the remote repository, whereas `gh stack submit` performs that push operation and additionally creates or updates Pull Requests and the GitHub stack that groups them.**

The `github/gh-stack` extension introduces structured branch management for GitHub CLI users. Understanding the **difference between `gh stack submit` and `gh stack push`** is essential for effective workflow management, as these commands serve distinct stages of the stacked pull request lifecycle.

## Core Functional Differences

### `gh stack push`: Remote Synchronization Only

This command focuses exclusively on moving local commits to the remote. According to the source code in [`cmd/push.go`](https://github.com/github/gh-stack/blob/main/cmd/push.go), its short description reads: `Short: "Push active branches in the current stack to the remote"` (lines 21-23).

The implementation in the `runPush` function (lines 81-115) performs the following:

- Identifies the **active stack** containing the current branch
- Skips branches marked as merged or queued
- Pushes remaining active branches using **force-with-lease** protection
- Updates the local stack file with new base SHAs
- Displays a hint suggesting `gh stack submit` for PR creation

Crucially, this command **never** changes the checked-out branch and does not interact with GitHub's PR or Stacks API.

### `gh stack submit`: Full Stack Publication

Described in [`cmd/submit.go`](https://github.com/github/gh-stack/blob/main/cmd/submit.go) (lines 33-35) as `Short: "Create a stack of PRs on GitHub"`, this command orchestrates complete stack publication.

The `runSubmit` function executes a multi-stage workflow:

1. Performs all `push` operations (pushing branches with force-with-lease)
2. Launches an **interactive TUI** (or runs in `--auto` mode) for drafting PR titles, bodies, and draft status
3. Creates new PRs or updates base branches of existing ones
4. Creates or updates the remote stack via the **GitHub Stacks API**, handling edge cases like adopting existing stacks or recovering from modify states
5. Persists changes to the local stack file

Like `push`, it leaves the current checkout unchanged.

## Source Code Architecture

The architectural separation is clear in the implementation files.

In [`cmd/push.go`](https://github.com/github/gh-stack/blob/main/cmd/push.go), the logic remains minimal:

```go
func runPush(cfg *config.Config, opts *pushOptions) error {
    // … load stack, discover active branches …
    activeBranches := activeBranchNames(s)
    // … fetch remote refs, then push with force‑with‑lease …
    if err := git.Push(remote, activeBranches, true, false); err != nil { … }
    // … update stored base SHAs and persist the stack file …
    updateBaseSHAs(s)
    if err := stack.Save(gitDir, sf); err != nil { … }
}

```

In contrast, [`cmd/submit.go`](https://github.com/github/gh-stack/blob/main/cmd/submit.go) (lines 27-31 and 47-52) extends this foundation:

```go
func runSubmit(cfg *config.Config, opts *submitOptions) error {
    // … load stack, resolve remote …
    // 1️⃣ Push all branches (same logic as push)
    // 2️⃣ Create or update PRs (ensurePR / createPR)
    // 3️⃣ Update PR bases if needed
    // 4️⃣ Create or update the remote stack (syncStack)
    // … persist changes and report success …
}

```

## When to Use Each Command

Use **`gh stack push`** when:

- You have rebased branches and need to update remote refs without opening PRs
- You want to resolve push conflicts before creating pull requests
- You need quick synchronization with `--force-with-lease` safety

Use **`gh stack submit`** when:

- You are ready to create the initial stack of PRs on GitHub
- You need to synchronize PR bases after adding new commits to the stack
- You want to use the interactive editor (`--auto` for non-interactive) to customize PR titles and draft status

## Command Examples

Push branches only after rebasing:

```bash

# Push active branches with force-with-lease protection

gh stack push

# Push to a specific remote

gh stack push --remote upstream

```

Submit the complete stack:

```bash

# Interactive mode with TUI for PR details

gh stack submit

# Auto-generated PR titles (non-interactive)

gh stack submit --auto

# Create PRs as ready for review (not drafts)

gh stack submit --open

```

Both commands can execute from any branch within a stack without changing your checkout.

## Summary

- **`gh stack push`** performs **only** remote branch synchronization using force-with-lease, updates local base SHAs, and skips merged branches.
- **`gh stack submit`** executes the push operation **plus** creates/updates PRs, manages PR base branches, and synchronizes the remote GitHub stack via API.
- **Neither command** changes the currently checked-out branch.
- **Push** is ideal for syncing work-in-progress; **submit** is required for GitHub PR creation and stack management.

## Frequently Asked Questions

### Does `gh stack submit` run `gh stack push` automatically?

Yes. According to the implementation in [`cmd/submit.go`](https://github.com/github/gh-stack/blob/main/cmd/submit.go), the submit command performs all push operations first—including the force-with-lease protected push and base SHA updates—before proceeding to PR and stack creation.

### Can I use `gh stack push` to update existing PRs?

No. The `push` command only updates remote branch refs. It does not interact with the GitHub API or modify PR metadata, titles, or base branches. Use `gh stack submit` to update PR bases and metadata.

### Will either command switch my current branch?

No. Both commands operate entirely on the stack file and remote refs without modifying your working directory checkout. You can run them from any branch within the stack.

### What happens to merged branches when running these commands?

Both commands automatically skip branches that are marked as merged or queued. The active branch detection logic filters these out before pushing to the remote, ensuring you only synchronize relevant work-in-progress branches.