fix: use merge ref for PR discovery when push.default=simple#13011
fix: use merge ref for PR discovery when push.default=simple#13011
Conversation
…sh} fails
When `push.default=simple` (the default) and the local branch name differs
from the remote tracking branch name, `git rev-parse --abbrev-ref @{push}`
fails with "cannot resolve 'simple' push to a single destination". The
fallback code was using the local branch name as the remote branch name,
causing `gh pr view` and `gh pr status` to search for a non-existent branch.
This fix adds `PushDefaultSimple` to the condition that checks the merge ref
from branch config, so the correct remote branch name is used for PR
discovery. This is safe because at this point in the code, @{push} has
already failed — meaning simple mode could not resolve, so the merge ref
is the best source of truth for the remote branch name.
This is a regression from PR cli#9208 (commit 7fc35fd).
Fixes cli#12203
Fixes cli#7590
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
There was a problem hiding this comment.
Pull request overview
This PR fixes PR discovery for gh pr view / gh pr status when push.default=simple and the local branch name differs from the remote tracking branch name by falling back to branch.<name>.merge (merge ref) to determine the correct remote head branch.
Changes:
- Extend
tryDetermineDefaultPushTarget()to use the merge ref forpush.default=simple(in the@{push}-failed fallback path). - Update/refine unit tests to cover the
push.default=simplemerge-ref behavior, including a fork PR-style “local name != remote name” scenario.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
pkg/cmd/pr/shared/find_refs_resolution.go |
Uses merge ref to derive the remote branch name when push.default=simple and @{push} can’t be resolved. |
pkg/cmd/pr/shared/find_refs_resolution_test.go |
Adds coverage for push.default=simple and a fork/renamed-local-branch scenario. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // means the local branch name differs from the remote tracking branch name. In | ||
| // simple mode, git refuses to push when names differ, but for PR discovery we | ||
| // still want to use the remote branch name from the merge ref. |
There was a problem hiding this comment.
The rationale comment for the push.default=simple fallback says failing to resolve @{push} “means the local branch name differs from the remote tracking branch name”. PushRevision can fail for other reasons too (e.g., no upstream/push info configured), so this is stronger than what we can infer here. Suggest rewording to “can mean” / “in the mismatch case” and also updating the earlier function doc comment (above) that currently only mentions upstream/tracking as using branch.<name>.merge.
| // means the local branch name differs from the remote tracking branch name. In | |
| // simple mode, git refuses to push when names differ, but for PR discovery we | |
| // still want to use the remote branch name from the merge ref. | |
| // can mean the local branch name differs from the remote tracking branch name. In | |
| // that mismatch case, git refuses to push when names differ in simple mode, but for | |
| // PR discovery we still want to use the remote branch name from the merge ref. |
|
It's been a while since I built my mental model of all the different push default behaviour so forgive me.
If We're trying to honor git's defaults here, and it seems like if you want something else, you should find another way to indicate that. Lemme know your thoughts, like I said, it's been a while. Cheers. |
|
Note Responses generated with Claude Hey @williammartin, thanks for looking at this! Good question. The key thing is that
So your triangular workflow concern (merging from The only case where execution reaches the The most common scenario for this is |
|
To be clear, when I describe a triangular workflow, I'm describing triangular within a single remote where we merge from one branch and push to another. For example: In this case, with But pushes may be done explicitly e.g. You say:
But this is not true for the use case outlined above. With this PR, we would instead use |

Summary
When
push.default=simple(the default) and the local branch name differs from the remote tracking branch name (e.g.,feature-branch-forktrackingorigin/feature-branch),git rev-parse --abbrev-ref @{push}fails with "cannot resolve 'simple' push to a single destination".The fallback code in
tryDetermineDefaultPushTarget()was using the local branch name as the remote branch name, causinggh pr viewandgh pr statusto search for a non-existent branch likeowner:feature-branch-forkinstead of the correctowner:feature-branch.This fix adds
PushDefaultSimpleto the condition that checks the merge ref from branch config (branch.<name>.merge), so the correct remote branch name is used for PR discovery. This is safe because at this point in the code,@{push}has already failed — meaning simple mode could not resolve, so the merge ref is the best source of truth for the remote branch name.Common scenarios where this occurs:
main→main), causinggh pr checkoutto create a prefixed local branchgit checkout -b my-local-name origin/remote-name)Regression from
This is a regression from PR #9208 (commit 7fc35fd, merged Jan 2025, shipped in gh v2.85.0).
Fixes #12203
Fixes #7590