Git | 集成分支使用的禁忌

20 阅读4分钟

引言

最近我在学习 Git,其中有一章节讲到了Git 集成使用的禁忌,恰巧在工作中也遇到了类似的问题,我利用这篇文章记录一下相关知识和实践。读完这篇文章,可以明白在集成分支和私有分支上可以做什么,不可以做什么。

集成分支使用的禁忌

禁止向集成分支执行修改历史的操作

场景

以 master 分支为例,master 分支是一个集成分支,我在 master 分支上开发,我提交了一个节点并推送到了远程,然后我发现有一些内容忘记提交了,我采用 --amend 的方式向该节点增加了一些内容,然后强行推送到远程,这时报错了,我以为是远程有别的提交,我就拉取远程代码并与本地的代码进行合并,合并后向远程推送还是无法推送成功。

解释出现该现象的原因

当我第一次提交节点并推送到远程之后,情况是这样的:

本地:
a --- b (master,origin/master)
远程:
a --- b (origin/master)

然后我发现有内容我忘记提交了,我就采用 --amend 的方式向该节点增加了一些内容。但是由于禁止强行推送内容到 master,所以这里报错了。

本地:
a --- b' (master,origin/master)
远程:
a --- b (origin/master)

我当时没有理解到这一层,还以为是远程 master 上有别人的新提交,所以我拉取了远程的代码到本地并进行了合并操作,之后的示意图是这样的,这样更没有办法向远程推送了。

本地:
a --- b' --- c (master)
 \          /
  -- b ---- (origin/master)
远程:
a --- b (origin/master)

总结起来出现该问题的原因是:

  • 不了解 master 分支上强行推送代码是不被接受的。
  • 向集成分支强行推送了代码。
  • 当推送不上去代码的时候没有看本地和远程的提交历史,直接拉取合并了代码。

注:

查看本地分支提交图
git log --oneline --graph -n 5

查看远程分支提交图
- 查看远程的分支列表
git branch -r
- 选择其中一个用 log 进行查看
git log --graph --oneline --decorate origin/feature-xyz
- 如果选择查看远程分支的且本地分支没有的提交
git log origin/master ^master --graph --oneline

我以上的场景是在 master 上进行开发,强行推送是根本就不会被接受的,那我如果是在某个非 master 的集成分支上强行推送呢?注意,也是不行的,即使能够推上去,也是不能强行推送的。

那为什么不能强行推送呢?强行推送会带来哪些不好的结果呢?

强行推送带来的直接后果是会改变远程分支的提交历史,而远程分支的提交历史一旦改变,其他同事在拉取代码的时候会造成不便:

  • 如果合并的话会产生分叉,提交历史不清晰,而且合并时可能会产生冲突。
  • 如果不合并还需要进行 rebase 操作。
比如远程由于我的强行推送,变成了 a---b---c'---d
同事本地是 a---b---c---e
同事如果不想产生分叉的话还需要 rebase 这个远程分支,
同事的本地分支就会变成 a---b---c'---d---c'---e'

再来回顾一下 rebase 的操作,比如此场景下的 rebase

  • 找出本地提交和远程的分叉点,这里是 b
  • 暂存本地提交 c 和 e
  • 将暂存的本地提交 c 和 e 依次应用到远程最新的 commit 的后面,最终本地分支变成了:
a---b---c'---d---c'---e'

规律总结与最佳实践

  • 公共分支和集成分支禁止改写历史,不能使用--amend、rebase、push -f,如果想要修复已有的提交,必须要新增提交。
  • 私有分支为了保持提交历史的简洁和线性,可以使用 --amend 和 rebase,在确保远程分支没有被其他人使用的情况下可以 push -f

参考