[patch] Unstage with reset so it works before the first commit - #143
Merged
Merged
Conversation
Unstage() built `git restore --staged -- <path>` on git 2.23 and later. With no --source, restore reads the index back from HEAD, so in a repository with no commits yet it exited 128 with "could not resolve HEAD", and ExecuteAsync threw. That is exactly when a user is most likely to have staged too much. GitRestoreBuilder now always builds `git reset -q -- <path>`. It unstages a committed path and leaves a never-committed one untracked, on every supported git, so the version probe and the reset HEAD fallback go away. Fixes #122 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PNmrp6FP3tBU47owLsiovc
|
This was referenced Sep 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Unstage(path)now works in a repository that has no commits yet. Before this, it failed every time there:ExecuteAsyncthrewGitCommandException("fatal: could not resolve HEAD") andTryExecuteAsyncreturnedSuccess = false.Cause
On git 2.23 and later,
GitRestoreBuilderbuiltgit restore --staged -- <path>. With no--source,restore --stagedreads the index back fromHEAD, and on an unborn branchHEADdoesn't resolve.Fix
GitRestoreBuildernow always buildsgit reset -q -- <path>, the option the triage recommended:HEADinto the index, which is whatrestore --stageddid.ProbeVersionAsync, theExecuteAsync/TryExecuteAsyncoverrides) and thereset HEADfallback unnecessary, so they're removed.-qstopsresetprinting its "Unstaged changes after reset" list.--separator stays, so a dash-leading path is still safe; checked against git 2.43 with a file named-dash.The public surface is unchanged:
IGitRestoreBuilderandGitRepository.Unstage. The builder class keeps its name because it's internal.Tests
New integration tests against real git (they ran here, none skipped):
UnstageBeforeTheFirstCommitLeavesTheFileUntrackedAsyncis the issue's acceptance case:Add().All()thenUnstageon an unborn branch. Neither call throws, and the file comes back untracked.UnstageAfterACommitRestoresTheIndexAndKeepsTheWorkingTreeAsyncguards the ordinary case. The staged change leaves the index and stays in the working tree.Unit tests:
GitRestoreBuilderTestsnow pins thereset -q -- <path>vector, the bare--, and a single invocation with no version probe.FallsBackToResetOnAGitOlderThanRestoreAsyncandTreatsExactlyTwoTwentyThreeAsSupportedAsync. The branch they tested no longer exists.Verification:
mainwith the issue's exact error,git exited with code 128: fatal: could not resolve HEAD, and passes with the fix.docs/superpowers/specs/2026-09-24-patch-verbs-design.mdstill describes the restore-plus-fallback design. I left it alone because it's a dated design record, not current documentation.Fixes #122
🤖 Generated with Claude Code
https://claude.ai/code/session_01PNmrp6FP3tBU47owLsiovc
Generated by Claude Code