Communitygithub.com

zhifengjiang/git-repo-organizer

Safety-first Codex skill for auditing and organizing Git branches, worktrees, commits, and remotes.

git-repo-organizer란 무엇인가요?

git-repo-organizer is a Codex agent skill that safety-first Codex skill for auditing and organizing Git branches, worktrees, commits, and remotes.

지원 대상~Claude CodeCodex CLI~Cursor
npx skills add zhifengjiang/git-repo-organizer

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Git Repository Organizer

Ground every conclusion in a fresh Git snapshot. Treat refs, checked-out directories, uncommitted files, and hosted remotes as separate state layers.

Select the operating mode

Infer the narrowest mode authorized by the request:

  • Analyze: inspect and report without changing refs, the index, or worktree contents. Use git ls-remote when current remote truth matters; do not fetch, merge, pull, commit, rebase, delete, push, create tracking branches, or switch worktrees merely to analyze.
  • Refresh: fetch remote-tracking refs, then report. Do not integrate a branch merely because refs were fetched.
  • Commit: organize and commit changes only in the named worktree.
  • Integrate: merge, rebase, or cherry-pick only the named branches through a clean integration worktree.
  • Clean up: remove only branches or worktrees proven safe under the decision matrix.
  • Synchronize: push or fast-forward only the named refs after refreshing and rechecking them.

If “整理” or “同步” does not clearly authorize mutations, inventory first and present the exact proposed operations. Require explicit confirmation before deleting remote refs, force-pushing, rewriting shared history, discarding changes, or force-removing a worktree.

Build a current snapshot

  1. Locate the real repository and common Git directory. Never assume the prompt working directory is the repository root.
  2. Read project instructions such as AGENTS.md before acting.
  3. In Analyze mode, verify live remote tips without updating remote-tracking refs:
git ls-remote --symref --heads REMOTE

State clearly that local remote-tracking refs remain cached and unchanged. In Refresh mode, or immediately before an explicitly requested remote mutation, run:

git fetch --all --prune --no-tags

Use no-tags by default. Fetching branches and fetching tags are separate operations; never overwrite a conflicting local tag automatically.

Fetching updates remote-tracking refs only. In Refresh mode, stop there and compare each local branch with its remote counterpart without integrating either side:

  • Never merge or pull merely to make an audit look current. A local branch may legitimately be ahead, behind, or diverged; report that state.
  • Never commit, stash, snapshot, switch, reset, or otherwise touch a dirty worktree merely to analyze it. Record the dirty state and treat it as a mutation blocker.
  • Local branches whose remote was deleted (upstream gone) or that were never pushed stay local-only; note that explicitly in the report.
  • Only enter Synchronize or Integrate mode when the user explicitly asks for that mutation. Re-run the audit immediately before it, operate in the worktree that owns the branch, and apply the decision matrix.
  1. Run the bundled read-only audit:
python3 scripts/audit_git_state.py --repo /absolute/path --format markdown
python3 scripts/audit_git_state.py --repo /absolute/path --base main --format json

Resolve scripts relative to this skill directory, not the target repository.

  1. Inspect unique commits and changed files for every branch that may be kept, integrated, or deleted:
git log --left-right --cherry-pick --oneline BASE...BRANCH
git diff --stat BASE...BRANCH
git diff --name-status BASE...BRANCH

Read representative diffs before describing branch functionality. Do not infer function from a branch name.

  1. Classify every detached worktree before cleanup:
git merge-base --is-ancestor HEAD BASE && echo "HEAD already in BASE"

Check against both the local base and the remote base (for example main and github/main). A clean detached HEAD that is an ancestor of the remote base is already merged — it does not need reintegration and needs no recovery branch; it is likely a leftover from a verification script and can be removed safely after confirmation. A detached HEAD that is not an ancestor may hold unique commits; create a recovery branch at HEAD before any removal, even if the worktree looks clean. Inspect untracked files and separate generated artifacts (test output, build directories) from handwritten work before force-removal.

  1. Keep output proportional to the decision. Write the JSON audit and bulk ref/worktree/diff listings to a scratch file and read only the summaries. Deep-dive diffs only for branches that are integration or deletion candidates; do not pour per-branch logs and full diffs into context in large repositories.

  2. Re-run the audit immediately before the final report and before each mutation. Repositories can change while analysis is running; include the snapshot time and tip hashes in the result. Also watch for concurrent activity: a ref, worktree, or remote branch created or deleted by another process since the last snapshot (for example a merge-candidate branch) changes the plan; re-present the plan instead of acting on stale targets.

Keep the state model precise

  • The repository’s normal checkout is the primary worktree. It appears in git worktree list but is not an external linked worktree.
  • A branch checked out under another path is an external linked worktree.
  • A detached worktree has a checked-out commit but no branch. Treat dirty detached worktrees as recoverable work, not garbage. Always check whether its HEAD is an ancestor of the base (local and remote): if yes and the worktree is clean, it is already merged and does not need reintegration; if not, its commits may become unreachable after removal and need a recovery branch first.
  • A branch ref and a worktree are different objects. Removing a clean linked worktree does not delete its branch; deleting a branch does not safely handle a dirty worktree.
  • Remote HEAD is a symbolic default-branch pointer, not another remote branch.
  • A remote-tracking ref is a local observation of remote state. Fetching it is not pulling or merging it.
  • Do not create a local branch for every remote branch unless the user asks for local tracking branches.

When explaining state to the user, keep these facts crisp:

  • A branch ref can be checked out by at most one worktree at a time (0 or 1); Git refuses a second checkout of the same branch.
  • Removing a worktree deletes only its directory and registration. Branch refs and commits stay in the shared repository; the branch simply becomes un-checked-out and can be checked out again later.
  • Removing a worktree loses only uncommitted work (staged, unstaged, untracked, or conflicted files). “Clean” means that loss risk is zero, not that the branch is merged.
  • A detached worktree occupies no branch. Its HEAD points straight at a commit, so it never causes another worktree to gain or lose a branch.
  • Branches are not “inside” the primary worktree; un-checked-out branches exist as refs and can be switched to at any time.

Define clearly deletable branches

A branch is clearly deletable (明确删除) only when its content is fully merged into the intended base branch (usually main):

  • By ancestry: the branch tip is an ancestor of the base (git merge-base --is-ancestor BRANCH BASE), so it has zero branch-only commits.
  • By patch equivalence: every branch-only commit has a patch-id equivalent already present in the base (git cherry BASE BRANCH shows no + entries), verified with git patch-id, never from commit subjects.

A branch with any unique commit or unique patch is not clearly deletable, even if its work looks redundant, its name resembles a merged branch, or its tip is preserved by a tag. Tag-archived branches may be deletable only with explicit confirmation, not by this rule.

A branch may instead be superseded (被取代): it implements a feature already delivered by an evolved or alternative implementation in the base. Verify commit-by-commit and file-by-file that the base covers the same intent and files, and that the remaining branch-only lines are obsolete remnants rather than missing functionality. Superseded branches are not clearly deletable by this rule; archive the exact tip with a tag, present the comparison evidence, and delete only after explicit user confirmation.

For remote branches, the merged-content evidence must hold against the remote base; content merged only into an unpushed local base does not qualify. Always apply the deletion gates in references/decision-matrix.md before deleting.

Report with a fixed branch matrix

For every canonical branch name, report:

FieldRequired meaning
LocalWhether refs/heads contains the branch
RemoteEvery same-name remote ref, not just the upstream
SyncAhead/behind or diverged against its configured upstream
Base relationBase-only and branch-only commits, ancestry, and patch-equivalent evidence
CheckoutNot checked out, primary worktree, external linked worktree, or detached
Worktree stateStaged, unstaged, untracked, and conflicts
FunctionFeatures or fixes proven by commits and diffs
RecommendationKeep, commit, integrate, archive, delete, or investigate; use "delete" only for clearly deletable branches whose content is fully merged into the base

List detached and prunable worktrees separately, each with its HEAD hash, whether that HEAD is an ancestor of the local and remote base, clean/dirty state, untracked artifacts, and a recommendation (safe to remove / recovery branch first / keep). End with ordered actions divided into safe now, requires confirmation, and blocked by uncommitted or unique work. When the user wants a local-only view, or when the request involves cleanup/deletion decisions (整理、删除候选、哪些可以删), always include the colored local repository diagram below as part of the report; do not wait for an explicit “画图” request.

Draw the local repository diagram (画出本地的代码库图)

Trigger on explicit requests such as “画出本地的代码库图”, “本地 Git 状态的图”, “只展示本地分支”, or “本地优先视图”, and include it automatically in every cleanup-oriented report (整理、删除候选、哪些可以删). Produce a local-first branch diagram:

  • Re-run the audit immediately before drawing; label the diagram with the snapshot time and tip hashes.
  • Scope to local branches only (refs/heads/*). Do not render remote-only branches.
  • Mark each branch that also has a same-name remote branch as 也有远程分支; otherwise mark 无远程分支, distinguishing never pushed from pushed then deleted (upstream gone).
  • Group branches by nature: long-lived/primary (keep), temporary (archive/delete after confirmation), and real work (keep and decide integration).
  • Attach worktree state to each branch: not checked out, primary worktree, or linked worktree (with its path), and clean/dirty status.
  • Attach cleanup evidence: unique commits/patches, upstream status (including ahead/behind), dirty files, and stashes.
  • If another process created a merge candidate or verification ref during the session, put those branches in their own pending group; report them but do not modify them until the external process resolves.
  • Draw every detached worktree in the Worktree subgraph even though it has no branch: label it detached <path> → HEAD <hash>, with clean/dirty status and the ancestor verdict (✔ HEAD 已在 base 中,已合入 or ✘ 未合入,需恢复分支). It has no branch edge.
  • Render one mermaid flowchart with a subgraph per group plus a separate worktree subgraph; connect each checked-out branch to its worktree.

Template:

flowchart TB
    subgraph LOCAL["本地分支 refs/heads/*"]
        subgraph KEEP["长期/主要 —— 保留"]
            A["main(ahead 25 · behind 4)<br/>✔ 也有远程分支<br/>primary worktree · 干净"]
            B["dev<br/>✔ 也有远程分支 · 未检出<br/>祖先,已完全合入 main"]
        end
        subgraph TEMP["临时性 —— 确认后归档/删除"]
            C["branch-c(N 个独有提交)<br/>✘ 无远程分支(upstream gone)<br/>linked worktree · 脏"]
        end
        subgraph WORK["有实际工作 —— 保留并决定是否合入"]
            D["branch-d(N 个独有提交)<br/>✘ 无远程分支(从未推送)<br/>linked worktree · 干净"]
        end
        subgraph PENDING["在途/外部验证 —— 不动"]
            E["merge-candidate-x(外部创建)<br/>✔ 也有远程分支 · linked worktree · 干净"]
        end
    end

    subgraph WT["Worktree"]
        W1["primary /path/to/repo → main · 干净"]
        W2["linked /path/to/wt1 → branch-d · 干净"]
        W3["linked /path/to/wt2 → branch-c · 脏"]
        W4["linked /path/to/wt3 → merge-candidate-x · 干净"]
        W5["detached /path/to/wt4 → HEAD abc1234 · 干净<br/>✔ HEAD 已在 base 中(已合入)"]
        W6["detached /path/to/wt5 → HEAD def5678 · 脏<br/>✘ 未合入(需恢复分支)"]
    end

    A --> W1
    B -- "祖先" --> A
    D --> W2
    C --> W3
    E --> W4

    style LOCAL fill:#e3f2fd,stroke:#1e88e5
    style KEEP fill:#e8f5e9,stroke:#4c8c4c
    style TEMP fill:#fff8e1,stroke:#f9a825
    style WORK fill:#e8eaf6,stroke:#3949ab
    style PENDING fill:#fff3e0,stroke:#fb8c00
    style WT fill:#f3e5f5,stroke:#8e24aa
    style A fill:#fce4ec,stroke:#d81b60

Organize local commits

Work only inside the worktree that owns the changes.

  1. Inspect staged, unstaged, untracked, ignored, generated, large, and secret-like files.
  2. Separate generated outputs, caches, screenshots, local logs, and credentials from product changes. For lockfiles, separate format-only re-serialization (for example a pnpm version quote-style change) from real dependency changes; verify with a dependency diff before restoring or committing.
  3. Group commits by behavior, not directory alone. Use patch staging when one file contains multiple concerns:
git add -p
git diff --cached --check
git diff --cached --stat
git diff --cached
  1. Run focused validation before each logical commit and broader validation before integration.
  2. Use conventional commit messages. Never use git add -A blindly on a mixed or unfamiliar worktree.
  3. Recheck status after every commit and state exactly what remains uncommitted.

Integrate branches safely

Read references/decision-matrix.md before merge, rebase, cherry-pick, deletion, worktree removal, or force-like operations.

Before merging, preflight the candidate against the intended base: git diff --quiet BASE BRANCH (tree equality), git cherry BASE BRANCH (patch equivalence), and git merge-base --is-ancestor. If the branch already contributes nothing to the base tree, do not create an empty merge commit; verify equivalence and treat it as already represented. If a merge attempt produces many conflicts, abort and compare the two trees directly before resolving anything.

Default integration pattern:

  1. Refresh all remote-tracking refs.
  2. Protect every dirty worktree with logical commits or a named recovery branch and explicit backup.
  3. Create a clean integration branch and linked worktree from the intended updated base.
  4. Choose merge for meaningful shared history, cherry-pick for a small isolated change, and semantic porting for overlapping or obsolete histories.
  5. Resolve conflicts by preserving current behavior and the intended feature. Never blanket-select ours or theirs.
  6. Validate after each integration stage, then run the full suite.
  7. Update the base only after reviewing the final range and confirming the remote has not moved.

Do not force-push main or master. Use force-with-lease only when the user explicitly authorizes rewriting a non-protected branch and after refreshing the exact remote ref.

Synchronize remotes safely

  • During analysis, use git ls-remote when current remote truth matters (see Build a current snapshot). Before an explicitly requested remote mutation, refresh the target remote and compute deletion or synchronization evidence against that refreshed remote base. Never merge or pull merely to analyze.
  • For “pull all remotes,” fetch all remotes; do not merge multiple remotes into the current branch.
  • Use git pull --ff-only only for a clean branch with a configured upstream and a proven fast-forward.
  • Before fast-forwarding or aligning a dirty primary worktree, snapshot all uncommitted work on a named recovery branch (logical commits or one snapshot commit). Never check out, merge, or reset over dirty files to make alignment easier.
  • If local and remote diverged, report both unique ranges and choose an integration strategy instead of pushing over either side.
  • If a tag fetch is rejected because a local and remote tag share a name but point to different objects, preserve both hashes, continue branch refresh with no-tags, and ask which tag identity is authoritative.
  • Classify failures as authentication, network, ref conflict, non-fast-forward, protection rule, or missing upstream. Do not hide a failed fetch behind a stale report.
  • Push a new branch with an explicit remote and upstream. Delete a remote branch only by explicit request and only after the deletion checks pass.

Safety invariants

  • Never discard uncommitted or untracked work to make cleanup easier.
  • Analyze mode is strictly non-mutating. Refresh mode may update remote-tracking refs only; neither mode changes commits, local branch refs, the index, or worktree contents.
  • Never prune or force-remove a dirty, detached, missing, or ambiguous worktree without a recovery artifact and explicit approval.
  • Never treat a detached worktree as garbage without checking HEAD ancestry against the local and remote base and inspecting dirty/untracked files first.
  • Never call a branch “merged” solely because its name resembles another branch or because its patch exists somewhere. Distinguish ancestry from patch equivalence.
  • Never call a branch “clearly deletable” while unique commits, unique patches, dirty files, stashes, or unverified generated artifacts remain. Unique work may be archived and deleted only after supersession analysis, a recovery tag or branch, and explicit user confirmation.
  • Never trust an earlier table after refs or worktrees change. Refresh and recompute.
  • Preserve unrelated user changes and keep operations scoped to the named repository and refs.

관련 스킬