Git Merge操作不当导致文件丢失

之前团队在使用Git的时候发生了文件 “莫名其妙” 丢失的情况,说是莫名其妙,是因为通过查看log提交记录,并没有任何关于这些文件的 “Deleted” 状态信息。最后检查出来是某位成员 merge 操作不当造成的。对于理解一些Git原理的人来说,可能在平时完全不会进行错误的操作。而对于不了解Git原理,特别是使用图形界面客户端且在使用Git的过程中SVN经验带入太多的人来说还是很容易犯这个错误的。

可以按如下步骤在本地复现该过程:

  1. git init git-example在本地创建git仓库,并cd git-example进入到该目录

  2. echo "aaa" > a创建文件a,Stagegit add .Commit (git commit -m 'add file a')

  3. 创建分支dev git checkout -b dev

  4. echo "AAA" > a 修改文件a,Stage –> Commit

  5. 切换到master分支 git checkout master

  6. echo "aAaA" > a 修改文件a,Stage –> Commit

  7. 创建文件夹dir mkdir dir, 添加文件b到dir中 echo "bbb" > dir/b, Stage –> Commit

  8. 切换到dev分支git checkout dev

  9. 合并master分支git merge master,合并有冲突,工作区状态为:

​ UU a

​ A dir/b

  1. 解决a文件冲突,保留两次提交的修改,并Stage(git add a)

  2. Unstagegit reset dir/b), 此时工作区状态为:

    ​ M a

    ​ ?? dir/

  3. 清理本地工作去git clean -fd

  4. Commit (git commit -m 'merge master')

  5. 切换到master分支git chekcout master

  6. 合并dev分支git merge dev, 合并完成后dir/b文件及dir目录将被删除

再次说明,这个明显不该犯的错误,对于使用图形界面且不熟悉Git原理的人来说是一个容易犯的错误。问题就发生在第11步的操作,dev分支的开发者可能认为自己没有添加dir/b文件,于是discard了对dir/b文件的添加。这其实是并不是在dev分支的合并中忽略了该文件,而是在合并提交中将该文件排除(删除了)。当dev分支开发完成,master合并时dir/b就被删除了。

团队中的愿意去花时间去了解Git原理的人可能很少,甚至对于游戏开发这种团队,要给没有任何程序背景的美术和策划讲清楚原理几乎时间不可能的事情。我的做法是告诉团队成员,在合并的时候除了解决冲突不要进行任何其它操作,按照这个原则执行下来暂时还没有继续犯同样的错误。