--no-ff 不能省略,因为省略会导致快进合并,丢失独立合并提交,从而破坏特性边界与可追溯性,使测试、审计、回滚及ci/cd识别发布内容变得困难。

为什么 feature 分支必须从 main(或 develop)拉取,而不是从其他 feature 分支?
因为分支本质是指针,不是副本。从另一个 feature/login 拉出 feature/payment,会导致后者隐式继承前者未合入的变更——这些代码既没经过主干测试,也没走评审流程,后续合并时容易把问题带进 main。
常见错误现象:git merge feature/login 后发现 feature/payment 里多了一堆无关的登录逻辑,甚至出现意料外的冲突。
- 正确做法:始终基于稳定基线拉分支,比如
git checkout main && git pull && git checkout -b feature/payment - 例外场景:仅当两个特性存在明确依赖(如“支付”必须等“登录”接口就绪),才允许从已验证过的
feature/login拉,但需在 PR 描述中显式声明依赖关系 - Git 不会阻止你从任意分支拉新分支,但工具不拦不代表逻辑合理
git merge --no-ff 在集成到 main 时为什么不能省?
省略 --no-ff 会让 Git 尝试快进合并(fast-forward),结果就是 main 上看不到独立的合并提交,特性边界消失——你再也分不清哪几行是“用户注册”改的,哪几行是“密码重置”加的。
这直接破坏了特性可追溯性。测试、审计、回滚都变困难:比如线上发现 bug,只知道发生在某次 main 提交,却无法快速定位它属于哪个特性分支。
批量替换指定目录下所有 Git 仓库的远程地址(remote URL)。 当用户需要将 Git 仓库从一个服务器迁移到另一个服务器时使用。 触发词:git remote 替换、git url 批量修改、git 仓库迁移、更换 git 地址、批量修改 remote url。
- 执行命令必须是:
git checkout main && git merge --no-ff feature/user-register - 合并后
main历史里会出现一个明确的 merge commit,其 message 默认包含分支名,且第一父提交指向main上一节点,第二父提交指向feature/user-register的 tip - CI/CD 流水线若自动打 tag,也依赖这种非快进结构来识别“一次发布包含哪些特性”
feature 分支上频繁 git rebase 到 main 的风险
目的是保持同步,但盲目 rebasing 会改写提交哈希,导致协作中断。如果你已把 feature/search 推送到远程,队友基于旧 commit 继续开发,你一 rebase 再 push --force,对方本地历史就彻底脱节。
真实使用场景中,只有两种情况适合 rebase:
- 分支刚创建、尚未共享给他人,用
git rebase main整理本地提交顺序(比如把调试日志删掉再提交) - 团队约定“所有 feature 分支在合并前必须 rebase 到最新
main”,且所有人严格遵守,此时需配合git pull --rebase和禁止 force-push 到 shared 分支 - 绝大多数情况下,用
git merge main更安全——它保留时间线,也避免哈希变更引发的协作混乱
删除 feature 分支的时机和检查点
很多人 merge 完就立刻 git branch -d feature/x,但漏掉两个关键检查:
- 确认远程分支也已清理:
git push origin --delete feature/x,否则远程仓库堆积大量过期分支,干扰git branch -r查看 - 确认该分支的 commit 已被
main包含:运行git merge-base main feature/x,输出应与git rev-parse feature/x相同;否则说明 merge 失败或用了 --squash 导致历史丢失 - CI 系统有时会为 feature 分支生成临时 artifact,删分支前最好确认构建任务已归档或不再需要
轻量级分支的优势在于创建和销毁成本低,但“轻量”不等于“随意”。真正难的不是命令怎么敲,而是每次切分支、合分支、删分支时,脑子里得清楚这个指针背后承载的是谁的责任、在哪条交付线上、是否已被验证。










