随着互联网时代的来临与发展,尤为分布式开发的大力引入,对于开发工程师来讲,代码管理变成了头等难题。10多我的或者更多的成员的研发团队如何管理同一份代码,异地办公如何跟同事有效的维护同一份代码?下面直接介绍Git,就不对Git和其余的版本管理工具进行比较了。css
Git属于分布式的版本控制系统,它具备如下特色:html
分布式工做流程:git
同传统的集中式版本控制系统(CVCS)不一样,Git 的分布式特性使得开发者间的协做变得更加灵活多样。在集中式系统中,每一个开发者就像是链接在集线器上的节点,彼此的工做方式大致相像。而在 Git 中,每一个开发者同时扮演着节点和集线器的角色——也就是说,每一个开发者既能够将本身的代码贡献到其余的仓库中,同时也能维护本身的公开仓库,让其余人能够在其基础上工做并贡献代码。由此,Git 的分布式协做能够为你的项目和团队衍生出种种不一样的工做流程,接下来的章节会介绍几种利用了 Git 的这种灵活性的常见应用方式。咱们将讨论每种方式的优势以及可能的缺点;你能够选择使用其中的某一种,或者将它们的特性混合搭配使用。
Git 提供的有如下三种工做流程:github
目前咱们团队使用的是最简单的方式,集中式工做流程,随着研发团队的壮大可能会选择使用第二种,下面咱们分别介绍下三种工做流数据库
1.集中式工做流vim
集中式系统中一般使用的是单点协做模型——集中式工做流。一个中心集线器,或者说仓库,能够接受代码,全部人将本身的工做与之同步。若干个开发者则做为节点——也就是中心仓库的消费者——而且与其进行同步。服务器
这意味着若是两个开发者从中心仓库克隆代码下来,同时做了一些修改,那么只有第一个开发者能够顺利地把数据推送回共享服务器。第二个开发者在推送修改以前,必须先将第一我的的工做合并进来,这样才不会覆盖第一我的的修改。这和 Subversion (或任何 CVCS)中的概念同样,并且这个模式也能够很好地运用到 Git 中。若是在公司或者团队中,你已经习惯了使用这种集中式工做流程,彻底能够继续采用这种简单的模式。只须要搭建好一个中心仓库,并给开发团队中的每一个人推送数据的权限,就能够开展工做了。Git 不会让用户覆盖彼此的修改。例如 John 和 Jessica 同时开始工做。 John完成了他的修改并推送到服务器。接着 Jessica 尝试提交她本身的修改,却遭到服务器拒绝。她被告知她的修改正经过非快进式(non-fast-forward)的方式推送,只有将数据抓取下来而且合并后方能推送。这种模式的工做流程的使用很是普遍,由于大多数人对其很熟悉也很习惯。固然这并不局限于小团队。利用 Git 的分支模型,经过同时在多个分支上工做的方式,即便是上百人的开发团队也能够很好地在单个项目上协做。网络
2.集成管理者工做流分布式
Git 容许多个远程仓库存在,使得这样一种工做流成为可能:每一个开发者拥有本身仓库的写权限和其余全部人仓库的读权限。这种情形下一般会有个表明``官方''项目的权威的仓库。要为这个项目作贡献,你须要从该项目克隆出一个本身的公开仓库,而后将本身的修改推送上去。接着你能够请求官方仓库的维护者拉取更新合并到主项目。维护者能够将你的仓库做为远程仓库添加进来,在本地测试你的变动,将其合并入他们的分支并推送回官方仓库。这一流程的工做方式以下所示:ide
这是 GitHub 和 GitLab 等集线器式(hub-based)工具最经常使用的工做流程。人们能够容易地将某个项目派生成为本身的公开仓库,向这个仓库推送本身的修改,并为每一个人所见。这么作最主要的优势之一是你能够持续地工做,而主仓库的维护者能够随时拉取你的修改。贡献者没必要等待维护者处理完提交的更新——每一方均可以按照本身节奏工做。
3.司令官与副官工做流
这实际上是多仓库工做流程的变种。通常拥有数百位协做开发者的超大型项目才会用到这样的工做方式,例如著名的 Linux 内核项目。被称为副官(lieutenant)的各个集成管理者分别负责集成项目中的特定部分。全部这些副官头上还有一位称为司令官(dictator)的总集成管理者负责统筹。司令官维护的仓库做为参考仓库,为全部协做者提供他们须要拉取的项目代码。整个流程看起来是这样的
这种工做流程并不经常使用,只有当项目极为庞杂,或者须要多级别管理时,才会体现出优点。利用这种方式,项目总负责人(即司令官)能够把大量分散的集成工做委托给不一样的小组负责人分别处理,而后在不一样时刻将大块的代码子集统筹起来,用于以后的整合。
介绍了上面三种工做流,想必你必定有想法使用哪种了,选择一个适合本身团队的工做流,只要是严格按照这种规则执行的话,相信你的研发团队对于代码的管理必定不会再混乱了,这也会大大提高团队的工做效率。
几乎全部的版本控制系统都以某种形式支持分支。使用分支意味着你能够把你的工做从开发主线上分离开来,以避免影响开发主线。在不少版本控制系统中,这是一个略微低效的过程——经常须要彻底建立一个源代码目录的副本。对于大项目来讲,这样的过程会耗费不少时间。 有人把 Git 的分支模型称为它的``必杀技特性'',也正由于这一特性,使得 Git 从众多版本控制系统中脱颖而出。为什么 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量,建立新分支这一操做几乎能在瞬间完成,而且在不一样分支之间的切换操做也是同样便捷。与许多其它版本控制系统不一样,Git 鼓励在工做流程中频繁地使用分支与合并,哪怕一天以内进行许屡次。理解和精通这一特性,你便会意识到 Git 是如此的强大而又独特,而且今后真正改变你的开发方式。
Git 建立分支
Git 是怎么建立新分支的呢?很简单,它只是为你建立了一个能够移动的新的指针。好比,建立一个 testing 分支,你须要使用 git branch 命令:
$ git branch testing
这会在当前所在的提交对象上建立一个指针
那么,Git 又是怎么知道当前在哪个分支上呢?也很简单,它有一个名为 HEAD 的特殊指针。请注意它和许多其它版本控制系统(如 Subversion 或 CVS)里的 HEAD 概念彻底不一样。在 Git 中,它是一个指针,指向当前所在的本地分支。在本例中,你仍然在 master 分支上。由于 git branch 命令仅仅建立一个新分支,并不会自动切换到新分支中去。
你能够简单地使用 git log 命令查看各个分支当前所指的对象。提供这一功能的参数是 --decorate 。
$ git log --oneline --decoratef30ab (HEAD, master, testing) add feature #32 - ability to add new 34ac2 fixed bug #1328 - stack overflow under certain conditions 98ca9 initial commit of my project
正上,当前 master 和 testing 分支均指向校验和以 f30ab 开头的提交对象。
分支切换
要切换到一个已存在的分支,你须要使用 git checkout 命令。咱们如今切换到新建立的 testing 分支去:
$ git checkout testing
这样HEAD就指向testing分支了。
那么,这样的实现方式会给咱们带来什么好处呢?如今不妨再提交一次:
$ vim test.rb $ git commit -a -m 'made a change'
如上图所示,你的 testing 分支向前移动了,可是 master 分支却没有,它仍然指向运行 git checkout 时所指的对象。这就有意思了,如今咱们切换回 master 分支看看:
$ git checkout master
这条命令作了两件事。一是使 HEAD 指回master分支,二是将工做目录恢复成master分支所指向的快照内容。也就是说,你如今作修改的话,项目将始于一个较旧的版本。本质上来说,这就是忽略testing分支所作的修改,以便于向另外一个方向进行开发。
如今咱们稍微再作些修改并 commit :
$ vim test.rb $ git commit -a -m 'made other changes'
如今,这个项目的提交历史已经产生了分叉。由于刚才你建立了一个新分支,并切换过去进行了一些工做,随后又切换回 master 分支进行了另一些工做。上述两次改动针对的是不一样分支:你能够在不一样分支间不断地来回切换和工做,并在时机成熟时将它们合并起来。而全部这些工做,你须要的命令只有 branch 、 checkout 和 commit 。
Git 合并分支
接下来我们举个稍微复杂点的例子,三个分支的分别处理不一样的事情,最后合并到一块
首先,咱们假设你正在你的项目上工做,而且已经有一些提交, 以下图:
如今,你已经决定要解决你的公司使用的问题追踪系统中的 #53 问题。想要新建一个分支并同时切换到那个分支上,你能够运行一个带有 -b 参数的 git checkout 命令:
$ git checkout -b iss53 Switched to a new branch "iss53"
它是下面两条命令的简写:
$ git branch iss53 $ git checkout iss53
你继续在 #53 问题上工做,而且作了一些提交。在此过程当中, iss53 分支在不断的向前推动,由于你已经检出到该分支(也就是说,你的 HEAD 指针指向了 iss53 分支)
$ vim index.html $ git commit -a -m 'added a new footer [issue 53]'
当你在 iss53 这个分支上正在顺畅的工做,这时候有个特别紧急的问题须要你来修复,那么为了避免影响 iss53 的正常工做,你须要作的是从新切换到 master 分支上来,在 master 分支的基础上再建立一个新的分支 hotfix ,而后在 hotfix 分支解决紧急的问题。
$ git checkout -b hotfix Switched to a new branch 'hotfix' $ vim index.html $ git commit -a -m 'fixed the broken email address' [hotfix 1fb7853] fixed the broken email address 1 file changed, 2 insertions(+)
这个时候 hotfix 分支上的问题完全解决了,你须要合并到 master 分支,而且部署上线, 那么你只须要在 master 分支使用 git merge 命令就能够了
$ git checkout master $ git merge hotfix Updating f42c576..3a0874c Fast-forward index.html | 2 ++ 1 file changed, 2 insertions(+)
在合并的时候,你应该注意到了"快进( fast-forward )"这个词。因为当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,因此 Git 只是简单的将指针向前移动。换句话说,当你试图合并两个分支时,若是顺着一个分支走下去可以到达另外一个分支,那么 Git 在合并二者的时候,只会简单的将指针向前推动(指针右移),由于这种状况下的合并操做没有须要解决的分歧——这就叫作 “快进( fast-forward )”。如今,最新的修改已经在master分支所指向的提交快照中了。
关于这个紧急问题的解决方案发布以后,你准备回到被打断以前时的工做中。然而,你应该先删除 hotfix 分支,由于你已经再也不须要它了, master 分支已经指向了同一个位置。你可使用带 -d 选项的 git branch 命令来删除分支:
$ git branch -d hotfix Deleted branch hotfix (3a0874c).
如今你能够切换回你正在工做的分支继续你的工做,也就是针对 iss53 分支
$ git checkout iss53 Switched to branch "iss53" $ vim index.html $ git commit -a -m 'finished the new footer [issue 53]' [iss53 ad82d7a] finished the new footer [issue 53] 1 file changed, 1 insertion(+)
这个时候 #53 问题解决后你就能够把代码合并到master了,操做跟刚才的 htofix 分支处理方式同样
$ git checkout master Switched to branch 'master' $ git merge iss53 Merge made by the 'recursive' strategy.index.html | 1 + 1 file changed, 1 insertion(+)
可是这和你以前合并hotfix分支的时候看起来有一点不同。在这种状况下,你的开发历史从一个更早的地方开始分叉开来( diverged )。由于, master 分支所在提交并非 iss53 分支所在提交的直接祖先,Git 不得不作一些额外的工做。出现这种状况的时候,Git 会使用两个分支的末端所指的快照(C4和C5)以及这两个分支的工做祖先(C2),作一个简单的三方合并。
和之间将分支指针向前推动所不一样的是,Git 将这次三方合并的结果作了一个新的快照而且自动建立一个新的提交指向它。这个被称做一次合并提交,它的特别之处在于他有不止一个父提交。
这个时候如何不须要 iss53 分支的话,你也能够删除 iss53 分支了
远程分支
以 github 为例,目前不少开源项目以及公司的研发项目代码通常都托管在 github ,那么就出现了远程仓库,远程分支等这些概念。
下面咱们从 github 远程仓库 clone 下来一份代码
若是你在本地的master分支作了一些工做,然而在同一时间,其余人推送提交到 git@github.com:glj1102/git_test.git 并更新了它的master分支,那么你的提交历史将向不一样的方向前进。也许,只要你不与 origin 服务器链接,你的origin/master指针就不会移动。
若是要同步你的工做,运行 git pull 命令。这个命令是抓取远程分支数据到本地分支,而且更新本地数据库,移动origin/master指针指向新的、更新后的位置。同时你也能够执行 git push 命令把你本地修改的数据提交到远程分支。
咱们使用的是 Worktile + github 来管理团队的,平时团队沟通,任务分配都是经过Worktile来作的,那么 Worktile 与github如何关联的呢?
Worktile绑定github代码仓储
在Worktile的 后台管理 > 服务管理 中找到 github ,点击添加
下一步会让你选择Worktile的一个 聊天群组 ,以后github的提交记录就会发送到这个群组中:
添加服务以后须要进行一些配置,配置方式有两种,一种是 受权模式 ,选择仓储,选择事件, 另外一种是 普通模式 ,这种模式Worktile会生成一个 Webhook 连接,拿到这个连接能够直接在github仓储中进行Webhook配置:
具体的配置Worktile后台github服务设置中有教程。
Worktile接收github发送的操做记录
根据不配置时选择的事件不一样,github会发送不一样的记录消息
经过上面对Git的介绍,对于团队管理者来讲,如何使用Git来有效的管理团队代码应该会有最基本的概念,那接下来就须要你真正的花时间来实践了。那么对于Git的命令集网上有不少例子的,下面我这里介绍两本Git的基本入门教程
Git 简易指南 http://www.bootcss.com/p/git-guide/
Git 图解 http://marklodato.github.io/visual-git-guide/index-zh-cn.html
本文做者:龚林杰
文章来源:Worktile技术博客
欢迎访问交流更多关于技术及协做的问题。
文章转载请注明出处。