Skip to content

Instantly share code, notes, and snippets.

@benabraham
Created February 12, 2026 15:12
Show Gist options
  • Select an option

  • Save benabraham/592cefe3b99b44c265b16f8478283bc4 to your computer and use it in GitHub Desktop.

Select an option

Save benabraham/592cefe3b99b44c265b16f8478283bc4 to your computer and use it in GitHub Desktop.
description
Safely commit session changes without touching the staging area

Safe Commit (Parallel-Agent Safe)

$ARGUMENTS

This command commits your session's changes without modifying the git index - safe for parallel agent work.

Usage

  • /commit - Create a new commit
  • /commit amend - Amend into the commit these changes logically belong to (typically a commit from this session or solving the same problem; may not be HEAD if other agents committed in between)

Technique: Shadow Index

Uses GIT_INDEX_FILE environment variable to create a temporary index, leaving the real .git/index untouched.

Workflow

  1. Identify files to commit

    • List files YOU modified in this session (not other uncommitted changes)
    • Show the user what will be committed
  2. Run pre-commit on YOUR files only

    pre-commit run --files <file1> <file2> ...

    This is safe - formatters/linters only modify the specified files. (Type checkers, tests, etc. with pass_filenames: false run on all code but don't modify anything)

  3. Check documentation coverage

    A. Skip for trivial changes — if ALL changes are trivial (typo fixes, formatting, config tweaks, import reordering, dependency bumps, renaming without behavior change), print "Documentation check: skipped (trivial changes)" and move on.

    B. Check code-level docs — for significant changes (new functions/classes, API changes, complex logic), verify:

    • New or modified functions/classes have docstrings matching the project's existing style
    • Complex logic blocks have inline comments explaining why
    • Record any gaps found

    C. Discover and check project docs — dynamically discover the project's documentation structure:

    • Look for /docs/ directory in the project root
    • Look for .claude/skills/ directory
    • Look for module-level CLAUDE.md files near the changed files
    • Look for CLAUDE.md in the project root that references documentation locations
    • Map changed files to the nearest relevant documentation areas found
    • Quick-scan (first ~30 lines) matched doc files to check if they cover the changed area
    • Record any gaps (new features not documented, existing docs contradicting changes)

    D. Report and offer — if gaps found, list them specifically and present AskUserQuestion:

    Documentation gaps detected:
    
    Code docs:
    - `path/to/file.py`: new `function_name()` has no docstring
    - `path/to/other.py`: complex logic at L45-60 has no explanatory comment
    
    Project docs:
    - `docs/features/X.md`: does not mention the new Y handler
    - `.claude/skills/sc-X/SKILL.md`: may be outdated after this change
    
    AskUserQuestion:
      question: "Documentation gaps found. How to proceed?"
      header: "Docs"
      options:
        - label: "Add docs now"
          description: "Pause and add documentation before committing"
        - label: "Skip — I'll document later"
          description: "Proceed with commit, no documentation changes"
        - label: "Skip — not needed"
          description: "These changes don't warrant documentation updates"
    
    • If user picks "Add docs now": add documentation (using the brodoc agent if available in the project, or directly if not), then add new/changed doc files to the commit file list and re-run pre-commit on them. Then proceed.
    • If user picks either skip option: proceed to next step.
    • If no gaps found: print "Documentation check: OK" and proceed.
  4. Gather commit history context (run both in parallel)

    # Previous commits touching the files being committed
    git log --oneline -10 -- <file1> <file2> ...
    # Latest 50 commits to establish project style
    git log --oneline -50

    Use both outputs to match the project's commit message style (length, format, capitalization, scope conventions, type usage patterns) when generating suggestions in the next step.

  5. Ask for commit message using AskUserQuestion

    • Use Conventional Commits: <type>(<scope>): <description>
    • Preferred types: feat, fix, docs, refactor, ai (for AI agent-oriented changes)
    • Other types allowed but prefer the above when applicable
    • Generate 2-3 commit message suggestions based on the changes
    • Present them via AskUserQuestion so user can pick one or write their own (via "Other"):
      AskUserQuestion:
        question: "Commit message?"
        header: "Message"
        options:
          - label: "feat(admin): add seat letter labels"
            description: "The suggested message based on changes"
          - label: "feat: seat letters A-F in admin"
            description: "Shorter alternative"
      
    • User picks an option or types a custom message via "Other"
  6. Execute shadow commit

    ⚠️ CRITICAL: temp index MUST be inside .git/mktemp without -p creates in /tmp which is often a different filesystem, causing git read-tree to fail with "unable to write new index file".

    ⚠️ CRITICAL: disable pre-commit hooks with --no-verify — pre-commit was already run in step 2. If hooks run again during the shadow commit, they stash/unstash against the REAL index, polluting it with our staged files.

    # Create temp index INSIDE .git/ (same filesystem!)
    TEMP_INDEX=$(mktemp -p "$(git rev-parse --git-dir)")
    
    # Populate from HEAD
    git read-tree HEAD --index-output="$TEMP_INDEX"
    
    # Add specific files to temp index
    GIT_INDEX_FILE="$TEMP_INDEX" git add <file1> <file2> ...
    
    # Commit from temp index (--no-verify: hooks already ran in step 2)
    GIT_INDEX_FILE="$TEMP_INDEX" git commit --no-verify -m "message"
    
    # Cleanup temp index
    rm -f "$TEMP_INDEX"
    
    # CRITICAL: Reset real index to match new HEAD
    # The shadow commit advanced HEAD but the real index still points to the old tree.
    # Without this, `git status` shows phantom staged changes.
    git reset HEAD -- <file1> <file2> ...

    For amend (into a specific commit, not necessarily HEAD):

    Step A: Identify the target commit

    # Typically a commit from this session or solving the same problem
    git log --oneline -10
    git show --stat <candidate-sha>

    Step B: Check if target has been pushed

    git branch -r --contains <candidate-sha>

    If the commit exists on a remote branch, MUST warn user via AskUserQuestion:

    AskUserQuestion:
      question: "⚠️ Commit <short-sha> '<message>' has been pushed to origin. Amending requires a force push. Proceed?"
      header: "Force push"
      options:
        - label: "Yes, I'll force push"
          description: "Rewrite history and force push later"
        - label: "No, create a new commit instead"
          description: "Keep history intact, make a separate commit"
    

    If user declines, fall back to the normal new-commit flow (step 5 above).

    Step C: Confirm target + choose commit message Show the candidate commit details (SHA, message, changed files), then ask:

    AskUserQuestion:
      question: "Amend into <short-sha>. Commit message?"
      header: "Message"
      options:
        - label: "<original commit message>"
          description: "Keep the original message (Recommended)"
        - label: "<new suggestion reflecting combined changes>"
          description: "Updated message covering both original and new changes"
        - label: "<another new suggestion>"
          description: "Alternative wording"
    

    User picks an option or types a custom message via "Other".

    Step D: Execute the amend

    If keeping original message:

    # Create fixup commit (preserves original message during autosquash)
    GIT_INDEX_FILE="$TEMP_INDEX" git commit --no-verify --fixup=<target-sha>
    
    # Autosquash rebase to fold it in (non-interactive, auto-stash other changes)
    GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash <target-sha>^ --autostash

    If using a new message:

    # Create amend! commit — replaces message during autosquash
    GIT_INDEX_FILE="$TEMP_INDEX" git commit --no-verify --fixup=amend:<target-sha> -m "<new message>"
    
    # Autosquash rebase — amend! commits replace message without opening editor
    GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash <target-sha>^ --autostash
  7. Verify commit integrity

    • Show the new commit with git show --stat HEAD
    • Run git diff HEAD -- <file1> <file2> ... to confirm working tree matches HEAD (must be empty)
    • Run git status to confirm no phantom staged changes remain
    • If git diff HEAD shows differences or git status shows staged files, something went wrong — investigate before declaring success

Critical Rules

  • NEVER use git add without GIT_INDEX_FILE - this would pollute the shared index
  • NEVER use git add . or git add -A - only add specific files you worked on
  • ASK user which files to include if unclear
  • SHOW diff before committing so user can verify
  • RUN pre-commit with --files flag to lint only your files
  • SPLIT into multiple commits if changes are unrelated or can be logically atomic (but don't over-split trivial changes)
  • AMEND safely - when using amend, show recent commits and ask user which one to amend into; check if target has been pushed and if so, ask user to confirm force push via AskUserQuestion before proceeding

Example Session

Agent: I modified these files in our session:
  - app/models/user.py
  - app/views/auth.py

Running pre-commit on these files...
✅ All checks passed

Documentation check: OK (code docs adequate, project docs up to date)

Checking commit history for context...
  Recent commits on these files: "feat(auth): add login view", "fix(auth): handle expired tokens"
  Project style: conventional commits, lowercase descriptions, short scopes

Agent: *uses AskUserQuestion with commit message options*
  → "feat(auth): add OAuth2 support for user login"
  → "feat: OAuth2 login support"
  → (Other — type your own)

User: *picks first option*

Agent: *executes shadow commit*
✅ Committed abc1234: "feat(auth): add OAuth2 support for user login"
   2 files changed, 45 insertions(+), 3 deletions(-)

Real index unchanged - other agents can continue working.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment