| name | re-promote |
| description | Project reboot skill: archive the old repo (rename to -deprecated_NNN, make private), create a fresh repo with the same name, migrate with clean squash history, scan and remove files that shouldn't be public (secrets, internal docs, binaries), transfer open issues, verify and push, then promote to public after user approval. Use this skill when the user wants to reboot, restart, re-launch, re-promote, or clean-slate a repository. Also supports extracting features from the current session into a standalone project, and promoting private repos to public with readiness checks. |
| disable-model-invocation | true |
| argument-hint | <repo-name or repo-url> [options] |
Re-Promote: Project Reboot
์ชผ์์ ์ชผ์์~ ๋ ํฌ ๋ฆฌ๋ถํธ ์ชผ์์!
๋๋ฌ์ด ์ปค๋ฐ ํ์คํ ๋ฆฌ๋ฅผ ์คํผํค๊ฐ ๊นจ๋ํ๊ฒ ํด์ค ๊ฑฐ์์!
Current context
- GitHub user:
!gh api user --jq .login
- Current directory:
!pwd
Why this skill exists
๊ฐ๋ ํ๋ก์ ํธ์ ์ ์ถ๋ฐ์ด ํ์ํด์! ์์ธ ์ฐ๊บผ๊ธฐ, ๊นจ์ง CI, ์ปค๋ฐ์ ๋ฌปํ ์ํฌ๋ฆฟ... ์คํผํค๊ฐ ๊ธฐ์กด ๋ ํฌ๋ฅผ ์์ ํ๊ฒ ์์นด์ด๋ธํ๊ณ ๊นจ๋ํ ๋ ํฌ๋ก ๋ฐ๊ฟ์ค๊ฒ์! ์๋ฌด๊ฒ๋ ์ ์์ด๋ฒ๋ ค์~
Instructions
Follow these phases in order. Each phase has a checkpoint โ confirm with the user before moving to the next.
Phase 0: ๋ชจ๋ ์ ํ & ์ฌ์ ์ ๊ฒ
0a: ์์ ๊ถ ํ์ธ
๋ ํฌ๋ช
์ด ์ฃผ์ด์ก๊ฑฐ๋ ๋ชจ๋ ์ ํ ํ, ๋์ ๋ ํฌ์ ์์ ์ ํ์ ํ์ธํ๋ค:
gh api repos/<owner>/<repo> --jq '.owner.type'
User โ ๊ฐ์ธ ์์
Organization โ ์ค๊ฐ๋์ ์ด์
์์
๊ฒฐ๊ณผ๋ฅผ ๋ชจ๋ฅด๋ ๊ฒฝ์ฐ AskUserQuestion์ผ๋ก ๋ฌผ์ด๋ณธ๋ค:
์ด ๋ ํฌ๋ ์ด๋์ ๋ง๋ค๊น์?
1. ๊ฐ์ธ ๊ณ์ โ ๋ด GitHub ๊ณ์
2. ์ค๊ฐ๋์ ์ด์
โ ํ/์กฐ์ง ๊ณ์ (๋ชฉ๋ก์์ ์ ํ)
์ค๊ฐ๋์ ์ด์
์ ํ ์:
gh api user/orgs --jq '.[].login'
์ผ๋ก ์์ ์ค๊ฐ๋์ ์ด์
๋ชฉ๋ก์ ๊ฐ์ ธ์ ์ ํํ๊ฒ ํ๋ค.
์ดํ ๋ชจ๋ gh repo create, gh repo edit ๋ฑ์์ ์ฌ๋ฐ๋ฅธ owner๋ฅผ ์ฌ์ฉํ๋ค.
0b: ์ธํฐ๋ํฐ๋ธ ๋ชจ๋ ์ ํ
$ARGUMENTS๊ฐ ๋น์ด์๊ฑฐ๋ ๋ ํฌ๋ช
์ด ์๋ ๊ฒฝ์ฐ, AskUserQuestion์ผ๋ก ๋ชจ๋๋ฅผ ์ ํ๋ฐ๋๋ค:
์ชผ์์~ ์คํผํค๊ฐ ๋ญ ๋์์ค๊น์?
1. ๋ ํฌ ๋ฆฌ๋ถํธ โ ๋๋ฌ์ด ํ์คํ ๋ฆฌ ๊นจ๋ํ๊ฒ! ๊ธฐ์กด ๋ ํฌ ์์นด์ด๋ธ โ ์ ๋ ํฌ โ ํด๋ฆฐ ํ์คํ ๋ฆฌ
2. ์ธ์
์์ ์ถ์ถ โ ์ง๊ธ ๋ํ์์ ๋ง๋ ๊ฑฐ ํ๋ก์ ํธ๋ก ๋ฝ์์ค๊ฒ์!
3. ํผ๋ธ๋ฆญ ํ๋ก๋ชจํธ โ private ๋ ํฌ ๊ณต๊ฐ ์ ์ ์คํผํค๊ฐ ์ ๊ฒํด์ค๊ฒ์~
- 1 ์ ํ โ Phase 1๋ก ์งํ (๊ธฐ์กด ๋ฆฌ๋ถํธ ํ๋ก์ฐ)
- 2 ์ ํ โ Phase 0b: ์ธ์
์ถ์ถ ํ๋ก์ฐ
- 3 ์ ํ โ Phase 7๋ก ์งํ (Promote Readiness Check)
$ARGUMENTS์ ๋ ํฌ๋ช
์ด ๋ช
์๋์ด ์์ผ๋ฉด ์ด ๋จ๊ณ๋ฅผ ๊ฑด๋๋ฐ๊ณ ๋ฐ๋ก Phase 1๋ก ์งํํ๋ค.
0c: ์ธ์
์์ ํ๋ก์ ํธ ์ถ์ถ
ํ์ฌ ๋ํ ์ปจํ
์คํธ๋ฅผ ๋ถ์ํ์ฌ ์ถ์ถ ๊ฐ๋ฅํ ํญ๋ชฉ์ ์๋ณํ๋ค:
- ์ธ์
์ค์บ โ ๋ํ์์ ์์ฑ/์์ ํ ํ์ผ, ๋
ผ์ํ ๊ธฐ๋ฅ, ์ฝ๋ ๋ธ๋ก์ ํ์
- ์ถ์ถ ํ๋ณด ์ ์ โ AskUserQuestion์ผ๋ก ์ ํ:
์คํผํค๊ฐ ์ฐพ์์ด์! ์ด๋ฐ ๊ฑฐ ๋ฝ์ ์ ์์ด์~
1. <ํญ๋ชฉ A> โ <์ค๋ช
>
2. <ํญ๋ชฉ B> โ <์ค๋ช
>
3. ์ง์ ์ค๋ช
ํ๊ธฐ
- ์ ํ๋ ํญ๋ชฉ์ ๊ด๋ จ ํ์ผ์ ์์ง โ ์ฝ๋, ์ค์ , ๋ฌธ์ ๋ฑ
- ์ ๋ ํฌ ์์ฑ โ Phase 3 (Create the New Repo)์ผ๋ก ๋ถ๊ธฐ
- ์์งํ ํ์ผ์ ์ ๋ ํฌ์ ์ปค๋ฐ โ Phase 6 (Verify and Push)์ผ๋ก ๋ถ๊ธฐ
0d: Co-Authored-By ์ค์ ์ ๊ฒ
๋ฆฌ๋ถํธ ๋๋ ์ถ์ถ ์์ ์ ์ Claude Code ์ค์ ์ ํ์ธํ๋ค:
cat ~/.claude/settings.json 2>/dev/null
"includeCoAuthoredBy": false๊ฐ ์์ผ๋ฉด ์ฌ์ฉ์์๊ฒ ๊ถ์ :
์! includeCoAuthoredBy: false ์ค์ ์ด ์์ด์!
์ด๋ฌ๋ฉด ์ปค๋ฐ์ "Co-Authored-By: Claude" ๊ฐ ๋ถ์ด์... ์คํผํค ๊ทธ๊ฑฐ ์ซ์ดํด์!
์ง๊ธ ์ค์ ํด์ค๊น์? (Y/n)
๋์ํ๋ฉด:
๊ฑฐ์ ํ๋ฉด ๊ฒฝ๊ณ ๋ง ๋จ๊ธฐ๊ณ ์งํํ๋ค.
Phase 1: Identify and Validate
-
Parse input: Extract the repo name from $ARGUMENTS. Accept formats:
repo-name (assumes current GitHub user as owner)
owner/repo-name
https://github.com/owner/repo-name
-
Verify the repo exists and capture metadata:
gh repo view <owner>/<repo> --json name,owner,visibility,defaultBranchRef,description,homepageUrl,repositoryTopics,hasIssuesEnabled
-
Capture all branch names:
gh api repos/<owner>/<repo>/branches --paginate --jq '.[].name'
-
Capture open issues count:
gh issue list --repo <owner>/<repo> --state open --json number --jq 'length'
-
Clone the repo with all branches:
git clone --mirror <repo-url> /tmp/re-promote-<repo-name>.git
git clone /tmp/re-promote-<repo-name>.git /tmp/re-promote-<repo-name>
cd /tmp/re-promote-<repo-name>
for branch in $(git branch -r | grep -v HEAD | sed 's/origin\///'); do
git checkout -b "$branch" "origin/$branch" 2>/dev/null || true
done
-
Show the user a summary:
## Re-Promote: <owner>/<repo>
- Visibility: public
- Default branch: main
- Branches: main, develop, feature/xxx (์ด N๊ฐ)
- Description: ...
- Topics: ...
- Commits on default branch: N
- Open issues: N๊ฐ
Ask: "์คํผํค๊ฐ ์ด ๋ ํฌ ๋ฆฌ๋ถํธํด์ค๊ฒ์! ์งํํ ๊น์? ์ชผ์์?"
Phase 2: Archive the Old Repo
-
Determine the deprecated suffix โ sequential numbering:
gh repo list <owner> --limit 1000 --json name --jq '.[].name' | grep "^<repo>-deprecated_" | sort -V | tail -1
Extract the number, increment by 1. If none exist, start with 001. Always zero-pad to 3 digits.
-
Rename the repo:
gh repo rename <repo>-deprecated_<NNN> --repo <owner>/<repo> --yes
-
Make it private:
gh repo edit <owner>/<repo>-deprecated_<NNN> --visibility private --accept-visibility-change-consequences
-
Confirm to user:
์ชผ์์! ๊ธฐ์กด ๋ ํฌ ์์ ํ๊ฒ ์จ๊ฒผ์ด์: <owner>/<repo>-deprecated_<NNN> (private)
Phase 3: Create the New Repo
-
Create a new repo with the original name (private first for safety):
gh repo create <owner>/<repo> --private --description "<original-description>"
-
Restore metadata:
gh repo edit <owner>/<repo> --add-topic <topic1> --add-topic <topic2> ...
Restore homepage URL if it existed.
-
Clone the new repo for work:
git clone https://github.com/<owner>/<repo>.git /tmp/re-promote-<repo>-new
cd /tmp/re-promote-<repo>-new
Phase 4: Migrate History (Squash & Clean)
This is the most critical phase. The goal is to create a clean, meaningful commit history across all branches.
4a: Analyze and Plan (Default Branch First)
-
Analyze the old repo's commit history on the default branch:
git -C /tmp/re-promote-<repo> log --oneline --first-parent <default-branch> | head -200
git -C /tmp/re-promote-<repo> log --oneline --merges <default-branch> | head -100
-
Detect natural grouping boundaries โ use this priority order:
- PR merge commits: If merge commits exist, each PR is a natural squash unit
- Feature branches merged: Group by merged branch names visible in merge commit messages
- Semantic grouping: If no PRs/merges, analyze commit messages for related changes (same prefix, same files touched, same time window) and group them into logical features/fixes
- Chronological chunks: As last resort, group by reasonable time windows
-
Present the plan:
## Proposed Commit Plan โ <default-branch>
| # | Squash Group | Original Commits | Proposed Message |
|---|-------------|-----------------|-----------------|
| 1 | Initial setup | abc1234..def5678 (12 commits) | chore: initial project scaffolding |
| 2 | Auth feature | ghi9012..jkl3456 (8 commits) | feat: add user authentication |
| ... | ... | ... | ... |
์คํผํค๊ฐ N๊ฐ ์ปค๋ฐ์ M๊ฐ๋ก ๊นจ๋ํ๊ฒ ์ ๋ฆฌํ์ด์!
์์ ํ ๊ฑฐ ์์ผ๋ฉด ๋งํด์ค์~
-
Wait for user approval before executing.
4b: Execute Migration (Default Branch)
For each approved squash group, in chronological order:
cd /tmp/re-promote-<repo>-new
git -C /tmp/re-promote-<repo> diff <group-start>^..<group-end> | git apply --allow-empty
git add -A
git commit -m "<approved commit message>"
If diff | apply fails (binary files, renames, etc.), use the snapshot approach:
git -C /tmp/re-promote-<repo> checkout <group-end>
find /tmp/re-promote-<repo>-new -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +
cp -r /tmp/re-promote-<repo>/* /tmp/re-promote-<repo>-new/
for f in /tmp/re-promote-<repo>/.[!.]* /tmp/re-promote-<repo>/..?*; do
[ -e "$f" ] && [ "$(basename "$f")" != ".git" ] && cp -r "$f" /tmp/re-promote-<repo>-new/
done
git -C /tmp/re-promote-<repo>-new add -A
git -C /tmp/re-promote-<repo>-new commit -m "<message>"
Windows ํธํ์ฑ: rsync๋ Windows Git Bash์ ๊ธฐ๋ณธ ์ค์น๋์ง ์๋๋ค. ์์ find + cp ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
Hidden files (.gitignore, .github/ ๋ฑ)๋ cp -r *๋ก ๋ณต์ฌ๋์ง ์์ผ๋ฏ๋ก ๋ณ๋๋ก ๋ณต์ฌํด์ผ ํ๋ค.
4c: Migrate Other Branches
For each non-default branch:
-
Analyze the branch:
git -C /tmp/re-promote-<repo> log --oneline <default-branch>..<branch> | head -50
-
If the branch has unique commits (not already merged to default):
- Find the diverge point from default branch
- Apply the same squash strategy
- Create the branch in the new repo from the appropriate base point
-
If the branch is fully merged into default, skip it (the commits are already in the default branch history).
-
Create and push the branch:
cd /tmp/re-promote-<repo>-new
git checkout -b <branch>
git checkout <default-branch>
-
Show branch migration summary to the user.
4d: Commit Convention Resolution
Commit messages follow a convention file. Resolve the convention in this priority order:
- Project-level: Look for
.claude/commit-convention.md in the repo root
- User-level: Look for
~/.claude/commit-convention.md
- Default: Use
references/commit-convention-default.md bundled with this skill
Read the resolved convention file and apply its rules to all commit messages.
Regardless of which convention is used, these rules are absolute and non-negotiable:
- NEVER include
Co-Authored-By: lines with Claude, Anthropic, AI, or any AI tool name
- NEVER include any AI attribution footer of any kind
- NEVER include
Generated by, Assisted by, or similar AI markers
- Preserve original human author attribution where meaningful
Phase 5: Transfer Issues
Open issues from the deprecated repo can be transferred to the new repo since they share the same owner.
-
List open issues:
gh issue list --repo <owner>/<repo>-deprecated_<NNN> --state open --json number,title --jq '.[] | "\(.number)\t\(.title)"'
-
If there are open issues, ask the user:
## Open Issues (N๊ฐ)
| # | Title |
|---|-------|
| 1 | Fix login bug |
| 2 | Add dark mode |
| ... | ... |
์ด์๋ค ์ ๋ ํฌ๋ก ์ฎ๊ฒจ์ค๊น์?
1. ์ ๋ถ ์ฎ๊ธฐ๊ธฐ โ ์ชผ์์!
2. ๊ณจ๋ผ์ ์ฎ๊ธฐ๊ธฐ โ ๋ฒํธ ์๋ ค์ค์
3. ๊ฑด๋๋ฐ๊ธฐ โ ๋์ค์ ํด๋ ๋ผ์~
-
Transfer approved issues:
gh issue transfer <issue-number> <owner>/<repo> --repo <owner>/<repo>-deprecated_<NNN>
Transfer each issue one by one. Labels and assignees are preserved. Issue numbers will change in the new repo.
-
Report transfer results:
## Issue Transfer
| Old # | New # | Title | Status |
|-------|-------|-------|--------|
| 5 | 1 | Fix login bug | transferred |
| 12 | 2 | Add dark mode | transferred |
๋ซํ ์ด์๋ deprecated ๋ ํฌ์ ์ ๋ณด๊ดํด๋์ด์~
Phase 6: Verify and Push
-
Verify all commit messages across all branches:
git log --format="--- %n%H%n%B" <default-branch> | head -500
for branch in $(git branch --format='%(refname:short)'); do
echo "=== $branch ==="
git log --format="%h %s" <default-branch>..$branch 2>/dev/null
done
-
Automated verification checks:
- Conventional commit format present
- No
Co-Authored-By lines containing Claude/Anthropic/AI
- No
Generated by or Assisted by markers
- Summary under 72 chars
- Correct type prefix
-
If any violations found, fix them before proceeding.
-
Show the final history:
## Final Commit History
### <default-branch>
| # | Hash | Message |
|---|------|---------|
| 1 | abc1234 | chore: initial project scaffolding |
| 2 | def5678 | feat: add user authentication |
### Other Branches
| Branch | Commits | Summary |
|--------|---------|---------|
| develop | 3 | ahead of main by 3 commits |
| feature/xxx | 2 | new feature in progress |
์คํผํค๊ฐ N๊ฐ ์ปค๋ฐ (M๊ฐ ๋ธ๋์น) ์ ๋ฆฌํ์ด์! ํธ์ํ ๊น์? ์ชผ์์?
-
Push all branches:
git push -u origin --all
Phase 7: Promote Readiness Check
Public ์ ํ ์ ์ ๋ ํฌ๊ฐ ๊ณต๊ฐ ์ค๋น๊ฐ ๋์๋์ง ์ ๊ฒํ๋ค. ๊ฐ ํญ๋ชฉ์ ์๋์ผ๋ก ๊ฒ์ฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํฌํธํ๋ค.
7a: ๋ฏผ๊ฐ ์ ๋ณด ์ค์บ
git log --all --diff-filter=A --name-only --pretty=format: | grep -iE '\.(env|pem|key|p12|pfx|credentials)$' | sort -u
grep -rn --include='*.{js,ts,py,go,java,rb,rs,yml,yaml,json,toml}' -iE '(api_key|apikey|secret|password|token|private_key)\s*[:=]' . 2>/dev/null | grep -v node_modules | grep -v '.git/' | head -20
๋ฐ๊ฒฌ๋๋ฉด ์ฆ์ ๊ฒฝ๊ณ ํ๊ณ ํด๋น ํ์ผ/๋ผ์ธ์ ๋ณด์ฌ์ค๋ค. ์ฌ์ฉ์๊ฐ ํ์ธํ ๋๊น์ง ์งํํ์ง ์๋๋ค.
7b: ํ์ ํ์ผ ์ ๊ฒ
| ํ์ผ | ์ํ | ์กฐ์น |
|---|
README.md | ์กด์ฌ ์ฌ๋ถ + ๋ด์ฉ ์ถฉ์ค๋ | ์๊ฑฐ๋ ๋น์ฝํ๋ฉด ๊ฒฝ๊ณ |
LICENSE | ์กด์ฌ ์ฌ๋ถ + ์ ํจํ ๋ผ์ด์ผ์ค | ์์ผ๋ฉด ์ฌ์ฉ์์๊ฒ ๋ผ์ด์ผ์ค ์ ํ ์์ฒญ (MIT, Apache-2.0, etc.) |
.gitignore | ์กด์ฌ ์ฌ๋ถ + ์ ์ ํ ํจํด | ์์ผ๋ฉด ์ธ์ด์ ๋ง๋ ๊ธฐ๋ณธ ์์ฑ ์ ์ |
for f in README.md LICENSE .gitignore; do
test -f "$f" && echo "OK: $f" || echo "MISSING: $f"
done
7c: README ํ์ง ์ ๊ฒ
README๊ฐ ์กด์ฌํ๋ฉด ๋ค์ ์์๋ฅผ ๊ฒ์ฌ:
| ์์ | ๊ฒ์ฌ ๋ฐฉ๋ฒ |
|---|
| ํ๋ก์ ํธ ์ค๋ช
| ์ฒซ ๋จ๋ฝ์ด ๋น์ด์์ง ์์์ง |
| ์ค์น ๋ฐฉ๋ฒ | install, setup, getting started ๋ฑ ์น์
์กด์ฌ |
| ์ฌ์ฉ๋ฒ | usage, example, how to ๋ฑ ์น์
์กด์ฌ |
| ๋ฐฐ์ง | ์๋จ์ shield.io ๋ฑ ๋ฐฐ์ง ์กด์ฌ ์ฌ๋ถ (๊ถ์ฅ) |
| ๋ฐ๋ชจ/์คํฌ๋ฆฐ์ท | ์ด๋ฏธ์ง๋ GIF ํฌํจ ์ฌ๋ถ (๊ถ์ฅ) |
๋น์ฝํ ํญ๋ชฉ์ด ์์ผ๋ฉด ๊ฐ์ ์ ์. ์ฌ์ฉ์๊ฐ ์ํ๋ฉด ์ฆ์์์ ๋ณด์ํ๋ค.
7d: GitHub ๋ ํฌ ์ค์ ์ ๊ฒ
gh repo view <owner>/<repo> --json description,homepageUrl,repositoryTopics,hasIssuesEnabled,hasWikiEnabled
| ์ค์ | ์ ๊ฒ |
|---|
| Description | ๋น์ด์์ผ๋ฉด ์์ฑ ์ ์ |
| Topics | ๋น์ด์์ผ๋ฉด ์ ์ ํ ํ ํฝ ์ ์ |
| Homepage URL | ์์ผ๋ฉด ์ ์ง, ์์ผ๋ฉด ๋ฌผ์ด๋ด |
| Issues | ํ์ฑํ ์ฌ๋ถ |
7e: ํจํค์ง ๋ ์ง์คํธ๋ฆฌ ์ค๋น (ํด๋น ์)
ํ๋ก์ ํธ ์ ํ์ ๋ฐ๋ผ ์๋ ๊ฐ์งํ๊ณ ์ ๊ฒ:
| ํ์ผ | ๋ ์ง์คํธ๋ฆฌ | ์ ๊ฒ |
|---|
package.json | npm | name, version, description, main/exports, license ํ๋ |
setup.py / pyproject.toml | PyPI | name, version, description, classifiers |
Cargo.toml | crates.io | name, version, description, license |
go.mod | Go modules | module path ํ์ธ |
ํด๋น ์์ผ๋ฉด ๊ฑด๋๋ด๋ค.
7f: Release / Tag ์ค๋น
-
ํจํค์ง ๋ฒ์ ๊ฐ์ง โ ํ๋ก์ ํธ์ manifest์์ ํ์ฌ ๋ฒ์ ์ ์ฝ๋๋ค:
grep -m1 'version' pyproject.toml setup.cfg setup.py 2>/dev/null
node -e "console.log(require('./package.json').version)" 2>/dev/null
grep -m1 'version' Cargo.toml 2>/dev/null
-
๊ธฐ์กด ํ๊ทธ ํ์ธ:
git tag -l | head -20
-
๋ฒ์ ์ผ์น ํ์ธ: ๋ฆด๋ฆฌ์ค ํ๊ทธ ์์ฑ ์ manifest ๋ฒ์ ๊ณผ ํ๊ทธ ๋ฒ์ ์ด ์ผ์นํ๋์ง ๊ฒ์ฆํ๋ค.
๋ถ์ผ์น ์ ์ฌ์ฉ์์๊ฒ ๊ฒฝ๊ณ ํ๊ณ ์ด๋ค ๋ฒ์ ์ผ๋ก ํต์ผํ ์ง ๋ฌผ์ด๋ณธ๋ค:
โ ๏ธ ๋ฒ์ ๋ถ์ผ์น ๊ฐ์ง
- pyproject.toml: 1.2.0b2
- ์ ์ ํ๊ทธ: v2.0.0
์ด๋ค ๋ฒ์ ์ผ๋ก ํต์ผํ ๊น์?
1. ํ๊ทธ๋ฅผ manifest์ ๋ง์ถค (v1.2.0b2)
2. manifest๋ฅผ ํ๊ทธ์ ๋ง์ถค (2.0.0) โ pyproject.toml ์์ + ์ปค๋ฐ
3. ์ ๋ฒ์ ์ง์
-
์ฌ์ฉ์๊ฐ ๋ฆด๋ฆฌ์ค๋ฅผ ์ํ๋ฉด:
git tag -a v<version> -m "<release message>"
git push origin v<version>
gh release create v<version> --title "v<version>" --notes "<release notes>" --repo <owner>/<repo>
7g: Promote Readiness Report
๋ชจ๋ ์ ๊ฒ ๊ฒฐ๊ณผ๋ฅผ ์ข
ํฉํ์ฌ ๋ฆฌํฌํธ:
## Promote Readiness Report
| ํญ๋ชฉ | ์ํ | ๋น๊ณ |
|------|------|------|
| ๋ฏผ๊ฐ ์ ๋ณด | PASS | ๊ฐ์ง ์์ |
| README.md | WARN | ๋ฐฐ์ง ์์ |
| LICENSE | PASS | MIT |
| .gitignore | PASS | Python |
| Description | PASS | ์ค์ ๋จ |
| Topics | WARN | ์์ โ ์ถ์ฒ: python, cli, whisper |
| ํจํค์ง (PyPI) | PASS | pyproject.toml ํ์ธ |
| Release | SKIP | ์ฌ์ฉ์ ๋ฏธ์ ํ |
PASS: N๊ฐ | WARN: N๊ฐ | FAIL: N๊ฐ
FAIL์ด ์์ผ๋ฉด ํด๊ฒฐํ ๋๊น์ง promoteํ์ง ์๋๋ค.
WARN์ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ฃผ๊ณ ์งํ ์ฌ๋ถ๋ฅผ ๋ฌผ์ด๋ณธ๋ค.
Phase 8: User Review and Promote
-
Show the new repo status:
## ์คํผํค๊ฐ ๋ค ์ค๋นํ์ด์! (์์ง Private)
- ์ ๋ ํฌ: https://github.com/<owner>/<repo> (private)
- ์์นด์ด๋ธ: https://github.com/<owner>/<repo>-deprecated_<NNN> (private)
- ๋ธ๋์น: N๊ฐ
- ๊นจ๋ํ ์ปค๋ฐ: N๊ฐ
- ์ฎ๊ธด ์ด์: N๊ฐ
- ์ ๊ฒ ๊ฒฐ๊ณผ: PASS N / WARN N / FAIL N
ํ๋ฒ ํ์ธํด๋ณด์ธ์! Public์ผ๋ก ๋ฐ๊ฟ์ค๊น์? ์ชผ์์?
-
Wait for user feedback. They might want:
- Commit message adjustments
- Branch cleanup
- README or other file changes before going public
- Additional issues transferred
- License addition
- Topic/description changes
-
Apply any requested changes, then re-run affected readiness checks.
-
When user approves, make public:
gh repo edit <owner>/<repo> --visibility public --accept-visibility-change-consequences
-
Final report:
## ์ชผ์์! ์คํผํค๊ฐ ๋ค ํด๋์ด์!
- ์ ๋ ํฌ: https://github.com/<owner>/<repo> (public!)
- ์์นด์ด๋ธ: https://github.com/<owner>/<repo>-deprecated_<NNN> (private)
- ๋ธ๋์น: N๊ฐ
- ๊นจ๋ํ ์ปค๋ฐ: N๊ฐ
- ์ฎ๊ธด ์ด์: N๊ฐ
๊ธฐ์กด ๋ ํฌ๋ private์ผ๋ก ์์ ํ๊ฒ ๋ณด๊ด ์ค์ด์์~
-
๊ด๋ จ ๋ ํฌ ์ถ์ฒ โ ๋ฆฌ๋ถํธํ ๋ ํฌ์ ์ฐ๊ด ๋์ ๋ ํฌ๋ฅผ ์ค๋งํธํ๊ฒ ์ถ์ฒ:
ํด๋ฆฌ์คํฑ ์์ง:
gh repo list <owner> --limit 50 --json name,pushedAt,primaryLanguage,repositoryTopics,stargazerCount,description --jq 'sort_by(.pushedAt) | reverse'
gh api user/orgs --jq '.[].login' | while read org; do
gh repo list "$org" --limit 20 --json name,pushedAt,primaryLanguage,repositoryTopics,stargazerCount,description
done
์ค์ฝ์ด๋ง:
| ์ ํธ | ๊ฐ์ค์น | ์ค๋ช
|
|---|
| ๊ฐ์ primaryLanguage | +3 | ๊ฐ์ ์ธ์ด ์คํ |
| ํ ํฝ ๊ฒน์นจ | +2/ํ ํฝ | repositoryTopics ๊ต์งํฉ |
| ์ต๊ทผ ์ปค๋ฐ (7์ผ ์ด๋ด) | +3 | pushedAt ๊ธฐ์ค |
| ์ต๊ทผ ์ปค๋ฐ (30์ผ ์ด๋ด) | +1 | pushedAt ๊ธฐ์ค |
| description ํค์๋ ๊ฒน์นจ | +1 | ํ๋ก์ ํธ ์ค๋ช
์ ์ฌ๋ |
| ๊ฐ์ ์ค๊ฐ๋์ ์ด์
| +2 | ํ ํ๋ก์ ํธ ์ฐ๊ด์ฑ |
| ์คํ 0๊ฐ (ํ๋ณด ํ์) | +1 | ์์ง ์๋ ค์ง์ง ์์ ๋ ํฌ |
์์ 3๊ฐ๋ฅผ ์ถ์ฒ:
์คํผํค๊ฐ ๊ด๋ จ ๋ ํฌ๋ ์ฐพ์์ด์! ์ชผ์์?
1. โญ owner/related-project โ ์ค๋ช
(์ต๊ทผ ์ปค๋ฐ: 2์ผ ์ )
2. โญ owner/another-tool โ ์ค๋ช
(์ต๊ทผ ์ปค๋ฐ: 5์ผ ์ )
3. โญ org/team-project โ ์ค๋ช
(์ต๊ทผ ์ปค๋ฐ: 1์ผ ์ )
์คํ ์ฐ์ด์ค๊น์? (๋ฒํธ ์ ํ / ๊ฑด๋๋ฐ๊ธฐ)
์ฌ์ฉ์๊ฐ ๋ฒํธ๋ฅผ ์ ํํ๋ฉด:
gh api -X PUT user/starred/<owner>/<repo>
๊ฑด๋๋ฐ๋ฉด ์กฐ์ฉํ ๋์ด๊ฐ๋ค.
Cleanup
After everything is confirmed, clean up temp files:
rm -rf /tmp/re-promote-<repo>*
Important Notes
- No destructive operations without confirmation โ every phase has a user checkpoint
- The old repo is never deleted โ only renamed and made private
- Private first, public later โ the new repo starts private for review
- No AI footers in commits โ absolute rule, no exceptions
- All branches are migrated โ not just the default branch
- Issue numbers will change after transfer โ this is a GitHub limitation
- Closed issues stay in the deprecated repo as archive
gh CLI is required โ if not installed, stop and tell the user
- If anything goes wrong mid-process, explain what happened and what state things are in
Error Recovery
| Situation | Recovery |
|---|
| Rename succeeded but new repo creation failed | The old repo is at -deprecated_NNN, rename it back: gh repo rename <repo> --repo <owner>/<repo>-deprecated_<NNN> |
| Push failed | Fix the issue locally, retry push. The old repo is safely archived. |
| Issue transfer failed for some issues | Report which ones failed, user can transfer manually later |
| Process interrupted mid-way | Report current state: which repo is named what, what's been pushed, what hasn't |
Prerequisites
gh CLI installed and authenticated (gh auth status)
- Git installed
- Write access to the target repository
- Permission to create repositories in the target owner/org