# gh stack unstack --local vs Regular unstack: What's the Difference?

> Understand the gh stack unstack --local vs regular unstack difference. Learn when to use local-only removal versus coordinated GitHub and local updates.

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

---

**The `--local` flag forces `gh stack unstack` to only remove the stack entry from your local `.git/gh-stack` file without contacting GitHub, while the default command orchestrates a coordinated removal from both the remote GitHub Stacks API and local tracking.**

The `gh-stack` extension for the GitHub CLI provides powerful stack management capabilities for pull request workflows. When you need to dissolve a stack, understanding the difference between `gh stack unstack --local` and the regular `unstack` command is crucial for maintaining repository hygiene. This guide examines the implementation details in the `github/gh-stack` repository to explain exactly how these two modes diverge in their remote API interactions and local file system behavior.

## How the Regular unstack Command Works

The standard `gh stack unstack` command follows a **remote-first dissolution strategy**. According to the implementation in [`cmd/unstack.go`](https://github.com/github/gh-stack/blob/main/cmd/unstack.go), the command first attempts to contact the GitHub Stacks API via `client.Unstack` to dissolve the remote stack representation.

This operation includes safety checks: if some pull requests are queued for merge or have auto-merge enabled, the remote stack cannot be fully dissolved. In these cases, the command preserves the local tracking entry so you can continue working with the still-existing remote stack.

Only after successfully dissolving the remote stack does the command remove the entry from your local `.git/gh-stack` file using `sf.RemoveStack`. This ensures your local state remains synchronized with GitHub's representation.

### Handling Untracked Stack Numbers

When you provide a specific stack number that isn't tracked in your local file, the regular command falls back to `runRemoteUnstack`. This function performs a remote-first lookup and unstack operation, allowing you to dissolve stacks that exist on GitHub but may have been created on another machine.

## How unstack --local Changes the Behavior

Adding the **`--local`** flag fundamentally restricts the command to your local file system. In [`cmd/unstack.go`](https://github.com/github/gh-stack/blob/main/cmd/unstack.go), the code path checks this flag early and bypasses all GitHub API calls entirely.

Instead of `runRemoteUnstack`, the command uses `lookupStackByNumber` with the local-only constraint. If the stack isn't found in your local `.git/gh-stack` file, the operation aborts immediately with an error message stating the stack is not tracked locally. The flag explicitly prevents the fallback to remote lookups that the standard command employs.

With `--local`, the stack entry is simply deleted from the local JSON file using the same `sf.RemoveStack` method, but the remote stack on GitHub remains completely untouched and continues to exist independently of your local repository state.

## Key Differences at a Glance

- **Remote API Interaction**: The regular command calls the GitHub Stacks API via `client.Unstack` to dissolve remote stacks, while `--local` never contacts GitHub.
- **Local Tracking Removal**: Both modes eventually call `sf.RemoveStack`, but the regular command only does so after successful remote dissolution, whereas `--local` operates immediately on the local file.
- **Partial Unstack Handling**: The regular command preserves local tracking when remote dissolution fails (due to queued PRs or auto-merge), allowing continued interaction with the remote stack. With `--local`, no remote check occurs, meaning the remote stack persists unchanged while local tracking disappears.
- **Missing Stack Behavior**: Without the flag, untracked stack numbers trigger a remote lookup via `runRemoteUnstack`. With `--local`, missing local entries produce an immediate error.

## Practical Code Examples

Remove the current stack both locally and on GitHub:

```bash
gh stack unstack

```

Remove a specific stack by number, coordinating remote and local removal:

```bash
gh stack unstack 7

```

Remove only the local tracking while preserving the GitHub stack:

```bash
gh stack unstack --local

```

Attempt to locally unstack a number not tracked locally (this fails):

```bash
gh stack unstack --local 9

# Error: stack #9 is not tracked locally

```

## Implementation Details in the Source Code

The logic divergence resides primarily in [`cmd/unstack.go`](https://github.com/github/gh-stack/blob/main/cmd/unstack.go). The `runRemoteUnstack` function (lines 68-81) encapsulates the remote-first approach, calling the GitHub API client defined in [`internal/github/client_interface.go`](https://github.com/github/gh-stack/blob/main/internal/github/client_interface.go) before manipulating local state.

When `--local` is passed, the code bypasses `runRemoteUnstack` and instead relies on `lookupStackByNumber` with strict local constraints (lines 82-88). The local stack file operations are handled by [`internal/stack/stack.go`](https://github.com/github/gh-stack/blob/main/internal/stack/stack.go), which provides the `RemoveStack` method used in both code paths.

The command also respects modify session guards via [`internal/modify/state.go`](https://github.com/github/gh-stack/blob/main/internal/modify/state.go), ensuring no active modification session exists before allowing unstack operations in either mode.

## Summary

- **Regular `unstack`**: Coordinates removal from GitHub via API first, then cleans local `.git/gh-stack` file; handles partial dissolutions by preserving local tracking when remote removal fails.
- **`unstack --local`**: Restricts operation to local file only, never contacting GitHub; fails immediately if the stack isn't tracked locally.
- Both commands use `sf.RemoveStack` from [`internal/stack/stack.go`](https://github.com/github/gh-stack/blob/main/internal/stack/stack.go) for local file manipulation.
- The regular command supports remote fallback for untracked stack numbers via `runRemoteUnstack`, while `--local` enforces strict local presence requirements.

## Frequently Asked Questions

### Does `gh stack unstack --local` delete the stack on GitHub?

No. The `--local` flag explicitly prevents any GitHub API calls. According to the implementation in [`cmd/unstack.go`](https://github.com/github/gh-stack/blob/main/cmd/unstack.go), this mode only manipulates the local `.git/gh-stack` file using `sf.RemoveStack`, leaving the remote stack intact and accessible through the GitHub web interface or other API clients.

### What happens if I run `unstack --local` on a stack number that exists only on GitHub?

The command aborts with an error. When `--local` is specified, the code strictly enforces local presence through `lookupStackByNumber`. If the stack number isn't found in your local tracking file, you receive a "stack #N is not tracked locally" error, unlike the regular command which would fall back to remote operations.

### Why would I use the regular `unstack` instead of `--local`?

Use the regular command when you want to fully dissolve a stack and remove it from both GitHub and your local tracking. This ensures consistency between your local state and the remote repository, and respects GitHub's constraints regarding queued or auto-merging pull requests by preserving local tracking if remote dissolution fails.

### Can I recover a stack after running `unstack --local`?

Yes, but only the local tracking entry is gone. Since the `--local` flag never touches the GitHub Stacks API, the remote stack remains fully intact on GitHub. You can re-establish local tracking by fetching the stack information again, assuming you know the stack number or can locate it in the GitHub UI.