实习第二周,花了两天时间重新认识了git。重温了一下git的基础操作,真切的感受到了git的强大。
由于之前并没有系统的学习git,而且一直使用图形化界面操作,所以很多概念都不是特别清楚,而且有些地方不是很懂为什么。
git基础学习:廖雪峰的git基础教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
git进阶学习:李鼎(哲良)翻译的git工作流教程:https://github.com/oldratlee/translations/tree/master/git-workflows-and-tutorials
git常用命令:阮一峰的常用 Git 命令清单:http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
重温基础
- 版本控制
git是一个分布式版本控制系统,那么既然是控制就代表了他有对文件进行增删改的功能,这样才能进行版本间的转换。(我之前一直都没用过这个核心功能,因为自己基本都是线性操作,连分支都不用,所以版本回溯的功能对我就是个摆设,基本上把git当成记事本用了。。。。。) - 几个重要的概念
远程库,版本库,工作区和暂存区,这几个概念廖雪峰的教程写的比较清楚,而且阮一峰的清单中第一张图也是整个基础教程的浓缩。
工作区:就是你的项目目录。
暂存区:你修改过的文件记录,就是通过git add命令后修改记录存放的地方。
版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。通过git commit命令后修改记录存放的地方,是本地版本的核心区。
远程库:别人机子上面的版本库。一般来说你有权限clone,但push与pull的权限就不一定了。
HEAD:git指针当前所指向的分支或版本。 - 常用操作
一般就是 git clone,git add ,git commit -m "message" ,git pull,git push,git checkout,git checkout -b ,git branch,git status,git merge。基本都在阮一峰的图上面了。 - 远程仓库
要注意的也就是ssh了,其他的就没什么了,一般来说和普通的下载与上传一样,但特殊情况比如出现冲突,那就是需要更新你的本地仓库了。 - 分支
git默认本地主分支位master,远程默认主分支为origin。
常见操作:一般来说,如果都从master的相同位置建立了新的分支A(修改了文件a),B(修改了文件b),C(与A一样修改了文件a的相同位置),D(修改了文件b,但与B修改的位置不同)。
=>第一步:要让A与master(未做过修改)合并,那只需要git merge A就可以了,git会自动合并A与master,a文件被修改。
=>第二步:要让B合并到A上,那首先需要切换到A分支,git checkout A,再合并,git merge B,那么git也会自动合并A与B,a,b文件均被修改。
=>第三步:要让C合并到B上,那首先需要切换到B分支,git checkout B,再合并,git merge C,那么git也会自动合并C与B,a,b文件均被修改。此时如果你切换回A分支会发现与B分支中的a文件不同。
=>第四步:要让B合并到A上,那首先需要切换到A分支,git checkout A,再合并,git merge B,那这时git并不会帮你合并分支,而是把A与B分支中文件相同位置的不同内容都放在A分支中的a文件中,并用 <<<<< ===== >>>>> 这三种符号进行划分与标识。
如果此时用git status查看状态会发现git显示 both modified:a.txt,这就意味着两条分支同时修改了文件a相同的位置。
如果这时你要切换到B分支,git会提示
$ git checkout B
a.txt: needs merge
error: you need to resolve your current index first
它会提示你先解决暂存区的文件。
那么这种情况就属于合并冲突,你需要根据自身需要修改a文件,再进行git add,git commit -m "A and B succ",这时A,B分支就合并了。
=>第五步:要让D合并到B上(B,D分支中修改b文件的位置不同),那么git也会自动合并D与B,b文件被修改。
总结:git会自动合并相同的内容,与新增的内容,但不会合并合不同的内容,而是将不同的内容提交到被修改的文件中,让当前的操作者决定如何修改。那么这就意味着当前操作者有权修改前人提交的文件(可以简单的理解为所有人都是平权的,不存在高级权限,只是当你提交后你就失去了控制权,新的提交属于公共文件,任何人都可以操作,当然也包括自己)。其实不难发现git的合并操作就是将修改的内容放在暂存区进行尝试提交,如果存在冲突就取消提交,让当前操作者决定如何操作。
- 标签
类似于给commit再加个tag,主要用于发布新版本时打tag。在图形化界面中进行操作会更加方便。
多人协作 => git工作流
多人协作是我实习的主要目的之一,毕竟项目不大可能由一个人去完成。
- 集中式工作流
据说好像有点类似SVN,但又不一样(开发者开始先克隆中央仓库。在自己的项目拷贝中,像SVN一样的编辑文件和提交修改;但修改是存在本地的,和中央仓库是完全隔离的。开发者可以把和上游的同步延后到一个方便时间点)。
该工作流只用到master这一个分支。(和我之前理解的git功能类似)
所有开发者在本地把自己工作完成后提交到master分支,再推送到远程分支上。这就意味着这个项目不能过于庞大,因为每次都是高度聚焦的提交。
worker1在提交完之后,后面的worker需要重新更新合并自己的代码,然后可能还要经过修改解决冲突后才能进行提交。
所以我感觉集中式工作流非常适合小一点的开发人数不多的项目。 - 功能分支工作流
功能分支工作流鼓励开发者之间协作和简化交流。核心思路是所有的功能开发应该在一个专门的分支,而不是在master分支上。这个隔离可以方便多个开发者在各自的功能上开发而不会弄乱主干代码。另外,也保证了master分支的代码一定不会是有问题的,极大有利于集成环境。
该工作流用到master与功能分支。
worker1在本地建立新的功能分支A,完成后将分支A推送到远程,那么远程也会多出分支A,其他worker都可以对该分支进行修改与讨论,并且都可以将远程的分支A合并到远程的master分支上(无论谁来做合并,首先要检出master分支并确认是它是最新的)。
通过隔离功能到独立的分支上,每个人都可以自主的工作,但必要时在开发者之间分享变更还是比较繁琐的。
功能分支除了可以隔离功能的开发,也使得通过Pull Requests讨论变更成为可能。一旦某个开发完成一个功能,不是立即合并到master,而是push到中央仓库的功能分支上并发起一个Pull Request请求去合并修改到master。在修改成为主干代码前,这让其它的开发者有机会先去Review变更。
功能分支工作流是开发项目中异常灵活的方式。问题是,有时候太过灵活了,对于大型团队,常常需要给不同分支分配一个更具体的角色。 - Gitflow工作流
Gitflow工作流定义了一个围绕项目发布的严格支模型。虽然比功能分支工作流复杂几分,但提供了用于一个健壮的用于管理大型项目的框架。
Gitflow工作流没有用超出功能分支工作流的概念和命令,而是为不同的分支分配一个很明确的角色,并定义分支之间如何和什么时候进行交互。除了使用功能分支,在做准备、维护和记录发布也使用各自的分支。
该工作流主要有两个分支master与develop分支,其他分支都是围绕这两个分支进行的。
master分支存储了正式发布的历史,而develop分支作为功能的集成分支。这样方便给master分支上的所有提交分配一个版本号。
=>功能分支:feature
从各种含义和目的上来看,功能分支加上develop分支就是功能分支工作流的用法。
每个新功能位于一个自己的分支,这样可以push到中央仓库以备份和协作。但功能分支不是从master分支上拉出新分支,而是使用develop分支作为父分支。当新功能完成时,合并回develop分支。新功能提交应该从不直接与master分支交互。
=>发布分支:release
当某一个功能分支完成开发后,该功能分支会和develop分支进行合并,然后develop再新建一个release分支用于Bug修复、文档生成和其它与发布有关的任务,此时进入发布循环,从这个时间点开始之后新的功能不能再加到这个release分支上。一旦release分支完成了,该分支将合并到master分支并分配一个版本号打好Tag。另外,这些从新建发布分支以来的做的修改要合并回develop分支。也就是说任务完成后release要被合并两次。
使用release分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。
=>维护分支:hotfix
维护分支用于给产品发布版本打补丁,这是唯一可以直接从master分出来的分支。修复完成,修改应该马上合并回master分支和develop分支,并且master分支应该用新的版本号打好Tag。
hotfix可以理解为一个直接在master分支上处理的临时发布。
实习的公司就是用的这种工作流。公司大佬给咱讲的时候完全听不明白,主要是因为自己git基础不行,这种东西还是要自己实践用过才好懂=_= - Forking工作流
Forking工作流不是使用单个服务端仓库作为『中央』代码基线,而让各个开发者都有一个服务端仓库。 这意味着各个代码贡献者有2个Git仓库:一个本地私有的,另一个服务端公开的,而不是共用一个服务端。
贡献的代码可以被集成,而不需要所有人都能push代码到仅有的中央仓库中,只有项目维护者才能push到正式仓库。 这使得Forking工作流成为开源项目的理想工作流。
这个工作流咱并没有实践过,所以也不好说啥,不过fork一些有意思的或是未来可能会被删掉的项目倒是非常不错的。 - Pull Request工作流
Pull Request可以和功能分支工作流,Gitflow工作流或Forking
工作流一起使用。 Pull Request要求要么分支不同要么仓库不同,所以不能用于集中式工作流。 在不同的工作流中使用Pull Request会有一些不同,但基本的过程是这样的:
1.开发者在本地仓库中新建一个专门的分支开发功能。
2.开发者push
3.分支修改到公开的第三方(例如Github,Bitbucket)仓库中。
4.开发者通过第三方发起一个Pull Request。
5.团队的其它成员review code,讨论并修改。
6.项目维护者合并功能到官方仓库中并关闭Pull Request。
Pull Request是其他工作流的一个便利的补充,让团队成员间的协作更轻松方便。这个咱也没搞过,所以也不知道说啥。。。。。。。
总结
git这种工具在理解了它的工作过程之后,用起来会简单方便很多。
不明所以简单的重复操作还不如花点时间一次性了结它的全部=_=,到头来还是花了很多时间,不过幸好有所收获。。。。。
感叹一句:公司大佬好多啊。。。。。