Git & GitHub 团队协作最佳实践
适用于 3 人小团队 | 简单分支策略 (main + feature)
1. 每日开始开发的标准流程
步骤一:更新本地代码
# 切换到主分支
git checkout main
# 拉取远程最新代码
git pull origin main
命令说明:
git checkout main— 切换到主分支git pull origin main— 从远程origin的main分支拉取最新代码并合并到当前分支
步骤二:创建功能分支
# 创建并切换到新分支
git checkout -b feature/功能名称
# 或者分两步
git branch feature/功能名称 # 创建分支
git checkout feature/功能名称 # 切换分支
命名规范:
feature/xxx— 新功能开发fix/xxx— Bug 修复hotfix/xxx— 紧急修复
步骤三:开始开发前检查
# 查看当前分支状态
git status
# 查看当前分支
git branch
2. 分支管理
常用命令
# 查看所有本地分支
git branch
# 查看所有分支(含远程)
git branch -a
# 切换分支
git checkout 分支名
# 创建并切换
git checkout -b 新分支名
# 删除本地分支(已合并)
git branch -d 分支名
# 强制删除本地分支
git branch -D 分支名
# 删除远程分支
git push origin --delete 分支名
最佳实践
- 一个功能一个分支,避免多功能混杂
- 分支名使用英文,简短且能描述功能
- 及时删除已合并的功能分支
3. 代码提交
git add — 暂存更改
# 暂存指定文件
git add 文件名
# 暂存多个文件
git add 文件1 文件2
# 暂存所有更改
git add .
# 交互式暂存(选择部分更改)
git add -p
参数说明:
-p(patch) — 交互式选择每个更改块是否暂存
git commit — 提交更改
# 提交暂存的更改
git commit -m "提交信息"
# 提交并显示差异
git commit -v
# 修改上一次提交信息
git commit --amend -m "新的提交信息"
Commit Message 规范:
<类型>: <简短描述>
[可选的详细描述]
常用类型:
| 类型 | 说明 |
|---|---|
feat |
新功能 |
fix |
Bug 修复 |
docs |
文档更新 |
refactor |
代码重构 |
style |
代码格式调整 |
test |
测试相关 |
示例:
git commit -m "feat: 添加用户登录功能"
git commit -m "fix: 修复用户头像加载失败问题"
查看提交历史
# 查看提交历史
git log
# 简洁模式
git log --oneline
# 图形化显示分支历史
git log --oneline --graph --all
4. 合并与变基
git merge — 合并分支
# 将 feature 分支合并到当前分支
git merge feature/功能名
# 合并时禁止快进(保留分支历史)
git merge --no-ff feature/功能名
参数说明:
--no-ff— 禁用快进合并,创建一个合并提交,保留分支历史
git rebase — 变基
# 将当前分支变基到 main
git rebase main
# 交互式变基(可合并、编辑提交)
git rebase -i HEAD~3
rebase 参数:
-i— 交互式变基,可对最近 N 个提交进行操作pick— 保留提交squash— 合并到前一个提交drop— 删除提交
Merge vs Rebase
| 特性 | Merge | Rebase |
|---|---|---|
| 历史 | 保留完整分支历史 | 线性历史,更整洁 |
| 冲突处理 | 一次性解决 | 逐个提交解决 |
| 安全性 | 安全,不改写历史 | 不用于已推送的分支 |
| 使用场景 | 合并功能分支到主分支 | 更新功能分支到最新主分支 |
建议:
- 功能分支合并到
main→ 使用merge --no-ff - 功能分支同步
main最新代码 → 使用rebase
5. 冲突处理
冲突产生场景
- 多人修改同一文件的同一部分
- 一个分支删除文件,另一个分支修改该文件
解决冲突流程
# 1. 尝试合并/变基
git merge feature/xxx
# 或
git rebase main
# 2. 查看冲突文件
git status
# 3. 打开冲突文件,手动编辑
# 冲突标记格式:
# <<<<<<< HEAD
# 当前分支的内容
# =======
# 要合并分支的内容
# >>>>>>> feature/xxx
# 4. 解决冲突后,暂存文件
git add 冲突文件
# 5. 完成合并
git commit # merge 方式
# 或
git rebase --continue # rebase 方式
# 6. 如果想放弃合并
git merge --abort # merge 方式
# 或
git rebase --abort # rebase 方式
使用工具解决冲突
# 使用可视化工具
git mergetool
预防冲突的最佳实践
- 频繁同步 — 每天开始工作前
git pull - 小步提交 — 频繁提交,减少单次修改范围
- 及时沟通 — 告知队友你正在修改的文件
- 模块划分 — 团队成员尽量修改不同模块
6. 推送代码
基本推送
# 推送到远程(已关联分支)
git push
# 推送到远程并建立追踪关系
git push -u origin 分支名
# 强制推送(危险操作,慎用)
git push -f
git push --force-with-lease # 更安全的强制推送
参数说明:
-u— 设置上游分支,之后只需git push-f— 强制推送,会覆盖远程历史--force-with-lease— 只有远程分支未被他人更新时才允许强制推送
首次推送 vs 后续推送
# 首次推送新分支
git push -u origin feature/xxx
# 后续推送(已建立追踪)
git push
推送失败常见原因
# 原因1:远程有新提交
# 解决:先拉取再推送
git pull --rebase origin 分支名
git push
# 原因2:分支不存在于远程
# 解决:使用 -u 参数
git push -u origin 分支名
# 原因3:无推送权限
# 解决:检查仓库权限设置
7. 完整工作流示例
# 生成密钥
ssh-keygen -t ed25519 -C "你的 GitHub 邮箱"
# 用户名配置
git config --global user.name "yumf"
git config --global user.email "yumf828@gmail.com"
# 把当前分支重置为和main分支一模一样
git reset --hard main
场景:开发新功能
# ========== Day 1:开始开发 ==========
# 1. 更新本地代码
git checkout main
git pull origin main
# 2. 创建功能分支
git checkout -b feature/user-auth
# 3. 开发并提交
git add .
git commit -m "feat: 添加用户认证模块"
# 4. 推送到远程
git push -u origin feature/user-auth
# ========== Day 2:继续开发 ==========
# 1. 继续开发(在功能分支上)
git status
# ... 修改代码 ...
# 2. 提交
git add .
git commit -m "feat: 完善登录逻辑"
# 3. 推送
git push
# ========== Day 3:同步主分支最新代码 ==========
# 1. 切换到 main 并更新
git checkout main
git pull origin main
# 2. 切回功能分支并变基
git checkout feature/user-auth
git rebase main
# 3. 如果有冲突,解决后继续
git add .
git rebase --continue
# 4. 强制推送(因为变基改写了历史)
git push -f
# ========== 功能完成:合并到 main ==========
# 1. 切换到 main
git checkout main
git pull origin main
# 2. 合并功能分支
git merge --no-ff feature/user-auth
# 3. 推送 main
git push origin main
# 4. 删除已合并的功能分支
git branch -d feature/user-auth
git push origin --delete feature/user-auth
快速参考卡
| 操作 | 命令 |
|---|---|
| 更新代码 | git pull origin main |
| 创建分支 | git checkout -b feature/xxx |
| 查看状态 | git status |
| 暂存更改 | git add . |
| 提交更改 | git commit -m "message" |
| 推送代码 | git push -u origin 分支名 |
| 合并分支 | git merge --no-ff 分支名 |
| 变基分支 | git rebase main |
| 解决冲突 | git add . → git commit / git rebase --continue |
| 放弃合并 | git merge --abort / git rebase --abort |
| 删除分支 | git branch -d 分支名 |
| 安全回滚提交区间 | git revert --no-commit old^..new |
常见问题速查
Q1: 撤销未提交的更改?
# 撤销工作区更改(未 add)
git checkout -- 文件名
# 撤销暂存区更改(已 add,未 commit)
git reset HEAD 文件名
git checkout -- 文件名
# 撤销最近一次提交(保留更改)
git reset --soft HEAD~1
Q2: 提交错了分支?
# 撤销提交,保留更改
git reset --soft HEAD~1
# 切换到正确分支
git checkout 正确分支名
# 重新提交
git commit -m "message"
Q3: 合并后想回退或撤销一串已提交代码?
如果提交已经推送到远程,或当前分支有多人协作,优先使用 git revert。它会创建新的反向提交,不删除历史,也不需要强制推送。
# 1. 查看当前工作区,确认没有未提交改动
git status
# 2. 创建回滚前备份分支
git branch backup/branch-before-rollback
# 3. 查看提交历史,确认要回滚的 commit 区间
git log --oneline --graph
# 4. 回滚从 oldest 到 newest 的整段提交,但先不自动提交
git revert --no-commit oldest^..newest
# 5. 检查回滚产生的文件改动和冲突状态
git status
# 6. 确认无误后提交回滚结果
git commit -m "revert: remove unwanted changes"
命令和参数说明:
git status:确认工作区是否干净,避免把本地未提交修改混进回滚。git branch backup/branch-before-rollback:在当前HEAD创建备份分支,方便必要时恢复。git log --oneline --graph:用简洁图形历史确认要回滚的 commit 区间。git revert:生成指定 commit 的反向修改,不改写已有提交历史。--no-commit:先把反向修改放进工作区,检查无误后再统一提交。oldest^..newest:表示从oldest到newest的闭区间;^用来把最早的oldest提交本身也包含进来。
如果 revert 出现冲突:
# 1. 手动解决冲突后暂存
git add .
# 2. 继续完成 revert
git revert --continue
如果想放弃本次 revert:
# 取消本次 revert,恢复到 revert 前状态
git revert --abort
本次 DSL 回滚示例:
git revert --no-commit aa267707^..7cf5f2d6
这表示回滚从 aa267707 feat(solidworks): add deterministic primitive VBA DSL generator 到 7cf5f2d6 fix(master): stop treating native SOLIDWORKS files as artifact contract 的整段提交。
只有在提交还没有共享给别人、也没有推送到远程时,才考虑用 reset 直接移动分支指针:
# 回退到指定提交,并丢弃之后的本地改动(危险)
git reset --hard 提交哈希
# 如果确实必须改写远程历史,优先使用 --force-with-lease
git push --force-with-lease
Q4: 如何暂存当前工作?
# 暂存当前工作
git stash
# 查看暂存列表
git stash list
# 恢复暂存
git stash pop
# 恢复指定暂存
git stash apply stash@{0}