Skip to content

fix(repo-hygiene): git-tree-reset runs clean -fdx even when reset --hard failed (partial destructive op) #394

Description

@kyle-sexton

Summary

In git-tree-reset.sh --apply, git clean -fdx runs unconditionally after git reset --hard, with no check on the reset's exit status. If the reset fails, the destructive clean still executes — a partial operation that deletes untracked/ignored files without the tree having been realigned.

Component

plugins/repo-hygiene/skills/clean/scripts/git-tree-reset.sh.

Root cause

184  git reset --hard "$UPSTREAM"
...
187  CLEAN_STDERR="$(git clean -fdx "${PRESERVE_ARGS[@]}" 2>&1 >/dev/null)"

The script runs under set -uo pipefail (no -e), and line 184's exit status is never inspected before line 187 runs. Any reset failure (the @{u} case in the companion issue, a locked index, a bad ref, an interrupted fetch) drops straight through to clean -fdx.

Evidence (this session)

The 6 repos that hit fatal: ambiguous argument '@{u}' at the reset step still proceeded to run git clean -fdx and reported AppliedClean: git clean -fdx (+1 preserve excludes). Net effect: cleaned but not reset.

Impact

Destructive clean -fdx executes in a state the reset was supposed to establish. For a tool whose contract is "reset to upstream then clean," running clean without a successful reset violates the invariant and can surprise the user (untracked work removed while the tree is not at the intended commit).

Expected

clean -fdx runs only if reset --hard succeeded. On reset failure: abort the apply, report the failure honestly, run no clean.

Acceptance criteria

  • Capture and check the reset exit status; on non-zero, skip clean and the restore-guard, print an explicit failure line, exit non-zero.
  • No AppliedReset:/AppliedClean: success lines emitted when the underlying command failed (see companion output-integrity issue).
  • Regression test: force a reset failure and assert clean did not run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: highSignificant impact, or blocks an imminent release; staff this cycle.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions