--- name: git-sync description: Use when 用户说"对xxx目录做一次 git 同步/提交推送/同步一下xxx"。对指定 git 仓库执行 pull→冲突检查→拟提交说明→commit→push 全流程。 category: custom metadata: author: Hermes Agent last_updated: "2026-09-14" --- # Git Sync — 指定仓库一键同步 触发器:**"对 xxx 目录做一次 git 同步"** 或等效说法("同步一下 xxx 目录 / 提交推送 xxx")。目录无需是仓库根目录,脚本自动定位。 ## 工作流 1. **分析现状(必先做)**: ```bash bash ~/.hermes/skills/custom/git-sync/scripts/git-sync.sh status ``` 脚本会 fetch 远端并输出:ahead/behind 计数、未提交变更清单、diff --stat、未跟踪文件 —— 既是拟提交说明的依据,也用于判断是否分叉。 2. **全流程同步**(拟好提交说明后): ```bash bash ~/.hermes/skills/custom/git-sync/scripts/git-sync.sh 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 status` | fetch + 状态 + 变更摘要(拟提交说明用) | | `git-sync.sh sync -m "msg"` | 全流程同步,成功打印提交信息 | | `git-sync.sh pull-ff` | 仅 fast-forward pull | | `git-sync.sh 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 - 脚本由其他技能/agent 复用时同样适用,别只当本技能专用