overview
团队协作开发中,都会用到版本控制系统(VCS),通过ta我们能高效、便捷的控制团队中的代码和文件。相比较于SVN,Git作为分散式版本控制系統,对于分支(branch)的操作更加健全,通过将开发(develop)、新特性(feature)、热修复(hotfix)等模块化的操作,放到特定分支进行操作,方便管理和推进。在此需求上衍生出了Git的一个扩展集——git-flow,能够非常方便的在各个分支间进行操作。但是在Branch带给我们这么多便利的同时,也给我们的维护带来了一些常见的问题。

Q:

团队多人开发时,你在使用GitX查看代码log时,是否遇到过这样的情况…
overview
好吧,可能一般不会有这么混乱的分支结构,但如果不多加留意的话,你们团队的分支结构也会很难分辨,给维护分支带来了很大的困难。所以我们心中都希望分支是这样的…
overview
当前Branch中,每一次commit都很清晰,正式我们所想要的。

那么让分支中像图1这么混乱的的原因是什么呢?如何避免产生这种无意义的分支呢? (。•ˇ‸ˇ•。)

A:

原因:
在获取代码时,我们通常会使用git pull来拉取origin的代码。而这一步操作,本质上是fetch+merge的结合体,如果只有一个人对远端仓库进行管理的话,不会出现上述问题,但是多人频繁对同一个远端Branch进行操作的话,会因为拉取代码后local和remote对同一文件都进行了修改,git pull会在fetch后对这部分修改自动将本地repo和远端repo进行merge操作,并在终端中提示你当前的merge branch,这就造成了上图充满了梦幻色彩的Branch结构。

解决方案:
使用git pull --rebase替代git pull

git pull –rebase

使用--rebase时,Git会先将本地的repo暂存起来,并从上次pull时的状态下拉取远端最新的代码,最后在套用本地的变更。这种样相当于对本地Branch进行了一步对齐的操作,这就避免了git pull带来的一些不必要的Merge Branch。
这里有一个小细节需要注意:基于如上所说的操作,本地repo相当于重新提交,SHA-1会变,并且会作为最后一次commit(但是提交时间不变)。

关于解决冲突

Merge 解决冲突

使用merge时,发生了冲突,merge会在当前分支中提示你存在冲突,当你修改冲突后,需要在把修改作为一次commit提交到当前分支。

Rebase 解决冲突

使用rebase时,发生冲突时,Git会自动切换到一个新建的临时分支。当在临时分支中解决冲突后,需要git add .将修改加入暂存区(stage area),在运行git rebase --continue继续rebase,Git会自动切换回原本的分支,此时就完成了冲突的解决,并且不会新增commit,解决冲突的代码归属于本地repo。

rebase时有多个commit发生冲突,需要解决多次…所以说,rebase在带来整洁、正经分支的同时,也可能会浪费你很多时间来解决冲突,较大规模的代码合并还是推荐使用merge。

“偷懒”技巧

如果我们希望一直采用--rebase的操作,但是有感觉有时候会忘记加,还需要reset之后重新操作。那么我就在告诉你一个“偷懒”的技巧~
为当前项目配置rebase操作:
进入.git路径,打开config配置文件,在当前分支配置选项中加入rebase = ture

1
2
3
4
[branch "yourBranch"]
remote = origin
merge = refs/heads/yourBranch
rebase = true

为mac中所有项目配置rebase操作:
直接加到~/.gitconfig中,让所有追踪的Branch都遵守这个规则

1
2
[branch]  
autosetuprebase = always

最后

遵循以上的方式,你就已经做出了一个‘整洁又正经的Branch’了~ 在版本记录中,看着一条整齐划一的提交线,方便管理的同时,心中轻微的强迫症也得到了些许治愈 (❁´▽`❁)