名称: git-workflow 描述: 管理Git操作,包括分支策略、提交约定、合并工作流程、冲突解决和工作树管理。触发关键词:git, branch, commit, merge, rebase, pull request, PR, cherry-pick, stash, reset, revert, checkout, switch, worktree, conflict, GitFlow, trunk-based, feature branch, release branch, version control, squash, amend, history, tag, remote, push, pull, fetch, clone. 允许工具: Read, Grep, Glob, Bash
Git 工作流程
概述
这个技能提供了关于Git最佳实践、分支策略、提交约定和协作工作流程的指导。它帮助维护一个干净且可导航的版本控制历史。
说明
1. 分支管理
- 遵循一致的命名约定(feature/, fix/, hotfix/, release/)
- 从适当的基础分支创建分支(main, develop, release branch)
- 保持分支专注且短期存在
- 及时删除已合并的分支
- 使用带有问题引用的描述性名称
2. 提交实践
- 编写有意义的提交消息(常规提交:feat, fix, docs, refactor, test, chore)
- 进行原子提交(每个提交代表一个逻辑更改)
- 使用常规提交格式,可选择范围和破坏性更改
- 在提交体中包含问题引用和上下文
- 谨慎修改提交(仅适用于未推送的提交)
3. 合并策略
- 选择适当的策略:合并提交、压缩或变基
- 在合并前审查更改(使用拉取请求)
- 谨慎解决冲突,了解上下文
- 维护干净的历史记录(在合并前进行交互式变基)
- 永不强制推送到受保护的分支
4. 工作树管理
- 使用工作树进行并行工作,无需分支切换
- 为隔离的功能开发或热修复创建工作树
- 列出活动工作树并在完成后清理
- 共享.git目录,同时保持独立的工作目录
- 适用于测试、审查拉取请求或同时处理多个功能
5. 冲突解决
- 理解冲突标记(<<<<<<, ======, >>>>>>)
- 在解决前检查完整上下文(git diff, git log)
- 对复杂冲突使用合并工具(git mergetool)
- 解决后测试(运行测试,验证功能)
- 在提交消息中记录非显而易见的解决方案
6. 协作
- 保持分支与基础分支同步
- 使用拉取请求进行代码审查
- 在适当时压缩提交(清理WIP提交)
- 保护重要分支(main, master, production)
- 清晰地沟通破坏性更改
最佳实践
- 原子提交:每个提交应代表一个逻辑更改
- 有意义的消息:描述什么和为什么,而不是如何(常规提交格式)
- 频繁分支:为所有更改使用功能分支
- 推送前拉取:与远程保持同步(fetch + rebase 或 merge)
- 合并前审查:所有更改都应被审查(拉取请求)
- 保护主分支:永不强制推送到main/master/production
- 干净历史记录:在合并前压缩WIP提交(交互式变基)
- 工作树用于并行工作:处理多个功能时使用工作树而不是暂存
- 冲突后测试:解决合并冲突后始终运行测试
- 记录破坏性更改:在提交消息中使用BREAKING CHANGE脚注
示例
示例1:常规提交消息
# 格式:<类型>(<范围>):<描述>
# 类型:feat, fix, docs, style, refactor, test, chore
# 功能添加
git commit -m "feat(auth): 添加OAuth2登录与Google提供者"
# 带问题引用的错误修复
git commit -m "fix(cart): 解决数量更新中的竞态条件
当快速点击添加/移除时,购物车数量可能变为负数
由于未同步的状态更新。
修复 #234"
# 破坏性更改
git commit -m "feat(api)!: 更改用户端点响应格式
BREAKING CHANGE: /users端点现在返回分页结果而不是数组。客户端必须更新以处理新格式。
迁移指南:https://docs.example.com/migration/v2"
# 文档
git commit -m "docs(readme): 添加Windows安装说明"
# 重构
git commit -m "refactor(db): 将查询构建器提取到单独模块"
示例2:分支命名约定
# 功能分支
git checkout -b feature/user-authentication
git checkout -b feature/JIRA-123-shopping-cart
# 错误修复分支
git checkout -b fix/login-redirect-loop
git checkout -b fix/JIRA-456-null-pointer
# 热修复分支(生产问题)
git checkout -b hotfix/security-patch-xss
# 发布分支
git checkout -b release/v2.1.0
# 实验分支
git checkout -b experiment/new-caching-strategy
示例3:Git工作流程命令
# 开始新功能
git checkout main
git pull origin main
git checkout -b feature/new-feature
# 常规开发周期
git add -A
git commit -m "feat: 实现功能部分1"
git push -u origin feature/new-feature
# 保持分支与主分支同步
git fetch origin
git rebase origin/main
# 或如果偏好合并
git merge origin/main
# 拉取请求前进行交互式变基以清理提交
git rebase -i origin/main
# 在编辑器中:压缩、重写或重新排序提交
# 拉取请求批准后,合并并清理
git checkout main
git pull origin main
git branch -d feature/new-feature
git push origin --delete feature/new-feature
# 处理合并冲突
git merge feature-branch
# 如果发生冲突:
git status # 查看冲突文件
# 编辑文件以解决冲突
git add <已解决文件>
git merge --continue
# 撤销最后一次提交(保留更改)
git reset --soft HEAD~1
# 撤销最后一次提交(丢弃更改)
git reset --hard HEAD~1
# 挑选特定提交
git cherry-pick abc123
# 为发布创建带注释标签
git tag -a v1.0.0 -m "发布版本1.0.0"
git push origin v1.0.0
示例4:工作树工作流程
# 列出现有工作树
git worktree list
# 为新功能创建工作树(创建分支和工作树)
git worktree add ../feature-auth feature/user-auth
# 从现有分支创建工作树
git worktree add ../hotfix-123 hotfix/critical-bug
# 使用分离HEAD创建工作树用于测试
git worktree add --detach ../testing-v1.2.0 v1.2.0
# 在工作树中工作
cd ../feature-auth
git status
# 进行更改,正常提交
git add .
git commit -m "feat(auth): 实现OAuth2流程"
# 完成后移除工作树(必须先切换到不同分支)
cd /original/repo
git worktree remove ../feature-auth
# 或如果工作树目录被手动删除
git worktree prune
# Loom特定:阶段在隔离的工作树中执行
# 每个阶段获得.worktrees/<阶段-id>/,分支为loom/<阶段-id>
# 这使得无需文件冲突的真正的并行执行
ls .worktrees/
# knowledge-bootstrap/
# implement-auth/
# add-tests/
示例5:冲突解决工作流程
# 尝试合并导致冲突
# 自动合并 src/api.rs
# 冲突(内容):在src/api.rs中合并冲突
# 自动合并失败;修复冲突然后提交结果。
# 检查哪些文件有冲突
git status
# both modified: src/api.rs
# both modified: src/config.rs
# 查看上下文中的冲突
git diff src/api.rs
# 文件中的冲突标记:
# <<<<<<< HEAD
# fn handle_request() {
# // 当前实现
# }
# =======
# async fn handle_request() {
# // 新的异步实现
# }
# >>>>>>> feature/new-api
# 选项1:在编辑器中手动解决
# 编辑src/api.rs,移除标记,保留所需代码
vim src/api.rs
# 选项2:使用合并工具
git mergetool
# 选项3:完全选择一方
git checkout --ours src/config.rs # 保留当前分支版本
git checkout --theirs src/config.rs # 采用传入分支版本
# 解决冲突后,暂存已解决文件
git add src/api.rs src/config.rs
# 验证解决方案
cargo test # 运行测试以确保无损坏
git diff --staged
# 完成合并
git commit -m "合并feature/new-api
通过结合同步和异步模式解决了api.rs中的冲突。
保持了当前config.rs的认证设置。"
# 如果合并变得太复杂,中止并尝试不同方法
git merge --abort
git rebase feature/new-api # 尝试变基代替
示例6:高级Git操作
# 暂存工作进度
git stash push -m "WIP: 半完成功能"
git stash list
git stash pop # 应用并从暂存移除
git stash apply stash@{1} # 应用特定暂存而不移除
# 挑选提交范围
git cherry-pick abc123..def456
git cherry-pick abc123 def456 ghi789 # 挑选特定提交
# 撤销提交(创建新提交以撤销更改)
git revert abc123
git revert --no-commit abc123..def456 # 撤销范围而不提交
# 重置到早期状态
git reset --soft HEAD~3 # 保留暂存更改
git reset --mixed HEAD~3 # 保留未暂存更改(默认)
git reset --hard HEAD~3 # 完全丢弃更改
# 引用日志:恢复“丢失”的提交
git reflog
git checkout abc123 # 恢复到被重置的提交
# 清理未跟踪文件
git clean -n # 干运行(显示将被删除的内容)
git clean -fd # 强制删除未跟踪文件和目录
# 二分查找以找到错误引入
git bisect start
git bisect bad # 当前提交是坏的
git bisect good v1.2.0 # 这个版本是好的
# Git检出中间提交,测试它
git bisect good # 或git bisect bad
# 重复直到Git找到问题提交
git bisect reset # 退出二分模式
示例7:Git别名以提高生产力
# 添加到 ~/.gitconfig
[alias]
co = checkout
br = branch
ci = commit
st = status
lg = log --oneline --graph --decorate
unstage = reset HEAD --
last = log -1 HEAD
amend = commit --amend --no-edit
wip = commit -am "WIP"
undo = reset --soft HEAD~1
branches = branch -a
tags = tag -l
stashes = stash list
# 按最后提交日期排序显示分支
recent = for-each-ref --sort=-committerdate refs/heads/ --format='%(refname:short) %(committerdate:relative)'
# 删除所有已合并的分支
cleanup = "!git branch --merged | grep -v '\\*\\|main\\|master' | xargs -n 1 git branch -d"
# 工作树快捷方式
wt = worktree
wtls = worktree list
wtadd = worktree add
wtrm = worktree remove