git是什么?如何使用git进行团队协作?

本文是一篇介绍性入门的文章,对于很多已经了解Git的朋友可以忽略此文,不喜勿碰。


git简介

公司新招聘来的同事,大多数都没有用过版本控制工具(有些还是直接使用U盘做拷贝,你敢信),少部分简单的使用过SVN,不过都是简单的commit与update。

这个也不能喷,在学校的时候老师一直在培训大家如何写代码(可能都没有),从来都没有教大家如何管理自己的代码,导致自己的项目乱七八糟,让自己做了很多徒劳的工作。

git是什么?

引用一下百科的解说:

Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 
为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

说白了就是一个版本控制工具,帮助大家管理自己的代码。

git与github有什么区别?

这个问题看似有点sb,不过确实很多人都分不清。

  • git(工具)是一个版本控制工具 
  • github(社区)是一个用git做版本控制的项目托管平台,并附带交友分享功能。。类似的平台还有bitbucket、oschina的码云这里写图片描述(逗逼名字)。这些平台基本都是以开源项目著称的,当然也提供一定的收费私有化托管服务。
  • 当然(私有化),估计大家还听说过coding、gitlab、gogs,这些都是做一些私有化项目托管的平台。coding是国内做的(鄙人不相信国内的任何东西),gitlab、gogs都是开源的git托管平台,可以自己私有化部署。
git与svn有什么区别?
SVN

svn可以理解为一个版本控制,加上SVN服务器备份的工具。如下所示: 
 
每一个SVN用户都可以从服务器checkout代码,同样也可以像服务器提交(commit)代码,可以更新(update)到别人提交的代码。

  • 优势:所有的操作都需要基于SVN中心服务器,所以操作起来必然很简单。
  • 劣势:正因为所有的操作都要基于SVN中心服务器,所以只要SVN中心服务出现冲突(conflict)、错误(error)都会给整个团队之中的成员带来灾难。
git

正因为SVN的劣势所在,git就应运而生,去掉了所有的操作都依赖于版本控制中心服务器的设计。使用的是高大上的分布式管理。如下所示:

每一个节点都可以充当控制中心的作用,所以从GIT服务器复制(clone)一份到本地,同样也可以单独对自己的本地git版本进行单独管理。在针对单个git版本库的操作(commit,pull)就如同SVN的commit与update操作。当然,不同版本库之间的操作就是拉取(pull),推送(push)。


理解git

git的常用命令有什么?

git的命令有很多,常见的就是我们在git –help上看到的命令,基本上都是对分支的提交拉取与不同分支的推送与拉取。如下所示:

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">usage: git [<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]</span>
           [-p|<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--paginate|--no-pager] [--no-replace-objects] [--bare]</span>
           [<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]</span>
           [-c name=<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">value</span>] [<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--help]</span>
           <<span class="hljs-command" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">command</span>> [<<span class="hljs-title" style="box-sizing: border-box;">args</span>>]</span>

The most commonly used git commands are:
   <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">add</span>        Add <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">file</span> contents <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> index
   bisect     Find <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">by</span> binary search <span class="hljs-operator" style="box-sizing: border-box;">the</span> change that introduced <span class="hljs-operator" style="box-sizing: border-box;">a</span> bug
   branch     List, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">create</span>, <span class="hljs-operator" style="box-sizing: border-box;">or</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">delete</span> branches
   checkout   Checkout <span class="hljs-operator" style="box-sizing: border-box;">a</span> branch <span class="hljs-operator" style="box-sizing: border-box;">or</span> paths <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> working tree
   clone      Clone <span class="hljs-operator" style="box-sizing: border-box;">a</span> repository <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> <span class="hljs-operator" style="box-sizing: border-box;">a</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">directory</span>
   commit     Record changes <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> repository
   diff       Show changes between commits, commit <span class="hljs-operator" style="box-sizing: border-box;">and</span> working tree, etc
   fetch      Download objects <span class="hljs-operator" style="box-sizing: border-box;">and</span> refs <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">from</span> another repository
   grep       Print <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">lines</span> matching <span class="hljs-operator" style="box-sizing: border-box;">a</span> pattern
   init       Create <span class="hljs-operator" style="box-sizing: border-box;">an</span> <span class="hljs-constant" style="box-sizing: border-box;">empty</span> git repository <span class="hljs-operator" style="box-sizing: border-box;">or</span> reinitialize <span class="hljs-operator" style="box-sizing: border-box;">an</span> existing <span class="hljs-constant" style="box-sizing: border-box;">one</span>
   <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">log</span>        Show commit logs
   <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">merge</span>      Join <span class="hljs-constant" style="box-sizing: border-box;">two</span> <span class="hljs-operator" style="box-sizing: border-box;">or</span> more development histories together
   mv         Move <span class="hljs-operator" style="box-sizing: border-box;">or</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">rename</span> <span class="hljs-operator" style="box-sizing: border-box;">a</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">file</span>, <span class="hljs-operator" style="box-sizing: border-box;">a</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">directory</span>, <span class="hljs-operator" style="box-sizing: border-box;">or</span> <span class="hljs-operator" style="box-sizing: border-box;">a</span> symlink
   pull       Fetch <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">from</span> <span class="hljs-operator" style="box-sizing: border-box;">and</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">merge</span> <span class="hljs-operator" style="box-sizing: border-box;">with</span> another repository <span class="hljs-operator" style="box-sizing: border-box;">or</span> <span class="hljs-operator" style="box-sizing: border-box;">a</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">local</span> branch
   push       Update remote refs along <span class="hljs-operator" style="box-sizing: border-box;">with</span> associated objects
   rebase     Forward-port <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">local</span> commits <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> updated upstream head
   reset      Reset current HEAD <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> specified state
   rm         Remove <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">files</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">from</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> working tree <span class="hljs-operator" style="box-sizing: border-box;">and</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">from</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> index
   show       Show various types <span class="hljs-operator" style="box-sizing: border-box;">of</span> objects
   status     Show <span class="hljs-operator" style="box-sizing: border-box;">the</span> working tree status
   tag        Create, list, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">delete</span> <span class="hljs-operator" style="box-sizing: border-box;">or</span> verify <span class="hljs-operator" style="box-sizing: border-box;">a</span> tag object signed <span class="hljs-operator" style="box-sizing: border-box;">with</span> GPG

See <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'git help <command>'</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> more information <span class="hljs-command" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span> <span class="hljs-title" style="box-sizing: border-box;">a</span> <span class="hljs-title" style="box-sizing: border-box;">specific</span> <span class="hljs-title" style="box-sizing: border-box;">command</span>.</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li></ul>

也许看到这么一个命令与分支会感到疑惑,很多人基本记不下来,git有很多与svn区别的功能,如stash、rebase、fetch等等,我们这里不做过多的介绍。git官方推出了已简单的在线learning工具,可以在:https://try.github.io/levels/1/challenges/1 在线编写 git 命令学习。

当然,还是记不住的朋友,比如我可以下载一个图形化工具 tortoise git

(与tortoise svn类似,俗话又叫“小乌龟”),地址在:https://tortoisegit.org/

那么我们就从我们的开发流程上来说说。


理解分支(branch)是什么?

以一个APP为例,我们研发一款移动APP的过程中,必然是一个迭代迭代的来。首先是1.0、1.1、1.2…….2.0…..3.0等等~。

这个时候为了防止影响已经稳定的线上版本,我们必然会对已经上线的版本做一个备份(master分之),使用另一个copy过来的项目进行开发(dev分之)。

即,这样公司的程序员小A就可以在dev分支上开发了,就算开发的时候小A脑残,不小心把逻辑弄错,无法正常运行的时候。我们还有稳定版本的Master分之,可以使用。(当然,你也可以回滚’revert’)

因为,存在一个本地仓库,我们就可以在一个功能没有完全开发完毕的时候先提交commit到本地仓库,测试好没有问题之后再push到远程git服务器。避免了,没有开发完成的项目产生任何差池无法处理。

如何进行团队协作?

如果只有一个开发者开发,那么上诉的操作并没有什么大碍。对于实际的开发工作中我们往往是多个开发者共同来开发一个项目。多人修改一个文件必然会出现冲突(conflict);不同人的思想开发一个逻辑难免会出现漏洞与错误;如何进行code review、代码质量把控、冲突降低才是git的优势。

同理,A、B、C三位员工还是可以在自己的个人分之上进行开发,所有的提交都不会影响到其他人。

尽量可能的降低耦合性就是git版本控制工具的核心思想。每个人都可以在自己的分支上畏缩无为的操作,直到自己的分配的功能开发完毕,这个时候就需要,将自己新增的功能回归到dev分支上,与其他的所开发的功能进行合并。

这个时候,就可以发起合并请求(merge request)

这里我们就需要使用到了图形化的git管理工具来协助我们了,常用的私有化git平台有gitlab、gogs、bitbuket。我们团队这里选择使用的是bitbucket,当然使用其他平台工具也是很类似的操作。

如下图所示,就是鄙人开发完成登录功能后,希望将自己的个人分之(dev_zhoushengtao)合并回归到dev分之,这个时候我就需要让同事(viki)帮我查看一下我所书写的代码有没有问题(code review)

这个时候viki就会收到一个merge的请求,来看merge request页面,就能看到我在dev_zhoushengtao分之上修改的代码与dev分之上的代码的差异。(与svn的patch显示方式类似),如下图所示:

viki可以看到我在dev_zhoushengtao分支上修改的每一行代码,如果觉得我所修改的代码符合逻辑,点击右上角的“合并”按钮dev_zhoushengtao上的所有的代码就回归到了dev分之上。当然,如果觉得修改的代码不好,点击“拒绝”就能够保护dev分之不被错误的逻辑所污染。

这里值得一提的是,dev分之我们可以设置合并权限,如设置viki才有权限对dev上的代码进行合并操作,避免其他开发者的违规操作,强制进行code review。这个时候,所有的代码质量、权限就全部集中到了代码管理员viki上。


一些特殊需求与操作

线上紧急bug处理,快速发版 
一个迭代开始的时候,我们往往相对于上一个迭代修改了很多代码。这个时候,由于开发时间与上线的速度问题,我们很难对上一个线上版本存在的bug进行快速修复。当然,如果出现p0级的bug,我们不得不进行快速修复上线的时候,我们之前设计的分之模型就比较有用了。

如下图所示:

因为master分之与线上的代码保持了一直,我们希望临时性处理一些问题,我们就从master分之临时性的拉出一个fix bug分之。将正在开发的分之切换到fix bug分之,快速修复bug上线。然后在切换到自己的dev_zhoushengtao分之进行迭代开发,做到的环境的快速切换。

多分支切换,本地修改暂存 
使用git的时候,我们往往使用branch解决任务切换问题,例如,我们往往会建一个自己的分支去修改和调试代码, 如果别人或者自己发现原有的分支上有个不得不修改的bug,我们往往会把完成一半的代码 commit提交到本地仓库,然后切换分支去修改bug,改好之后再切换回来。这样的话往往log上会有大量不必要的记录。

其实如果我们不想提交完成一半或者不完善的代码,但是却不得不去修改一个紧急Bug,那么使用’git stash’就可以将你当前未提交到本地(和服务器)的代码推入到Git的栈中。

<code class="hljs http has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">usage</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">git stash list  列举出自己的暂存代码</span>
   <span class="hljs-attribute" style="box-sizing: border-box;">or</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">git stash show  查看stash的详情</span>
   <span class="hljs-attribute" style="box-sizing: border-box;">or</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">git stash drop  丢弃stash</span>
   <span class="hljs-attribute" style="box-sizing: border-box;">or</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">git stash ( pop | apply ) 弹出栈中的stash</span>
   <span class="hljs-attribute" style="box-sizing: border-box;">or</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">git stash branch  stash某个分之</span>
   <span class="hljs-attribute" style="box-sizing: border-box;">or</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">git stash [save [--patch]  压入栈stash</span>
   <span class="hljs-attribute" style="box-sizing: border-box;">or</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">git stash clear 清空</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

最后说一句:git的操作很多,本人仅仅一篇博客并不能说明什么,有什么说不到位或者没说到的地方,请大家直接去多联系多操作,多使用–help命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值