2cddf06b6c
Co-authored-by: 旅行呀~ <travelxiao@qq.com>
312 lines
13 KiB
Markdown
312 lines
13 KiB
Markdown
---
|
|
name: git-init
|
|
description: >-
|
|
Complete Git workflows on Windows for Gitea (and other hosts): init, signed
|
|
Chinese commits, push, clone, pull, fetch, branch, merge, tag, stash, and
|
|
Gitea SSH/GPG key verification challenges, using a local author profile,
|
|
DPAPI-encrypted access token, SSH, and GPG. Use when the user asks to
|
|
初始化 Git, git init, Gitea, 验证密钥, 验证SSH, 验证GPG, 找不到此签名对应的密钥,
|
|
提交, commit, 推送, push, 克隆, clone, 拉取, pull, fetch, 分支, branch, 合并,
|
|
merge, 标签, tag, stash, 远程推送, 配置远程仓库, 配置 SSH, 配置 GPG,
|
|
配置 Git Token, or uses the git-init skill.
|
|
---
|
|
|
|
# git-init
|
|
|
|
Windows PowerShell. Default remote host is **Gitea** (self-hosted or public). Do not use `eval "$(ssh-agent -s)"`. See [gitea.md](gitea.md) for URL forms, Token, SSH, and GPG on Gitea.
|
|
|
|
Resolve `scripts/`:
|
|
|
|
1. Workspace `.cursor/skills/git-init/scripts` if it exists
|
|
2. Else `$env:USERPROFILE/.cursor/skills/git-init/scripts`
|
|
3. Else tell the user to run `install.ps1` from the git-skills repo and stop
|
|
|
|
```powershell
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/<name>.ps1"
|
|
```
|
|
|
|
Secrets live in `%USERPROFILE%/.git-skills/` (never in the project).
|
|
|
|
## Security red lines
|
|
|
|
- Never read, print, or log `token.dpapi` or the **HTTPS access token**
|
|
- Never put the HTTPS access token in chat, argv, README, `.env`, or git config
|
|
- Never ask the user to paste the **HTTPS access token** into the conversation; use `store-token.ps1` on their machine
|
|
- **Exception (Gitea key verify only):** you MAY ask for the short-lived **challenge token** shown on `/user/settings/keys` → 验证 (GPG and/or SSH). Do not store it. Do not confuse it with the access token
|
|
- Do not run `store-token.ps1` or `store-profile.ps1` in the agent session
|
|
- Never `--force` / `--force-with-lease` unless the user explicitly asked
|
|
- Never `--no-verify` / skip hooks; never change an existing remote
|
|
- Never set `--global` `user.name` / `user.email`. `credential.helper` may be global
|
|
- Commit only when the user asked to commit/提交; push only when they asked to push/推送
|
|
- Never `reset --hard`, `rebase -i`, `push --delete`, or rewrite history unless the user explicitly asked
|
|
|
|
## Route
|
|
|
|
| User intent | Path |
|
|
| --- | --- |
|
|
| 初始化 / git init / 配置远程 / 首次提交 | **Init** |
|
|
| 提交 / commit | **Commit** (do not re-run init) |
|
|
| 推送 / push / 远程推送 | **Push** |
|
|
| 提交并推送 | **Commit** then **Push** |
|
|
| 克隆 / clone | **Clone** — [workflows.md](workflows.md) |
|
|
| 拉取 / pull / fetch | **Sync** — [workflows.md](workflows.md) |
|
|
| 分支 / 切换 / 新建分支 | **Branch** — [workflows.md](workflows.md) |
|
|
| 合并 / merge / rebase | **Merge** — [workflows.md](workflows.md) |
|
|
| 标签 / tag | **Tag** — [workflows.md](workflows.md) |
|
|
| stash / 暂存改动 | **Stash** — [workflows.md](workflows.md) |
|
|
| 状态 / log / diff / 现在 git 怎么样 | **Inspect** (`repo-status.ps1`) |
|
|
| 验证密钥 / 验证 SSH / 验证 GPG / 找不到此签名对应的密钥 / 开锁 | **Verify keys** (below) |
|
|
|
|
If the folder is not a repo and the user asked to commit/push/pull/branch, run **Init** first (ask for remote URL if missing). Clone does not init the current folder.
|
|
|
|
Examples: [examples.md](examples.md).
|
|
|
|
## Shared: profile + token
|
|
|
|
```powershell
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/profile-status.ps1"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/token-status.ps1"
|
|
```
|
|
|
|
- Profile `missing` → stop; user runs `store-profile.ps1` in their own terminal
|
|
- Token `missing`/`invalid` → required for **Init** and for **HTTPS Push**; for **SSH Push** continue without token. User runs `store-token.ps1` in their own terminal when needed
|
|
|
|
Do not ask for name/email/HTTPS access token in chat if the profile exists.
|
|
|
|
# Verify keys (Gitea SSH + GPG)
|
|
|
|
Proactive path when the user wants key verification, or Init finished adding keys, or UI shows 「找不到此签名对应的密钥」.
|
|
|
|
```
|
|
- [ ] Explain: open /user/settings/keys, click 验证 (challenge token ≠ access token)
|
|
- [ ] Ask for GPG challenge token (and Key ID if unknown)
|
|
- [ ] Ask for SSH challenge token
|
|
- [ ] Run verify-gitea-keys.ps1 with tokens received
|
|
- [ ] Show signature blocks; user pastes back into Gitea → 验证
|
|
- [ ] Remind: hard-refresh; only new commits show verified
|
|
```
|
|
|
|
**Ask in chat (required, do not wait for the user to invent the step):**
|
|
|
|
1. GPG: 「请打开 Gitea → 设置 → SSH/GPG 密钥 → 对应 GPG → 点验证,把页面上的令牌发给我(这是一次性挑战令牌,不是访问令牌)」
|
|
2. SSH: 「请再打开同一页的 SSH 密钥 → 点验证,把**另一个**页面令牌发给我」
|
|
|
|
When tokens arrive:
|
|
|
|
```powershell
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/ensure-gpg.ps1" -Name "<name>" -Email "<email>"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/verify-gitea-keys.ps1" -GpgToken "<gpg-page-token>" -SshToken "<ssh-page-token>" -KeyId "<key_id>"
|
|
```
|
|
|
|
- Only GPG: `-GpgOnly -GpgToken "..."`
|
|
- Only SSH: `-SshOnly -SshToken "..."`
|
|
- Missing token → script prints `need_token` / `ask=...`; ask again and stop until answered
|
|
|
|
Then paste the printed `BEGIN PGP SIGNATURE` / `BEGIN SSH SIGNATURE` blocks back to the user and tell them to click **验证** on Gitea. Do not claim verification succeeded until they confirm the UI shows 已验证.
|
|
|
|
After both verified, ensure local signing:
|
|
|
|
```powershell
|
|
git config user.signingkey "<key_id>"
|
|
git config commit.gpgsign true
|
|
git config --unset gpg.format
|
|
```
|
|
|
|
Details: [gitea.md](gitea.md).
|
|
|
|
# Init
|
|
|
|
```
|
|
- [ ] Detect
|
|
- [ ] Profile + token
|
|
- [ ] Remote URL + SSH/GPG
|
|
- [ ] git init + local author
|
|
- [ ] origin (do not overwrite)
|
|
- [ ] Inject credentials
|
|
- [ ] SSH
|
|
- [ ] GPG
|
|
- [ ] .gitignore + README
|
|
- [ ] First signed Chinese commit
|
|
- [ ] Push main
|
|
- [ ] Verify
|
|
```
|
|
|
|
Detect:
|
|
|
|
```powershell
|
|
git rev-parse --is-inside-work-tree
|
|
git remote -v
|
|
```
|
|
|
|
If `origin` already exists: report remotes, switch to **Commit**/**Push** if that is what they wanted, and stop init. Do not change remotes.
|
|
|
|
If the user did not give a remote URL, ask and wait.
|
|
|
|
Default: reuse `~/.ssh/id_ed25519` and an existing GPG key. Generate only when missing.
|
|
|
|
```powershell
|
|
git init -b main # skip if already a repo
|
|
```
|
|
|
|
Local author from `profile-status.ps1`:
|
|
|
|
```powershell
|
|
git config user.name "<name>"
|
|
git config user.email "<email>"
|
|
git remote add origin "<url>"
|
|
git config --global credential.helper manager # only if unset
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/inject-credential.ps1" -RemoteUrl "<url>"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/ensure-ssh.ps1" -Email "<email>"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/test-ssh.ps1" -RemoteUrl "<url>"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/ensure-gpg.ps1" -Name "<name>" -Email "<email>"
|
|
git config user.signingkey "<key_id>"
|
|
git config commit.gpgsign true
|
|
```
|
|
|
|
Show the **public** SSH key. Tell the user to add it in Gitea: **设置 → SSH / GPG 密钥**. Run `test-ssh.ps1` (supports custom SSH ports from the URL). Status `ok` even if ssh exits 1 when the message contains `Hi there` / `successfully authenticated` / `Welcome to Gitea`. If auth fails, wait for the user to add the pubkey.
|
|
|
|
**Gitea key verification is required** (official: unverified keys → 「找不到此签名对应的密钥」). After keys are added, go to **Verify keys**: **proactively ask** for the GPG and SSH challenge tokens from `/user/settings/keys` → 验证, then run `verify-gitea-keys.ps1`. Prefer OpenPGP for commits (`user.signingkey` = Key ID; do not set `gpg.format=ssh` unless the user wants SSH commit signing). Guide: [gitea.md](gitea.md). Official: https://docs.gitea.com/administration/signing/
|
|
|
|
Ensure `.gitignore` contains:
|
|
|
|
```
|
|
.git-skills/
|
|
*.dpapi
|
|
.env
|
|
.env.*
|
|
*.pem
|
|
id_rsa
|
|
id_ed25519
|
|
id_ecdsa
|
|
```
|
|
|
|
Create `README.md` only if missing (项目简介 / 基础使用说明 / 项目结构 / 开发说明). Do not overwrite.
|
|
|
|
Then **Commit** with message `初始化: 完成项目Git配置` if there is no commit yet, then **Push** `main` (`git branch -M main` first). Verify with the Push/Commit verify steps.
|
|
|
|
# Commit (every time)
|
|
|
|
Do this for the first commit and every later commit. Do not re-init.
|
|
|
|
```
|
|
- [ ] prepare-commit
|
|
- [ ] GPG key if signing=missing
|
|
- [ ] status / diff / log
|
|
- [ ] assert-no-secrets
|
|
- [ ] Stage related files only
|
|
- [ ] Signed Chinese commit
|
|
- [ ] Verify signature
|
|
- [ ] Push only if asked
|
|
```
|
|
|
|
```powershell
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/prepare-commit.ps1"
|
|
```
|
|
|
|
If `signing=missing`:
|
|
|
|
```powershell
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/ensure-gpg.ps1" -Name "<name>" -Email "<email>"
|
|
git config user.signingkey "<key_id>"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/prepare-commit.ps1"
|
|
```
|
|
|
|
Then:
|
|
|
|
```powershell
|
|
git status
|
|
git diff
|
|
git diff --staged
|
|
git log -5 --oneline
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/assert-no-secrets.ps1"
|
|
```
|
|
|
|
If `assert-no-secrets` is `blocked`, unstage those paths and do not commit them.
|
|
|
|
Stage **only related files**. Do not `git add -A` on later commits unless the user asked to commit everything. Init may `git add -A` after `.gitignore` is in place.
|
|
|
|
If there is nothing to commit, stop. Do not create an empty commit.
|
|
|
|
Message must be Chinese `类型: 描述`. Types: `初始化` / `新增` / `修复` / `优化` / `文档`. Infer from the diff; if the user gave a message, rewrite it into this format. Forbidden: `update` / `fix` / `test` / `修改一下`. Details: [reference.md](reference.md).
|
|
|
|
**Every commit must include `Co-authored-by` trailers** from the local profile (primary author always; plus optional `coAuthors`). Do not invent co-authors. Prefer profile author over any IDE default. If Cursor also appends `Co-authored-by: Cursor <...>`, keep the profile trailers from `emit-commit-message.ps1` (do not drop them). Build the message with:
|
|
|
|
```powershell
|
|
$subject = "类型: 描述"
|
|
$msg = & powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/emit-commit-message.ps1" -Subject $subject | Out-String
|
|
git commit -S -m $msg.TrimEnd()
|
|
```
|
|
|
|
Equivalent shape (must keep a blank line before trailers):
|
|
|
|
```
|
|
类型: 描述
|
|
|
|
Co-authored-by: 旅行呀~ <travelxiao@qq.com>
|
|
```
|
|
|
|
Always `-S`. Never strip `Co-authored-by` lines. Never `--amend` unless the user asked and the HEAD commit is yours, unpushed, and no hook failed.
|
|
|
|
```powershell
|
|
git status
|
|
git log --show-signature -1
|
|
git log -1 --format=%B
|
|
```
|
|
|
|
Confirm the body contains `Co-authored-by:` and author is `姓名 <邮箱>` from the profile. If the user also asked to push, continue to **Push**.
|
|
|
|
# Push (every time)
|
|
|
|
Do this for the first push and every later push. Do not re-init. Do not commit during Push unless the user also asked to commit.
|
|
|
|
```
|
|
- [ ] prepare-push
|
|
- [ ] Push current branch
|
|
- [ ] Verify
|
|
```
|
|
|
|
```powershell
|
|
git status -sb
|
|
git remote -v
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/prepare-push.ps1"
|
|
```
|
|
|
|
If `remote_missing`, ask for a URL and go to **Init** step “Add origin”, then retry. If HTTPS `token_missing`, stop and tell the user to run `store-token.ps1`.
|
|
|
|
```powershell
|
|
git branch --show-current
|
|
git rev-parse --abbrev-ref --symbolic-full-name '@{u}'
|
|
```
|
|
|
|
- No upstream: `git push -u origin HEAD`
|
|
- Upstream exists: `git push`
|
|
- After init, `main` may not exist yet: `git branch -M main` then `git push -u origin main`
|
|
- Never `--force` unless explicitly requested (warn that it rewrites remote history)
|
|
- Never push to a different remote/branch than the user named
|
|
|
|
```powershell
|
|
git status -sb
|
|
git log --show-signature -1
|
|
```
|
|
|
|
# Clone / Sync / Branch / Merge / Tag / Stash / Inspect
|
|
|
|
Read [workflows.md](workflows.md) and follow that path. Network ops always run auth first:
|
|
|
|
```powershell
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/repo-status.ps1"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/prepare-auth.ps1" -RemoteUrl "<url>"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File "<scripts>/prepare-push.ps1"
|
|
```
|
|
|
|
- **Clone**: `prepare-auth` then `git clone`; then `prepare-commit` inside the clone (do not commit unless asked)
|
|
- **Pull**: `prepare-push` then `git pull --ff-only`. If it fails, stop and report divergence; do not force
|
|
- **Inspect**: `repo-status.ps1` plus `git status` / `diff` / `log --show-signature`; read-only
|
|
|
|
## Additional resources
|
|
|
|
- Gitea URLs, Token, SSH/GPG verify: [gitea.md](gitea.md)
|
|
- Commit types, Windows SSH/GPG, troubleshooting: [reference.md](reference.md)
|
|
- Clone, pull, branch, merge, tag, stash, inspect: [workflows.md](workflows.md)
|
|
- Trigger examples: [examples.md](examples.md)
|