unfuck-my-git-state
Recover a repo without making the blast radius worse.
Core Rules
- 1. Snapshot first. Do not "just try stuff."
- Prefer non-destructive fixes before force operations.
- Treat
.git/ as production data until backup is taken. - Use
git symbolic-ref before manually editing .git/HEAD. - After each fix, run verification before proceeding.
Fast Workflow
- 1. Capture diagnostics:
bash scripts/snapshot_git_state.sh .
- 2. Route by symptom using
references/symptom-map.md. - Generate non-destructive command plan:
bash scripts/guided_repair_plan.sh --repo .
- 4. Apply the smallest matching playbook.
- Run
references/recovery-checklist.md verification gate. - Escalate only if the gate fails.
For explicit routing:
CODEBLOCK2
Regression Harness
Use disposable simulation tests before changing script logic:
CODEBLOCK3
Run one scenario:
CODEBLOCK4
Playbook A: Orphaned Worktree Metadata
Symptoms:
- -
git worktree list shows a path that no longer exists. - Worktree entries include invalid or zero hashes.
Steps:
git worktree list --porcelain
git worktree prune -v
git worktree list --porcelain
If stale entries remain, back up
.git/ and remove the specific stale folder under
.git/worktrees/<name>, then rerun prune.
Playbook B: Phantom Branch Lock
Symptoms:
- -
git branch -d or git branch -D fails with "already used by worktree". - INLINECODE10 seems to disagree with branch ownership.
Steps:
git worktree list --porcelain
Find the worktree using that branch, switch that worktree to another branch or detach HEAD there, then retry the branch operation in the main repo.
Playbook C: Detached or Contradictory HEAD
Symptoms:
- -
git status says detached HEAD unexpectedly. - INLINECODE12 and
git symbolic-ref -q HEAD disagree.
Steps:
git symbolic-ref -q HEAD || true
git reflog --date=iso -n 20
git switch <known-good-branch>
If branch context is unknown, create a rescue branch from current commit:
git switch -c rescue/$(date +%Y%m%d-%H%M%S)
Then reconnect to the intended branch after investigation.
Playbook D: Missing or Broken Refs
Symptoms:
- -
unknown revision, not a valid object name, or cannot lock ref.
Steps:
git fetch --all --prune
git show-ref --verify refs/remotes/origin/<branch>
git branch -f <branch> origin/<branch>
git switch <branch>
Use
reflog to recover local-only commits before forcing branch pointers.
Last Resort: Manual HEAD Repair
Only after backup of .git/.
Preferred:
git show-ref --verify refs/heads/<branch>
git symbolic-ref HEAD refs/heads/<branch>
Fallback when
symbolic-ref cannot be used:
echo "ref: refs/heads/<branch>" > .git/HEAD
Immediately run the verification gate.
Verification Gate (Must Pass)
Run checks in references/recovery-checklist.md. Minimum bar:
- -
git status exits cleanly with no fatal errors. - INLINECODE22 matches intended branch.
- INLINECODE23 has no missing paths and no zero hashes.
- INLINECODE24 has no new critical errors.
Escalation Path
- 1. Archive
.git:
tar -czf git-metadata-backup-$(date +%Y%m%d-%H%M%S).tar.gz .git
- 2. Clone fresh from remote.
- Recover unpushed work with reflog and cherry-pick from old clone.
- Document failure mode and add guardrails to automation.
Automation Hooks
When building worktree tooling (iMi, scripts, bots), enforce:
- - preflight snapshot and state validation
- post-operation verification gate
- hard stop on HEAD/ref inconsistency
- explicit user confirmation before destructive commands
Resources
- - Symptom router: INLINECODE26
- Verification checklist: INLINECODE27
- Diagnostic snapshot script: INLINECODE28
- Guided plan generator: INLINECODE29
- Disposable regression harness: INLINECODE30
unfuck-my-git-state
在不扩大影响范围的前提下恢复仓库。
核心规则
- 1. 先做快照。不要直接尝试操作。
- 在强制操作前优先使用非破坏性修复。
- 在备份完成前将 .git/ 视为生产数据。
- 手动编辑 .git/HEAD 前先使用 git symbolic-ref。
- 每次修复后,先运行验证再继续。
快速工作流
- 1. 捕获诊断信息:
bash
bash scripts/snapshot
gitstate.sh .
- 2. 使用 references/symptom-map.md 按症状路由。
- 生成非破坏性命令计划:
bash
bash scripts/guided
repairplan.sh --repo .
- 4. 应用最小的匹配操作手册。
- 运行 references/recovery-checklist.md 验证关卡。
- 仅在关卡失败时升级处理。
显式路由:
bash
bash scripts/guidedrepairplan.sh --list
bash scripts/guidedrepairplan.sh --symptom phantom-branch-lock
回归测试框架
在修改脚本逻辑前使用一次性模拟测试:
bash
bash scripts/regression_harness.sh
运行单个场景:
bash
bash scripts/regression_harness.sh --scenario orphaned-worktree
操作手册 A:孤立工作树元数据
症状:
- - git worktree list 显示一个不再存在的路径。
- 工作树条目包含无效或零哈希值。
步骤:
bash
git worktree list --porcelain
git worktree prune -v
git worktree list --porcelain
如果仍有陈旧条目,备份 .git/ 并删除 .git/worktrees/ 下的特定陈旧文件夹,然后重新运行 prune。
操作手册 B:幻影分支锁定
症状:
- - git branch -d 或 git branch -D 失败,提示已被工作树使用。
- git worktree list 似乎与分支所有权不一致。
步骤:
bash
git worktree list --porcelain
找到使用该分支的工作树,将该工作树切换到另一个分支或分离 HEAD,然后在主仓库中重试分支操作。
操作手册 C:分离或矛盾的 HEAD
症状:
- - git status 意外显示分离 HEAD。
- git branch --show-current 和 git symbolic-ref -q HEAD 不一致。
步骤:
bash
git symbolic-ref -q HEAD || true
git reflog --date=iso -n 20
git switch
如果分支上下文未知,从当前提交创建救援分支:
bash
git switch -c rescue/$(date +%Y%m%d-%H%M%S)
然后在调查后重新连接到目标分支。
操作手册 D:缺失或损坏的引用
症状:
- - unknown revision、not a valid object name 或 cannot lock ref。
步骤:
bash
git fetch --all --prune
git show-ref --verify refs/remotes/origin/
git branch -f origin/
git switch
在强制设置分支指针前,使用 reflog 恢复仅本地存在的提交。
最后手段:手动修复 HEAD
仅在备份 .git/ 后执行。
首选方法:
bash
git show-ref --verify refs/heads/
git symbolic-ref HEAD refs/heads/
当 symbolic-ref 无法使用时回退方案:
bash
echo ref: refs/heads/ > .git/HEAD
立即运行验证关卡。
验证关卡(必须通过)
运行 references/recovery-checklist.md 中的检查。最低标准:
- - git status 正常退出,无致命错误。
- git symbolic-ref -q HEAD 与目标分支匹配。
- git worktree list --porcelain 无缺失路径且无零哈希值。
- git fsck --no-reflogs --full 无新增严重错误。
升级路径
- 1. 归档 .git:
bash
tar -czf git-metadata-backup-$(date +%Y%m%d-%H%M%S).tar.gz .git
- 2. 从远程仓库全新克隆。
- 使用 reflog 和 cherry-pick 从旧克隆中恢复未推送的工作。
- 记录失败模式并为自动化添加防护措施。
自动化钩子
在构建工作树工具(iMi、脚本、机器人)时,强制执行:
- - 前置快照和状态验证
- 操作后验证关卡
- HEAD/引用不一致时硬停止
- 破坏性命令前明确用户确认
资源
- - 症状路由器:references/symptom-map.md
- 验证检查清单:references/recovery-checklist.md
- 诊断快照脚本:scripts/snapshotgitstate.sh
- 引导式计划生成器:scripts/guidedrepairplan.sh
- 一次性回归测试框架:scripts/regression_harness.sh