惯用svn的Git小白,如何避免代码覆盖的事故

习惯了SVN的Git新手,如何避免代码覆盖的事故

Git作为后起之秀,相对于CVS、SVN、CVS, Perforce这种集中式版本控制库他有一些创新性的改进,主要体现在几点:

  • 基于社交模式的开发协作和管理能力:

    用户通过WEB控制台,可以进行基本的项目管理比如团队成员管理、开发里程碑管理、简单的任务管理等;团队成员可以在WEB控制台上进行查看提交历史、查看代码变更历史、代码评审等功能;Git还提供WIKI知识共享和团队沟通的机制。Git的控制台基本可以满足协同开发的需求,所以很多协同开发平台就直接集成了它的功能,比如说coding、华为云以及各大互联网公司的DevOps平台。

  • 分布式仓库管理能力:
    Git是一种分布式版本控制系统,使用者在客户端从服务器端获取的不仅仅是文件副本,而是整个版本库的镜像。客户端不依赖服务器也能进行版本控制;从安全角度讲,若服务器端数据损坏了造成的损失也是有限的。

  • 快捷轻便的分支管理功能:
    相对于其他的版本控制工具,Git的分支操作非常轻量,分支的创建和切换也很快,因此Git提倡开发者使用切换分支、合并分支等功能在研发生命周期的各个阶段(开发、测试、发布)灵活的实现代码协作和版本控制。

  • 对持续集成持续部署的支持:例如Web Hooks、Deploy Keys都是为了便于持续集成持续部署提供的功能。

基于上述特性,Git足以成为大型项目、大型团队的协作利器,因此也成为了SCM软件的新宠。很多的开源项目已经转到github上了,Github的首页上显示,GitHub上已经有百万个开源项目了。 越来越多企业开发团队也都逐渐从SVN转到了git上,我们的团队也是其中之一。铁打的营盘流水的兵,团队陆陆续续有没用过Git的新人加入,每一波新人使用Git的时候都会造成一些代码覆盖的事故。又有新人来了,针对Git小白写一份简明教程,提示注意事项、便于他们快速理解,减少误操作。

不同于SVN,Git特有的操作

Git客户端和服务端都有一个版本库,而SVN只有服务器端有版本库,因此无论是从服务器端获取代码和提交代码与SVN都有所不同:

惯用svn的Git小白,如何避免代码覆盖的事故_第1张图片

Git本地有三个区域:

工作区 (workspace) :工作区即开发中存储并修改文件的区域;

索引区(index):工作区的文件添加到git的索引中,则git开始对文件进行跟踪监控,也叫数据暂存区域

本地仓库(Local Repository):当本地执行commit时,暂存区域的数据被记录到本地数据仓库中,可进行版本控制。

惯用svn的Git小白,如何避免代码覆盖的事故_第2张图片

  • ### 创建本地仓库和远程仓库的命令
#在本地创建仓库
mkdir demorepo 
cd demorepo 
git init 
##自己添加文件,此处略

#关联远端服务器,并推送到服务器端
git remote add origin  git@github.com:xxxtest/demorepo.git 
git push -u origin master

#从服务器端clone仓库到本地,相当于SVN的checkout
##使用git协议连接服务器库,需要在web控制台配置SSH Key,具体配置可以自己查
git clone git@github.com:xxtest/demorepo.git 
git clone https://github.com/xxxtest/demorepo.git
git push -u origin master
  • ### 提交本地库和提交远程库的命令

#修改本地文件后,提交到本地仓库(已经关联远程仓库)

cd demorepo

git add testfile.txt

git commit - m "Update testfile.txt"

#将本地修改提交到远程仓库

git push

  • 学会使用git分支

    Git 分支非常轻量,不像svn分支一样分支是物理的副本,Git分支是指向一个commit对象的一个可变指针, 创建分支就是创建分支指针 。 master分支是指向最后一次commit对象的指针, head指针指向当前工作目录。

    因此,Git推荐用户灵活使用分支提高开发协作效率,例如建立开发分支、功能性分支、临时性分支、预发布分支、bug修复分支等等。

    
    #创建分支
    
    $ git branch develop
    
    #切换到分支 'develop'(本地创建的或从远程获取的分支)
    
    $ git checkout develop
    
    
    #这一句等于以上两句的功能:创建并切换到分支
    
    $ git checkout -b develop
    
    #把本地develp分支推送到远端 
    
    $ git push origin develop:develop 
    
  • 学会使用GitLib Web控制台

    惯用svn的Git小白,如何避免代码覆盖的事故_第3张图片

很容易被Git新手忽略的是git的WEB控制台,这是一个有助于团队协作的高效工具,应该充分利用。
1. 点击提交Hash号能够查看提交历史和内容
2. 点击左侧菜单里的Files菜单能查看文件进行代码评审
3. 在Web控制台还能在Server端进行创建仓库、创建分支、修改文件等功能
4. 此外如左侧菜单栏所示,web控制台的Members提供团队成员管理、Milestone可以制定项目里程碑、Wiki能进行项目沟通等协同开发功能。更多功能有兴趣可以自己研究。

使用Git协作开发,注意几点避免代码覆盖事故

由于Git库在客户端和服务器端都有仓库,涉及到仓库之间的同步,所以使用不当容易造成事故。Git提倡灵活使用分支进行开发协作,方法有多种:如Git官网上的书中提到,某些大的开源项目的做法是开发者各自建立自己的开发分支,然后合并到共享的开发分支上,合并时需要有管理员审核通过后才能合并到主分支上。

而实际开发过程中,我们发现很多事故就是出在merge时,因此简单的大家使用同一个develop分支,尽量少让初级人员进行合并。基于大家共享的开发分支,下图示说明代码覆盖事故产生的过程:

  1. Step1和Step2:Jack和Rose同时从服务器端更新了文件A和B;
  2. Step 3:Jack对B进行了修改,变成新版的B+
  3. Step4:Jack在本地仓库提交了修改后的B+
  4. Step5:Jack将本地仓库的修改Push到了远程仓库
  5. Step6:Rose在本地修改了A,变成了新版本的A+

  6. Step7:Rose 在本地仓库提交了修改后的A+

  7. Step8:Rose准备将本地仓库的修改Push到远程仓库失败,因为Jack已经有了新的提交

  8. Step9:Rose需要从Server端Pull最新的修改到本机来,git会在没有冲突的情况下自动merge修改,若存在冲突会要求Rose手动合并。

    需要注意,Pull相当于先fetch在merge,这里很容易出错:比如Rose无意间也改动了B,merge解决冲突的时候覆盖了Jack的代码,在step10提交时事故就发生了。

  9. Step10:Rose提交代码,若操作无误,正常流程结束。

惯用svn的Git小白,如何避免代码覆盖的事故_第4张图片

此外,我们发现常常发生事故的场景是,开发者长时间不提交代码,提交代码时要进行大量的解决冲突的工作,初级开发者解决冲突不当就会覆盖别人的代码。

另一种常见的造成失误的情况就是,对IDE里的工具不熟悉、粗心大意导致失误,例如不小心选了强制覆盖远程代码的选型,造成代码覆盖事故。

根据对上述分析可知,使用同一个开发分支的协作开发者注意以下事项,就可减少错误:

  1. 首先要了解Git的基本原理和基本命令,知其然就知其所以然,就能减少失误。

  2. 及时提交代码、更新代码,避免因为长时间不更新代码而产生过多冲突文件,在解决冲突的过程中初级人员也是非常容易出错的。

  3. 开发人员一定要熟悉你所使用的git工具,无论是小乌龟还是IDE里集成的git工具,避免因为对工具不熟悉造成误操作。

  4. 本地修改前应该尽可能的避免本地库与远程之间有过多的差异,本地修改前执行一次git pull先把远程更新拉到本地;

  5. 推荐的操作步骤,提交前先把本地修改存入栈,然后从服务器端更新代码,这样可以避免过多的代码merge:
1、git stash
2、git pull
3、git pop
4、若有冲突解决冲突
  1. 当解决冲突时,若不是你修改过的文件就采用远程库里的版本,对于你自己修改过的文件也要查看日志找到提交人,跟他确认后再进行冲突解决,然后提交。

若事故已经发生了,如何解决问题

如果事故已经发生了,首先应该查看日志分析原因,找到出问题的节点撤销操作、回滚代码。关于事故的分析非常重要,今天来不及写了,先列一些参考资料和相关命令,回头慢慢补充

  • 查看日志,分析原因

    git log可以查看日志,选项的选项很多,详细可以查看官方文档和教程。

    Windows下的Tortorisgit等图形化工具,提供了更友好的日志查看功能,本来想写写的,发现一篇博文讲的很详细,请参考:

    http:\/\/blog.csdn.net\/tantexian\/article\/details\/42641457

    
    #log  --graph 结合使用时尤其有用,这个选项添加了一些ASCII字符串来形象地展示你的分支、合并历史 
    
    $ git log --pretty=format:"%h %s" --graph
  • 回滚代码
    撤销、回退相关命令,官方文档有详细的说明,请参考https:\/\/git-scm.com\/blog\/2010\/03\/02\/undoing-merges.html
    这里先简单列一些:
    运行带有 --amend 选项的提交命令尝试重新提交:git commit --amend

    取消暂存:git reset HEAD ...

    丢弃工作区的修改:git checkout -- filename

    Merge错了,需要回滚,若merge后还没有修改可以用reset,若已经修改了则需要用revert

    #Git撤销merge,merge后还未进行任何操作,可以reset

    $ git checkout [merge操作所在的分支]

    $ git reset --hard [merge前的版本号]

    #Git撤销merge,merge后已经进行了操作,需要revert

    $ git revert -m 【要撤销的那条merge线的编号】 【merge前的版本号】

推荐学习资料

  • git官方文档
  • 官方教程
  • 廖雪峰教程

你可能感兴趣的:(DevOps)