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

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, 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 (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, the logic remains minimal:

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 (lines 27-31 and 47-52) extends this foundation:

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:


# 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:


# 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →