Original Note

Git & GitHub 团队协作最佳实践 - Read

Git & GitHub 团队协作最佳实践

适用于 3 人小团队 | 简单分支策略 (main + feature)


1. 每日开始开发的标准流程

步骤一:更新本地代码

# 切换到主分支
git checkout main

# 拉取远程最新代码
git pull origin main

命令说明:

  • git checkout main — 切换到主分支
  • git pull origin main — 从远程 originmain 分支拉取最新代码并合并到当前分支

步骤二:创建功能分支

# 创建并切换到新分支
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

预防冲突的最佳实践

  1. 频繁同步 — 每天开始工作前 git pull
  2. 小步提交 — 频繁提交,减少单次修改范围
  3. 及时沟通 — 告知队友你正在修改的文件
  4. 模块划分 — 团队成员尽量修改不同模块

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:表示从 oldestnewest 的闭区间;^ 用来把最早的 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 generator7cf5f2d6 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}