Files
atlas/git-sync/SKILL.md

82 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: git-sync
description: Use when 用户说"对xxx目录做一次 git 同步/提交推送/同步一下xxx"。对指定 git 仓库执行 pull→冲突检查→拟提交说明→commit→push 全流程。
category: custom
metadata:
author: Hermes Agent
last_updated: "2026-09-15"
---
# Git Sync — 指定仓库一键同步
触发器:**"对 xxx 目录做一次 git 同步"** 或等效说法("同步一下 xxx 目录 / 提交推送 xxx")。目录无需是仓库根目录,脚本自动定位。
## 工作流
1. **分析现状(必先做)**:
```bash
bash ~/.hermes/skills/custom/git-sync/scripts/git-sync.sh <repo> status
```
脚本会 fetch 远端并输出:ahead/behind 计数、未提交变更清单、diff --stat、未跟踪文件 —— 既是拟提交说明的依据,也用于判断是否分叉。
2. **全流程同步**(拟好提交说明后):
```bash
bash ~/.hermes/skills/custom/git-sync/scripts/git-sync.sh <repo> sync -m "<提交说明>"
```
自动执行:fetch → 仅落后则 `pull --ff-only` → `add -A` → `commit` → `push` → 打印提交 hash / 标题 / 文件统计 / 远端确认。
3. **按退出码分支处理**:
- `3` **DIVERGED**(本地与远端分叉)→ 必须用 clarify 问用户选哪边:
- **merge 合并**:`resolve merge`(产生合并提交,两边内容都保留)
- **以远程为主**:`resolve remote`(丢弃本地提交,破坏性)
- **以本地为主**:`resolve local`(force push 覆盖远端,破坏性)
- `4` **CONFLICT**:先跑 `git status` 看冲突文件,向用户报告是"pull 时本地改动与远端更新冲突"还是"merge 后的 unmerged paths";按用户指示解决后(编辑文件 / 选边 / `git add` + `git commit`)再重跑 sync
- `5` **NO_CHANGES**:如实报告"工作区干净、无变更",不硬造提交
4. **汇报结果**:提交短 hash(附长 hash)、标题、`N files changed, X insertions(+), Y deletions(-)`、push 远端确认行。
## 命令
| 命令 | 作用 |
|---|---|
| `git-sync.sh <repo> status` | fetch + 状态 + 变更摘要(拟提交说明用) |
| `git-sync.sh <repo> sync -m "msg"` | 全流程同步,成功打印提交信息 |
| `git-sync.sh <repo> pull-ff` | 仅 fast-forward pull |
| `git-sync.sh <repo> resolve merge\|remote\|local` | 分叉后的处理;remote/local 破坏性操作需 `GIT_SYNC_CONFIRM=yes` |
## 退出码
| 码 | 含义 |
|---|---|
| 0 | 成功 |
| 2 | 参数错误 / 目录不存在 |
| 3 | 分叉,需用户决策(或 push 被拒需重新决策) |
| 4 | 冲突(pull 被拒 / 存在 unmerged paths) |
| 5 | 无变更可提交 |
| 6 | 非 git 仓库 / 分支无 upstream / 无远端 |
| 7 | sync 缺 `-m` 提交说明 |
| 8 | 破坏性操作缺 `GIT_SYNC_CONFIRM=yes` |
## 提交说明写法
- 依据 `status` 输出的 diff --stat 与文件清单写,句式:`<动词+对象>: <做了什么/为什么>`,如 `feat(blogwatcher): 新增企业 RSS 源并修正去重逻辑`
- 多文件混合改动时突出主体内容,不写 "update" 空话
- 有破坏性变更或格式整体变化时在说明中点明
## 坑
- **先 `status` 再 `sync`**:提交说明必须基于真实 diff;直接盲跑 sync 无法拟说明
- 本地有未提交改动且落后于远端时,ff pull 会失败(本地改动将被覆盖)→ 属冲突路径(码 4),去问用户,不要 stash 后盲推
- sync 检测到 unmerged paths(`git ls-files -u`)会直接拒绝提交,先解决冲突
- `resolve remote`(`git reset --hard`)与 `resolve local`(force push)都会丢内容,必须先经 clarify 拿到用户明确选择,脚本侧再加 `GIT_SYNC_CONFIRM=yes`
- push 失败(码 3)通常是 pull 后又有人推了东西:重新 `status`,再走分叉决策
- **`pull.rebase=true` 的仓库**(本机 nexus 即如此):有未暂存改动时 ff-only pull 必失败报 "cannot pull with rebase",哪怕与远端无文件重叠——先用 `git diff --name-only HEAD origin/main` 确认无重叠,再 `git -c pull.rebase=false pull --ff-only`,不必惊动用户。脚本遇此会自动打印 hint
- **push 报 `could not read Username for 'http://<host>'`**:远端是 HTTP 且本机无该 host 凭据(keychain 里存的端口对不上也照样失败)。同主机若跑了 Gitea SSH,改 `git remote set-url origin ssh://git@<host>:2222/<owner>/<repo>.git` 即可直推;改前先 `git ls-remote <ssh-url>` 验证有权限,改后 `git push` 并用 `git ls-remote origin refs/heads/main` 核对远端 hash
- **`add -A` 会把未跟踪的大目录一并提交**(实测 node_modules 56MB / 5606 文件):`status` 里出现这类目录时先补 `.gitignore`(`node_modules/`、`.DS_Store`)再 sync,否则仓库历史被永久撑大
- **生成物目录会被 `add -A` 一并提交**(实测 nexus 的 `sreweekly/translation_tasks/`:767 个 `task_XXXX.txt`/`meta.json` 流水线中间产物,且流水线跑完会自己删掉这批文件,导致「先提交、后全量删除」两个巨量提交):同步前先判断 status 里的新目录是成果还是中间产物,后者不要入库
- 脚本由其他技能/agent 复用时同样适用,别只当本技能专用