问题场景
典型情况:两台设备协作开发
- 设备A:修改代码 → commit → push
- 设备B:pull → 测试 → 优化 → commit → push
核心问题:提交粒度过细 + 跨设备同步导致 commit 历史污染
- 未测试的中间状态进入主分支
- commit 历史充满「修复」「再修」等无意义记录
- 难以回溯和定位有效版本
最佳实践方案
方案一:Feature Branch + Squash Merge(推荐)
流程:
- 设备A创建功能分支:
git checkout -b feature/xxx
- 开发过程中随意 commit(草稿性质)
- Push 分支到 remote:
git push origin feature/xxx
- 设备B拉取分支测试:
git fetch && git checkout feature/xxx
- 测试修改后继续 commit + push
- 测试通过后,合并到主分支时使用 squash:
优点:
- 开发过程自由提交,不影响主分支
- 最终只有一个干净的、经过测试的 commit
- 符合模块化 commit scope 规范
方案二:Amend + Force Push
适用条件:单人开发、修改周期短、只有一个待测试的 commit
流程:
- 设备A首次 commit + push
- 设备B pull 后测试修改,使用
git commit --amend修改上一个 commit
- Force push:
git push --force-with-lease
方案三:本地多 Commit + Rebase 整理
流程:
- 本地多次 commit(不 push)
- 测试通过后,用
git rebase -i整理:
- 将多个 commit squash 或 fixup 为一个
- 最后 push
方案对比
方案 | 适用场景 | 复杂度 | 历史整洁度 |
Feature Branch + Squash | 多人协作/功能开发 | 中 | ★★★ |
Amend + Force Push | 单人/小改动 | 低 | ★★★ |
Rebase 整理 | 单设备/本地开发 | 高 | ★★★ |
Merge 选项详解
核心合并策略选项
选项 | 行为 | commit 历史 | 适用场景 |
--ff(默认) | 快进合并,仅移动指针 | 线性,无合并节点 | 分支无分叉时 |
--no-ff | 强制创建合并 commit | 保留分支拓扑 | 保留功能分支痕迹 |
--ff-only | 仅允许快进,否则失败 | 线性 | CI/严格线性历史 |
--squash | 压缩所有变更为暂存区 | 需手动 commit,单一节点 | 清理琐碎提交 |
--ff vs --squash 关键差异
差异要点:
--ff:保留原 commit,移动指针
--squash:丢弃原 commit 元信息,变更合并为一个新 commit
--squash后 feature 分支与 main 无关联(无法追溯来源)
其他常用选项
冲突处理:
--strategy=<strategy>:指定合并策略(recursive、ort、octopus)
-X <option>:策略参数,如-X theirs(冲突时取对方)、-X ours
提交相关:
--no-commit:合并但不自动 commit,允许检查后再提交
--edit/--no-edit:是否编辑合并 commit 信息
-m <msg>:指定合并 commit 信息
其他:
--abort:中止合并,恢复原状态
--continue:解决冲突后继续合并
--stat/--no-stat:是否显示变更统计
选择建议
目标 | 选项 | ㅤ | ㅤ |
保持线性历史 | --ff-only + rebase | ㅤ | ㅤ |
保留分支结构 | --no-ff | ㅤ | ㅤ |
清理多个琐碎提交 | --squash | ㅤ | ㅤ |
跨设备开发测试场景 | --squash(推荐) | ㅤ | ㅤ |
推荐工作流
基于双设备开发测试模式,推荐 Feature Branch + Squash Merge:
- 所有开发在 feature 分支进行
- 跨设备同步用 push/pull feature 分支
- 测试完成后 squash 合并到主分支
- 删除 feature 分支
主分支只保留经过测试的完整功能提交,符合
pump_station、actuator 等模块化 commit scope 规范。





