版本控制
基本的版本控制,其实就类似于编写文档时的撤销和回退,在需要的时候将当前文本内容变为历史内容。所以程序代码的版本控制系统,核心就在于要保存历史记录,并有一个索引指向代码的各个历史版本,并能够通过索引随时将当前项目的内容替换为历史版本的内容。
Git
Git就是一种广泛使用的分布式版本控制系统,除了免费的GitHub外,各个公司、团队可以以Git为基础定制化自己的一套系统。Git做版本控制时,他所管理的版本历史记录,不是你代码的记录,而是代码改动的记录。即他不会记下你某个时间点代码内容是什么样的,他记录的是在那个时间点代码有什么样的变动。
常见工作模型
目前常见的Git工作模型大致是这样的:
1.先由主工程师完成基础框架,并将代码推送至服务器上,作为中央仓库
2.中央仓库的代码会有多个分支,比如master,dev等
3.每个成员需要从中央仓库clone一个本地仓库
4.项目的开发工作,基本都是在dev分支做。当完成一个版本的开发后,会合并到master分支
5.每个成员开发时,都需要从dev分支建立属于自己的分支,在这个分支上进行开发
6.成员在开发完成一个小功能时,需要提交代码至自己的本地仓库中
7.在完成一个大模块的开发后,需要将本地仓库同步至远程仓库
8.每个成员在开发过程中要注意保持自己本地仓库与远程仓库同步
提交代码:add 和 commit
在使用Git时,最常见的命令就是add和commit了。Git中有一个叫做暂存区(stage)的东西。每当有新的代码改动,都需要先执行add命令将改动加入到暂存区。add时,可以指定要加入的内容,比如add xxx.txt, 也可以偷偷懒一次全部加入add -A 或add .。在加入到暂存区之后,还可以继续开发,也就是可以有多次add,每次add都会将部分改动加入到暂存区。当你觉得差不多了,可以执行一次commit,也就是将当前暂存区内的所有改动,统一标记为一次提交,提交至本地仓库中。在提交后,会自动生成一个字符串,作为这次提交的索引,叫做commit id。 而这次提交所生成的commit,就相当于一个指针或者引用,指向了这一次提交。
随着工作的进行,会有很多很多commit引用,我们只需要知道commit对应的id,或者其他手段,获取到这个指针/引用,就可以获取到“在那次提交时项目的代码是怎么样的”。
同步仓库:pull 和 push
在本地仓库开发完成并向远程仓库同步时,要使用push。 笼统的说,push就是拿本地仓库去覆盖掉远程仓库。当然如果有冲突的话,这一请求会被拒绝掉。实际上,push命令所做的是:将当前分支,也就是HEAD所指向的分支,提交到远程仓库,同时将这一分支上的所有提交也一并提交到远程仓库去。HEAD指向master这样远程仓库已经存在的分支,那就相当于是更新了远程仓库的分支的提交记录。 而如果指向了其他远程仓库不存在的分支,比如新的feature1,此时就会更新远程仓库信息,告诉他:现在多了一个分支,这个分支有哪些改动。之后其他成员从远程仓库同步下来之后,也得到了你的新的分支信息。
从远程仓库同步下来的操作是pull。不过pull其实不是一个命令,他内部其实分为了两步。如果不执行pull,也可以分别通过这两个命令来实现pull的功能,这两个命令就是fetch和merge。
第一步,git fetch,他的作用是更新本地仓库关联的所有远程仓库中,各个分支的一系列提交记录。这里只是获取到,并不会有其他操作。第二步merge,则是将当前的本地提交与获取到的远程仓库的提交做一个合并,这就是上面说到的fast-forward的典型。一般情况下,直接pull更简单省事。但是一旦出现冲突,由于会自动的进行merge,自动的合并之后可能会出现很多问题,需要自己一个一个查。而如果先fetch之后,再查看一下有哪些更新,此时再手动merge,就会好很多。
注意事项
在一个团队中使用Git时,一定要细心,中央仓库在服务器上占用的资源是有限的,稍有不慎将一些无用的大体积文件上传到服务器都会造成很大的问题。我这里总结一些经验:
1.尽量少使用git add -A
2.每次add和commit前后都要注意检查是否有没必要提交的内容
3.本地commit时要做好code-review
4.提交代码,慎用push -f
5.遇事不决先建个分支,这样不管出什么问题起码不会影响到别人
6.执行commit时填写的 commit信息 一定要规范
7.分支名很重要,不能乱起
8.不用的、弃用的、开发完的一些分支,该删的删,留到后面管理会比较乱