Git 合并提交的问题
文章目录
问题
- 基于 master 分支新开了功能分支,在半个月后需要同步 master 分支的工作(600+ 提交),于是合并 master 到功能分支。
- 合并完成后打开 Unity 发现工作区中多出一个
Assets/Plugins/iOS.meta
文件,此文件是 master 分支中最近新增的,功能分支上没有,但是合并 master 到功能分支后此文件被删除了! - 回到合并之前的状态,重新合并发现并没有错误地删除此文件。
使用 git log -p
可以显示出文件被改名为功能分支中的一个 .meta
文件,但是 Git 为什么在首次合并时会错误地删除文件呢,而之后不会呢?
这里很奇怪,没有找到原因。
发现
在查找相关资料后发现,Git 从设计上就是不追踪文件改名操作的!Git 只是根据快照的内容推测文件路径的变化,显示在差异中。
Why does Git not “track” renames? - Git FAQ - Git SCM Wiki
Is it possible to move/rename files in Git and maintain their history? - Stack Overflow
在 Git 中很难追踪文件路径的变化。
分析
Git 是通过提交引入修改,准确的说是每一个提交是一个快照。
首先定义下普通提交与合并提并的概念:
- 普通提交是指只有一个父结点的提交,只包含一次相关的改动
- 合并提交是指有多个父结点的提交,包含非首个父结点中所有提交的改动
Git 建议小且原子性的提交,这样易于追踪变化。
合并提交有以下缺点:
- 提交多的分支向提交少的分支合并时,包含的改动很多,这样容易产生问题。
- 在查看历史时合并提交往往易被忽略,因为人们都是假定合并提交只是将一个分支与另一个分支融合,并不会想到合并提交与普通提交一样,可以在其中做任何改动。
- 查看文件改动时,只会在历史中显示有合并提交,但并不会显示出合并提交对其作的改动。
建议
- 建议合并分支时仔细,出现任何问题都要查找发生原因。
- 可以考虑使用变基代替合并,这样会减少合并大量提交时大量改动容易出错的问题。
- 减少无用合并提交的数量,参见 Git 干净的历史 - 狂飙。
- 及早合并功能分支到 master 上。