github / github/gh-stack

gh stack rebase --continue doesn't report new conflicts hit while resuming a multi-commit branch rebase

オープン
#430 コメント 1 件 リアクション 2 件 担当者 0 名 GitHub で見る
bug topic: cli - rebase
主要言語
Go
スター
1.5k
フォーク
70
平均マージ
1日 8時間
マージ済み PR(30日)
7

説明

## Summary

`gh stack rebase --continue` only prints `Conflicted files:` listing for first conflict encountered when cascading one stacked branch onto another. If resolving that conflict and continuing causes git to hit a second conflict on a later commit within the same branch's replay, the tool does not report what files are now conflicted and just returns a generic wrapped error.

This can make it look like there's only one conflicted file when there are actually more. You can only see the other conflicts by manually running `git status`.

## Steps to reproduce

1. Create a stack with a branch containing at least two commits and at least two files, where:
- Commit A modifies `file1.txt` so that there's a conflict with the (rebased) parent branch.
- Commit B later modifies `file2.txt` so that it also conflicts with the parent branch, independently of commit A.
2. Rebase the stack
3. The tool stops on commit A's conflict and correctly prints:
```
Conflicted files:
C file1.tsx (lines N–M)
```
4. Resolve `file1.txt`, stage it, run `gh stack rebase --continue` again.
5. Git internally applies commit B next, which conflicts on `file2.txt`.

## Expected behavior

Step 5 should print the same kind of `Conflicted files:` block, listing `file2.txt` with its conflict line numbers, like step 3 did for `file1.txt`.

## Actual behavior

Step 5 prints a generic error:
```
rebase continue failed — resolve remaining conflicts and try again: exit status 1
```

No indication of which file(s) are now conflicted. The only way to discover where the new conflict is is running `git status` manually.

## Proposed solution / notes

I'll be honest, not familiar with Go so this "solution" is mostly Claude. I did double check that it looks at least mostly right to me. Figured it might be helpful.

> Traced this to `cmd/rebase.go` and `internal/git/git.go`:
>
> - `printConflictDetails()` / `printConflictDetailsWithContinue()` (`cmd/rebase.go:545`) is the function that formats the `Conflicted files:` block with per-file conflict-marker line numbers (via `git.FindConflictMarkers`). It's only called from the branch-to-branch **cascade** logic, at `cmd/rebase.go:259` and `:435`.
> - `continueRebase()` (`cmd/rebase.go:312`) has a separate path for resuming an *already in-progress* `git rebase` within a single branch's multi-commit replay:
> ```go
> if git.IsRebaseInProgress() {
> rebaseOpts := git.RebaseOpts{CommitterDateIsAuthorDate: state.CommitterDateIsAuthorDate}
> if err := git.RebaseContinue(rebaseOpts); err != nil {
> return fmt.Errorf("rebase continue failed — resolve remaining conflicts and try again: %w", err)
> }
> }
> ```
> This path never calls `printConflictDetails`.
> - Following `RebaseContinue` (`internal/git/gitops.go:334`) into `tryAutoResolveRebase` (`internal/git/git.go:118`), the conflicted-files list is actually fetched — just to check whether `rerere` already auto-resolved everything — and then discarded on the way out:
> ```go
> conflicts, err := ConflictedFiles()
> if err != nil {
> return originalErr
> }
> if len(conflicts) > 0 {
> return originalErr // <-- conflicts is right here and gets thrown away
> }
> ```
>
> **Fix**: in `continueRebase`, when `git.RebaseContinue` returns an error, call `printConflictDetailsWithContinue` (using the still-in-progress rebase's current conflicted files, e.g. by calling `git.ConflictedFiles()` again, or by threading `tryAutoResolveRebase`'s local `conflicts` slice out through the error) before returning, instead of just wrapping the raw error string. That gives resume-mid-branch conflicts the same reporting as cascade-boundary conflicts.

## Environment

- `gh` version: 2.97.0 (2026-07-31)
- `gh-stack` extension: `github/gh-stack` v0.1.0
- OS: macOS Tahoe 26.5.1

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

cmd/rebase.go の continueRebase から始め、その進行中のパスを printConflictDetailsWithContinue と比較します。次に internal/git/gitops.go の git.RebaseContinue と internal/git/git.go の tryAutoResolveRebase を追跡し、gh stack rebase --continue で複数コミットにまたがる競合フローを再現します。後続の競合で、汎用エラーだけでなく現在の Conflicted files ブロックが報告されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
git, go
領域
cli
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
72/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。