github / github/gh-stack

`gh stack push` resolves an empty remote and silently pushes nothing when `branch.<name>.remote` is `.`

Aperta
#412 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
bug topic: cli - push
Lingua principale
Go
Stelle
1.5k
Fork
70
Merge medio
1g 8h
PR unite (30g)
7

Descrizione

## Summary

When a stack branch's `branch..remote` is `.` (the local repository), `gh stack push` resolves the push remote to an **empty string**, pushes nothing, and reports success:

```
$ gh stack push
Pushing 2 branches to ....
✓ Pushed 2 branches
To create PRs for this stack, run `gh stack submit`

$ git ls-remote --heads origin | grep probe
# nothing — no ref was created
```

Note the blank remote name between "to" and the ellipsis. Exit status is 0.

`gh stack submit` then fails PR creation, but the error describes a *state* problem rather than the push failure that caused it, and the run still ends on a success line:

```
$ gh stack submit --auto
Checking stack state...
Pushing to ....
⚠ failed to create PR for probe-one: creating PR: GraphQL: Head sha can't be blank,
Base sha can't be blank, No commits between main and probe-one,
Head ref must be a branch (createPullRequest)
✓ Pushed and synced 2 branches
```

This is a single-remote repository. `origin` is the only remote, and it is correct.

## Root cause

`branch..remote = .` is a normal git configuration meaning "the upstream is a local branch". Anyone with **`branch.autoSetupMerge = always`** in their git config gets it automatically on every `git switch -c` from a local branch — which is exactly how a stack is built, so every branch in the stack has it.

Remote auto-detection appears to read `branch..remote`, find `.`, and yield an empty remote name rather than falling back to the single remote / `origin`.

Isolated by toggling it:

| `branch.autoSetupMerge` | `branch..remote` | `gh stack push` | branches pushed |
|---|---|---|---|
| `always` | `.` | `Pushing 2 branches to ....` | **0** |
| unset | unset | `Pushing 2 branches to origin...` | 2 |

Also fixed by setting `remote.pushDefault = origin`; unsetting it reproduces the failure again, deterministically.

## Reproduction

```bash
git config --global branch.autoSetupMerge always # or set it locally

git switch main
git switch -c probe-one && echo p1 > p1.txt && git add . && git commit -m "p1"
git switch -c probe-two && echo p2 > p2.txt && git add . && git commit -m "p2"
git switch probe-one

git config --get branch.probe-one.remote # -> .
gh stack init probe-one probe-two
gh stack push # "Pushing 2 branches to ...." / "✓ Pushed 2 branches"
git ls-remote --heads origin | grep probe # -> nothing
```

Public repo with two stacks set up for this: https://github.com/xn/gh-stack-repro

## Expected

- Fail loudly when the push remote cannot be resolved, rather than pushing to an empty remote name.
- Never print `✓ Pushed N branches` unless refs actually moved — report per-branch results, and exit non-zero when nothing was pushed.
- Treat `branch..remote = .` as "no usable remote for this branch" and fall back to the single remote / `origin` / `remote.pushDefault`.

## Workaround

`gh stack push --remote origin`, or `git config remote.pushDefault origin`.

## Environment

- `gh` 2.97.0
- `gh-stack` v0.1.0
- git 2.50.1
- macOS 26.4.1, darwin/arm64

## Related

Same GraphQL error signature as #219 and #381, but a different root cause — those are about which *repository* the API calls target in multi-remote/fork clones. This one is a single-remote clone where the *push target itself* resolves to empty and no ref is ever created. #45 is a third variant (SSH host alias); ruled out here — the failure reproduces with a plain `https://` remote and a pristine global config.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia dall’auto-rilevamento dei remote e dai percorsi di push utilizzati da `gh stack push`, quindi confronta la loro gestione di `branch..remote = .` con i casi di un singolo remote e di `remote.pushDefault`. Riproduci il problema utilizzando i comandi e il repository descritti sopra e verifica che i remote non risolti falliscano in modo esplicito, che venga segnalato l’effettivo spostamento delle ref e che lo stato di uscita sia diverso da zero quando non è stato eseguito alcun push.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
git, github, go
Ambito
cli
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
55/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.