name: git-best-practices description: 针对异构仓库的提交、分支管理、PR和版本历史管理的Git工作流模式。适用于创建提交、管理分支、发起拉取请求或重写历史记录时使用。若无仓库文档支持,请勿用于非Git实施任务或特定仓库的发布策略决策。
Git最佳实践
始终有效的原则
当此技能加载时,所有Git操作都应遵循以下准则:
- 先探查后行动 — 在分支、合并或发起PR前,运行分支探查以确定仓库的默认分支和生产分支
- 约定式提交 — 每个提交使用
type(scope): description格式 - 显式暂存 — 按文件名添加文件,确保只提交预期的更改
- 保护共享历史 — 强制推送时使用
--force-with-lease;任何强制推送前需与用户确认
代理Git工作流
执行Git操作时遵循以下顺序:
- 检查状态 — 运行
git status和git diff HEAD;输出:工作树和未暂存/已暂存的差异 - 探查分支 — 识别并存储默认/当前/(可选)生产分支名称(见分支探查)
- 按名称暂存 — 对每个文件执行
git add 路径/到/文件;用git status验证 - 编写约定式提交 — 使用
type(scope): description格式,正文可选 - 安全推送 — 默认使用常规推送;仅当重写历史记录时使用
git push --force-with-lease origin {分支},且需用户确认
检查点提交
代理在长时间运行任务期间可创建WIP检查点提交。这些是开发过程中的临时产物,应在PR前清理。
- 前缀使用
wip:或标准约定式提交格式 - 即使在WIP状态下也保持更改逻辑分组
- 在发起PR前运行
/rewrite-history以构建清晰的提交历史
提交规范
- 按文件名显式暂存文件:
git add src/auth.ts src/auth.test.ts - 提交前用
git status验证暂存内容 - 避免提交密钥、
.env文件、凭证和大文件 — 若暂存文件看起来敏感,提醒用户 - 最终PR就绪状态下,每个提交应针对一个逻辑更改
强制推送
仅使用 --force-with-lease 以防止覆盖上游更改:
git push --force-with-lease origin feat/my-branch
无论分支如何,任何强制推送前都需与用户确认。
约定式提交
格式:type(scope): description
主题行规则:
- 小写,祈使语气,无尾随句点
- 少于72个字符
- 范围可选,但当存在清晰子系统时推荐使用
常见类型:
| 类型 | 用途 |
|---|---|
feat |
新功能 |
fix |
错误修复 |
docs |
仅文档 |
refactor |
无行为改变的重构 |
perf |
性能改进 |
chore |
维护、依赖、工具 |
test |
添加或更新测试 |
ci |
CI/CD流水线更改 |
build |
构建系统更改 |
style |
格式化、空格(无逻辑更改) |
提交正文
正文可选 — 仅当更改确实不明显时添加。主题行说明“做了什么”;正文解释“为什么”。
以下情况添加正文:
- 动机或权衡不明显
- 多部分更改受益于项目符号列表
- 需要外部上下文(链接、问题引用、根本原因)
示例
<examples>
<example name=“simple-fix”> 单行修复,无需正文:
fix(shell): 恢复Alt+F终端导航
</example>
<example name=“scoped-with-body”> 非明显修复,正文解释根本原因:
fix(shell): 使用HOMEBREW_PREFIX避免path_helper破坏登录shell中的插件
macOS path_helper在登录shell中重新排序PATH,将/usr/local/bin
放在/opt/homebrew/bin之前。这导致`brew --prefix`解析旧的
Intel Homebrew,使得fzf、zsh-autosuggestions和zsh-syntax-highlighting
在Ghostty(生成登录shell)中静默加载失败。
使用HOMEBREW_PREFIX环境变量(由.zshenv中的brew shellenv设置)替代
调用`brew --prefix` — 它在path_helper后仍有效且更快。
</example>
<example name=“multi-part-feature”> 具有项目符号列表正文的多部分功能:
feat(install): 添加claude引导运行时管理
- 将Claude默认值迁移到claude/defaults下的声明性文件
- 添加claude-bootstrap检查/修复/卸载,支持先备份后迁移
- 停止存储完整的claude/codex运行时树并加强漂移检查
</example>
<example name=“ticket-linked”> 具有分支和范围中工单引用的单仓库提交:
fix(pool-party): 处理重新连接时的陈旧结算状态
当参与者在结算过程中断开连接时,PoolSettlement合约保持待处理状态。
检查结算时间戳并在重新连接时使陈旧条目过期。
修复SEND-718
</example>
<example name=“submodule-bump”> 包含下游提交信息的子模块更新:
chore(submodule): 更新claude-code
将claude-code提升至88d0c75(feat(skills): 添加tiltup、specalign和e2e技能)。
对于简单更新,bump或bump claude-code submodule是可接受的。
</example>
<example name=“breaking-change”>
使用!后缀的破坏性更改:
refactor(api)!: 更改认证端点响应格式
/auth/token端点现在返回{ access_token, expires_in }
而非{ token, expiry }。所有客户端必须更新其解析器。
</example>
</examples>
分支探查
在分支或发起PR前,探查仓库的分支拓扑。运行以下命令并存储结果:
# 默认分支(大多数仓库的PR目标)
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
# 当前分支
git branch --show-current
# 生产分支(若与默认分支不同)
git branch -r --list 'origin/main' 'origin/master' 'origin/production'
当gh不可用或仓库无远程时的备用方案:
# 从本地引用推断默认分支
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'
# 最后手段:检查本地分支,若未知则大声失败
if git rev-parse --verify main >/dev/null 2>&1; then
echo main
elif git rev-parse --verify master >/dev/null 2>&1; then
echo master
else
echo "错误:无法确定默认分支(未找到main/master)。" >&2
exit 1
fi
存储探查到的分支名称并在后续所有命令中引用。在所有后续命令中使用实际分支名称。
分支命名
优先使用仓库分支命名约定。若无文档约定,使用:
格式:type/description-TICKET-ID
示例:
feat/add-login-SEND-77fix/pool-party-stall-SEN-68chore/update-depshotfix/auth-bypass
存在问题时包含工单ID。无工单时省略。
分支流程
优先使用仓库分支流程策略。若无策略文档,常见基线为:
{生产分支}(生产部署)
└── {默认分支}(暂存/测试网部署,PR目标)
├── feat/add-feature-TICKET
├── fix/bug-description-TICKET
└── hotfix/*(从生产分支分支用于热修复)
- 功能和修复分支从默认分支开始
- 热修复分支从生产分支开始
- PR目标为默认分支,除非仓库使用单分支流程
- 当默认分支和生产分支相同时,所有PR直接针对该分支
合并策略
优先使用仓库合并策略(许多组织要求)。
若无策略,以下默认值合理:
| PR目标 | 策略 | 理由 |
|---|---|---|
| 功能 → 默认分支 | 压缩合并 | 清晰历史,每个功能一个提交 |
| 默认 → 生产 | 合并提交 | 保留发布边界;可见部署点 |
| 热修复 → 生产 | 压缩合并 | 生产上的单一原子修复 |
PR工作流
规模
务实规模优于任意限制。无论PR大小,每个提交都应讲述清晰故事。PR应作为连贯单元可审查 — 若审查者无法在脑中完整把握更改,请考虑拆分。
PR创建
使用仓库原生PR工具(gh pr create、GitLab CLI或Web UI),包含:
- 短标题少于70个字符
- 摘要部分含1-3个项目符号点
- 测试计划作为项目符号检查清单
PR前历史重写
对于具有混乱WIP历史的分支,使用/rewrite-history以:
- 备份分支
- 重置到基础分支尖端
- 将更改重新提交为清晰的叙述序列
- 验证与备份的字节对字节匹配
- 在强制推送重写历史前与用户确认
- 发起PR并链接到备份分支
每个重写的提交引入一个连贯想法,基于前一个构建 — 如同教程教读者如何构建功能。