Git 저장소 정리기 (Git Repository Organizer)
모든 결론은 신선한 Git 스냅샷에 기반합니다. 참조(refs), 체크아웃된 디렉토리, 커밋되지 않은 파일, 호스팅된 리모트를 별도의 상태 계층으로 취급합니다.
작동 모드 선택
요청에서 허용된 가장 좁은 모드를 추론합니다.
- 분석 (Analyze): 참조, 인덱스, 작업 트리 내용을 변경하지 않고 검사 및 보고합니다. 현재 리모트 진실이 중요할 때는
git ls-remote를 사용합니다. 분석 목적으로 fetch, merge, pull, commit, rebase, delete, push, 추적 브랜치 생성, 작업 트리 전환을 하지 마십시오. - 새로고침 (Refresh): 리모트 추적 참조를 가져온(fetch) 후 보고합니다. 단순히 참조를 가져왔다고 브랜치를 통합하지 마십시오.
- 커밋 (Commit): 지정된 작업 트리 내에서만 변경 사항을 정리하고 커밋합니다.
- 통합 (Integrate): 깨끗한 통합 작업 트리를 통해 지정된 브랜치만 merge, rebase 또는 cherry-pick합니다.
- 정리 (Clean up): 결정 매트릭스에서 안전하다고 입증된 브랜치나 작업 트리만 제거합니다.
- 동기화 (Synchronize): 새로고침 및 재확인 후 지정된 참조만 푸시(push) 또는 빨리 감기(fast-forward)합니다.
"정리" 또는 "동기화"가 변경을 명확히 허용하지 않는 경우, 먼저 목록을 보여주고 정확한 제안 작업을 제시하십시오. 원격 참조 삭제, 강제 푸시, 공유 히스토리 재작성, 변경 사항 폐기, 작업 트리 강제 제거 전에는 명시적인 확인을 요구하십시오.
현재 스냅샷 구축
- 실제 저장소와 공통 Git 디렉토리를 찾습니다. 프롬프트 작업 디렉토리가 저장소 루트라고 가정하지 마십시오.
- 작업 전에 AGENTS.md와 같은 프로젝트 지침을 읽습니다.
- 분석 모드에서는 리모트 추적 참조를 업데이트하지 않고 라이브 리모트 팁을 확인합니다:
git ls-remote --symref --heads REMOTE
로컬 리모트 추적 참조는 캐시된 상태로 변경되지 않았음을 명확히 밝힙니다. 새로고침 모드 또는 명시적으로 요청된 리모트 변경 직전에는 다음을 실행합니다:
git fetch --all --prune --no-tags
기본적으로 no-tags를 사용합니다. 브랜치 가져오기와 태그 가져오기는 별도 작업입니다. 충돌하는 로컬 태그를 자동으로 덮어쓰지 마십시오.
가져오기는 리모트 추적 참조만 업데이트합니다. 새로고침 모드에서는 여기서 멈추고 각 로컬 브랜치를 원격 브랜치와 비교하되, 어느 쪽도 통합하지 마십시오:
- 감사를 최신 상태로 만들기 위해 merge나 pull을 절대 하지 마십시오. 로컬 브랜치가 앞서거나, 뒤쳐지거나, 분기된 상태는 정당할 수 있습니다. 해당 상태를 보고하십시오.
- 분석 목적으로 더티(dirty) 작업 트리를 커밋, 스태시, 스냅샷, 전환, 리셋하거나 건드리지 마십시오. 더티 상태를 기록하고 이를 변경 차단 요소로 취급하십시오.
- 리모트가 삭제된 로컬 브랜치(
upstream gone) 또는 푸시된 적이 없는 브랜치는 로컬 전용으로 유지하며, 보고서에 명시적으로 기록합니다. - 사용자가 명시적으로 변경을 요청할 때만 동기화 또는 통합 모드로 진입합니다. 변경 직전에 감사를 다시 실행하고, 해당 브랜치가 속한 작업 트리에서 작업하며, 결정 매트릭스를 적용합니다.
- 번들된 읽기 전용 감사 실행:
python3 scripts/audit_git_state.py --repo /절대/경로 --format markdown
python3 scripts/audit_git_state.py --repo /절대/경로 --base main --format json
대상 저장소가 아닌 이 스킬 디렉토리 기준으로 스크립트를 확인합니다.
- 유지, 통합 또는 삭제될 수 있는 모든 브랜치에 대해 고유 커밋 및 변경 파일을 검사합니다:
git log --left-right --cherry-pick --oneline BASE...BRANCH
git diff --stat BASE...BRANCH
git diff --name-status BASE...BRANCH
브랜치 기능을 설명하기 전에 대표적인 diff를 읽습니다. 브랜치 이름에서 기능을 추론하지 마십시오.
- 정리 전에 분리된(detached) 작업 트리를 분류합니다:
git merge-base --is-ancestor HEAD BASE && echo "HEAD already in BASE"
로컬 베이스와 리모트 베이스(예: main 및 github/main) 모두에 대해 확인합니다. 리모트 베이스의 조상인 깨끗한 분리된 HEAD는 이미 병합된 상태입니다. 재통합이 필요 없으며 복구 브랜치가 필요하지 않습니다. 확인 스크립트의 잔재일 가능성이 높으며, 확인 후 안전하게 제거할 수 있습니다. 조상이 아닌 분리된 HEAD는 고유 커밋을 보유할 수 있습니다. 작업 트리가 깨끗해 보이더라도 제거 전에 HEAD에 복구 브랜치를 만드십시오. 강제 제거 전에 추적되지 않은 파일을 검사하고 생성된 아티팩트(테스트 출력, 빌드 디렉토리)를 수동 작업과 분리하십시오.
-
출력을 결정에 비례하게 유지합니다. JSON 감사와 대량의 참조/작업 트리/diff 목록을 스크래치 파일에 쓰고 요약만 읽습니다. 통합 또는 삭제 후보 브랜치에 대해서만 심층 diff를 수행합니다. 대규모 저장소에서는 브랜치별 로그와 전체 diff를 컨텍스트에 쏟아내지 마십시오.
-
최종 보고서 직전과 각 변경 직전에 감사를 다시 실행합니다. 분석이 실행되는 동안 저장소가 변경될 수 있습니다. 결과에 스냅샷 시간과 팁 해시를 포함하십시오. 또한 동시 활동을 주시하십시오: 마지막 스냅샷 이후 다른 프로세스에 의해 생성 또는 삭제된 참조, 작업 트리, 리모트 브랜치(예: 병합 후보 브랜치)는 계획을 변경합니다. 변경된 대상을 처리하는 대신 계획을 다시 제시하십시오.
상태 모델 정확히 유지
- 저장소의 일반 체크아웃은 **기본 작업 트리(primary worktree)**입니다.
git worktree list에 나타나지만 외부 링크된 작업 트리는 아닙니다. - 다른 경로 아래 체크아웃된 브랜치는 **외부 링크된 작업 트리(external linked worktree)**입니다.
- 분리된 작업 트리는 체크아웃된 커밋은 있지만 브랜치는 없습니다. 더티 분리된 작업 트리는 복구 가능한 작업으로 취급하고 쓰레기로 간주하지 마십시오. HEAD가 베이스(로컬 및 리모트)의 조상인지 항상 확인하십시오: 조상이고 작업 트리가 깨끗하면 이미 병합된 상태이므로 재통합이 필요하지 않습니다. 조상이 아니면 제거 후 커밋에 도달할 수 없게 될 수 있으므로 먼저 복구 브랜치가 필요합니다.
- 브랜치 참조와 작업 트리는 다른 객체입니다. 깨끗한 링크된 작업 트리를 제거해도 브랜치는 삭제되지 않습니다. 브랜치를 삭제해도 더티 작업 트리가 안전하게 처리되지는 않습니다.
- 리모트 HEAD는 기본 브랜치를 가리키는 심볼릭 포인터일 뿐, 또 다른 리모트 브랜치가 아닙니다.
- 리모트 추적 참조는 리모트 상태의 로컬 관찰입니다. 이를 가져오는 것은 pull하거나 merge하는 것이 아닙니다.
- 사용자가 로컬 추적 브랜치를 요청하지 않는 한 모든 리모트 브랜치에 대해 로컬 브랜치를 생성하지 마십시오.
사용자에게 상태를 설명할 때 다음 사실을 명확히 유지하십시오:
- 브랜치 참조는 한 번에 최대 하나의 작업 트리에서 체크아웃될 수 있습니다(0 또는 1). Git은 동일한 브랜치의 두 번째 체크아웃을 거부합니다.
- 작업 트리를 제거하면 해당 디렉토리와 등록만 삭제됩니다. 브랜치 참조와 커밋은 공유 저장소에 남아 있습니다. 브랜치는 단순히 체크아웃되지 않은 상태가 되며 나중에 다시 체크아웃할 수 있습니다.
- 작업 트리를 제거하면 커밋되지 않은 작업(스테이징, 언스테이징, 추적되지 않음 또는 충돌 파일)만 손실됩니다. "깨끗함"은 손실 위험이 0임을 의미하며, 브랜치가 병합되었다는 의미가 아닙니다.
- 분리된 작업 트리는 브랜치를 차지하지 않습니다. HEAD가 커밋을 직접 가리키므로 다른 작업 트리가 브랜치를 얻거나 잃는 원인이 되지 않습니다.
- 브랜치는 기본 작업 트리 "내부"에 있지 않습니다. 체크아웃되지 않은 브랜치는 참조로 존재하며 언제든지 전환할 수 있습니다.
명확히 삭제 가능한 브랜치 정의
브랜치가 **명확히 삭제 가능(clearly deletable)**하려면 콘텐츠가 의도된 기본 브랜치(보통 main)에 완전히 병합되어야 합니다:
- 계보(ancestry): 브랜치 팁이 기본 브랜치의 조상입니다(
git merge-base --is-ancestor BRANCH BASE). 따라서 브랜치 전용 커밋이 0개입니다. - 패치 동등성(patch equivalence): 모든 브랜치 전용 커밋은 패치 ID가 동등한 커밋이 이미 기본 브랜치에 존재합니다(
git cherry BASE BRANCH에서+항목 없음).git patch-id로 확인하며, 커밋 제목으로 확인하지 않습니다.
고유 커밋이나 고유 패치가 있는 브랜치는 명확히 삭제 가능하지 않습니다. 작업이 중복되어 보이거나, 이름이 병합된 브랜치와 비슷하거나, 팁이 태그로 보존되더라도 마찬가지입니다. 태그로 보관된 브랜치는 명시적 확인 후에만 삭제 가능할 수 있으며, 이 규칙에 의한 것은 아닙니다.
브랜치는 대체됨(superseded) 상태일 수도 있습니다: 기본 브랜치에서 진화된 또는 대체 구현으로 이미 제공된 기능을 구현하는 경우입니다. 기본 브랜치가 동일한 의도와 파일을 다루는지, 남은 브랜치 전용 라인이 누락된 기능이 아닌 구식 잔재인지 커밋별, 파일별로 확인하십시오. 대체된 브랜치는 이 규칙으로 명확히 삭제 가능하지 않습니다. 정확한 팁을 태그로 보관하고, 비교 증거를 제시하며, 명시적 사용자 확인 후에만 삭제하십시오.
리모트 브랜치의 경우, 병합된 콘텐츠 증거가 리모트 기본 브랜치에 대해 유효해야 합니다. 푸시되지 않은 로컬 기본 브랜치에만 병합된 콘텐츠는 자격을 충족하지 못합니다. 삭제 전에 항상 references/decision-matrix.md의 삭제 게이트를 적용하십시오.
고정된 브랜치 매트릭스로 보고
모든 표준 브랜치 이름에 대해 다음을 보고하십시오:
| 필드 | 필수 의미 |
|---|---|
| 로컬 | refs/heads에 브랜치가 있는지 여부 |
| 리모트 | 업스트림뿐만 아니라 모든 동일 이름의 리모트 참조 |
| 동기화 | 구성된 업스트림에 대해 앞/뒤 또는 분기됨 |
| 기본 관계 | 기본 전용 및 브랜치 전용 커밋, 계보 및 패치 동등성 증거 |
| 체크아웃 | 체크아웃되지 않음, 기본 작업 트리, 외부 링크된 작업 트리 또는 분리됨 |
| 작업 트리 상태 | 스테이징됨, 언스테이징됨, 추적되지 않음, 충돌 |
| 기능 | 커밋과 diff로 입증된 기능 또는 수정 사항 |
| 권장 사항 | 유지, 커밋, 통합, 보관, 삭제 또는 조사. 콘텐츠가 기본 브랜치에 완전히 병합된 '명확히 삭제 가능한' 브랜치에만 "삭제" 사용 |
분리된 작업 트리와 정리 가능한 작업 트리를 별도로 나열하고, 각각 HEAD 해시, 해당 HEAD가 로컬 및 리모트 기본의 조상인지 여부, 깨끗함/더티 상태, 추적되지 않은 아티팩트, 권장 사항(안전하게 제거 가능 / 복구 브랜치 우선 / 유지)을 포함하십시오. 안전한 작업, 확인 필요 작업, 커밋되지 않았거나 고유한 작업으로 차단된 작업으로 나누어 정렬된 작업 목록으로 마무리하십시오. 사용자가 로컬 전용 보기를 원하거나, 요청이 정리/삭제 결정(整理、删除候选、哪些可以删)을 포함하는 경우, 아래 색상 코드 로컬 저장소 다이어그램을 보고서의 일부로 항상 포함하십시오. 명시적인 "画图" 요청을 기다리지 마십시오.
로컬 저장소 다이어그램 그리기 (画出本地的代码库图)
"画出本地的代码库图", "本地 Git 状态的图", "只展示本地分支", "本地优先视图"와 같은 명시적 요청 시 트리거하고, 모든 정리 지향 보고서(整理、删除候选、哪些可以删)에 자동으로 포함합니다. 로컬 우선 브랜치 다이어그램을 생성합니다:
- 그리기 직전에 감사를 다시 실행합니다. 다이어그램에 스냅샷 시간과 팁 해시를 표시합니다.
- 로컬 브랜치(
refs/heads/*)로만 범위를 지정합니다. 리모트 전용 브랜치는 렌더링하지 않습니다. - 동일한 이름의 리모트 브랜치도 있는 각 브랜치를 也有远程分支(리모트 브랜치도 있음)로 표시하고, 그렇지 않으면 无远程分支(리모트 브랜치 없음)로 표시하여 푸시된 적이 없는 브랜치와 푸시 후 삭제된 브랜치(
upstream gone)를 구분합니다. - 브랜치를 성격별로 그룹화: 장기/주요(유지), 임시(확인 후 보관/삭제), 실제 작업(유지 및 통합 결정).
- 각 브랜치에 작업 트리 상태를 첨부: 체크아웃되지 않음, 기본 작업 트리, 링크된 작업 트리(경로 포함), 깨끗함/더티 상태.
- 정리 증거 첨부: 고유 커밋/패치, 업스트림 상태(앞/뒤 포함), 더티 파일, 스태시.
- 세션 중 다른 프로세스가 병합 후보 또는 확인 참조를 생성한 경우 해당 브랜치를 자체 보류 그룹에 넣습니다. 보고는 하지만 외부 프로세스가 해결될 때까지 수정하지 마십시오.
- 분리된 작업 트리는 브랜치가 없더라도 Worktree 하위 그래프에 그립니다:
detached <path> → HEAD <hash>로 레이블을 지정하고, 깨끗함/더티 상태 및 조상 판정(✔ HEAD 已在 base 中,已合入또는✘ 未合入,需恢复分支)을 포함합니다. 브랜치 에지는 없습니다. - 그룹당 하나의 서브그래프와 별도의 작업 트리 서브그래프로 하나의 메르마이드 순서도를 렌더링합니다. 체크아웃된 각 브랜치를 해당 작업 트리에 연결합니다.
템플릿:
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
로컬 커밋 정리
변경 사항이 속한 작업 트리 내에서만 작업합니다.
- 스테이징됨, 언스테이징됨, 추적되지 않음, 무시됨, 생성됨, 대용량 및 비밀 파일을 검사합니다.
- 생성된 출력물, 캐시, 스크린샷, 로컬 로그, 자격 증명을 제품 변경 사항과 분리합니다. 잠금 파일의 경우, 형식만 다시 직렬화한 것(pnpm 버전 인용 스타일 변경 등)과 실제 종속성 변경을 구분합니다. 복원 또는 커밋 전에 종속성 diff로 확인합니다.
- 디렉토리만이 아닌 동작별로 커밋을 그룹화합니다. 하나의 파일에 여러 관심사가 포함된 경우 패치 스테이징을 사용합니다:
git add -p
git diff --cached --check
git diff --cached --stat
git diff --cached
- 각 논리적 커밋 전에 집중된 검증을 실행하고, 통합 전에 더 광범위한 검증을 실행합니다.
- 관용적인 커밋 메시지를 사용합니다. 혼합되거나 익숙하지 않은 작업 트리에서 git add -A를 맹목적으로 사용하지 마십시오.
- 모든 커밋 후 상태를 다시 확인하고 어떤 것이 커밋되지 않은 상태로 남아 있는지 정확히 명시합니다.
브랜치 안전하게 통합
merge, rebase, cherry-pick, 삭제, 작업 트리 제거 또는 강제 연산 전에 references/decision-matrix.md를 읽습니다.
작업 트리 제거는 작업 트리 디렉토리와 등록만 삭제하며 브랜치 참조는 삭제하지 않습니다. 링크된 작업 트리가 있는 브랜치를 삭제해도 작업 트리가 정리되지는 않습니다. 작업 트리 없이 브랜치를 삭제하는 것은 안전합니다. 반대로, 브랜치 참조가 있는 작업 트리를 제거해도 여전히 체크아웃되지 않은 브랜치 참조가 남아 있습니다. 두 가지 모두 안전하게 수행할 수 있습니다. 브랜치 참조가 체크아웃된 링크된 작업 트리를 실수로 제거할 위험은 없습니다. 브랜치 삭제는 연결된 작업 트리가 있는지 여부를 확인하며, 작업 트리가 있으면 거부합니다. 강제 플래그(-D)는 이 보호를 우회하며, 우리가 절대 금지하는 것은 아닙니다.
결정 매트릭스
references/decision-matrix.md를 참조하십시오.