git简介

Git相关概念

Git与Github、GitLab

作为目前最流行的分布式版本管理工具,git从诞生伊始就备受关注。虽然这与它的作者Linus(大名鼎鼎的Linux操作系统的作者)的个人影响力有一定的关系,但更重要的是,git无论是在设计理念、性能、安全性还是易用性等方面都有着传统的版本管理工具无可比拟的优势。除此之外,它还是完全开源和免费的。

很多对Git完全不了解的同学可能会误以为Git和Github是一个概念,但其实两者有着本质的区别:前者是一个版本管理工具,而后者是一个项目托管平台。在英文中hub的意思是“中心,核心”,所以Github意为它是以Git作为版本管理工具的项目托管平台。

作为一个工具来说,Git是不需要联网的。只要在本地安装了Git,就可以使用命令行对本地项目进行版本管理。但如果你希望有一个网站可以帮你托管你的项目(这样即使本地数据损坏了,你的代码仍然可以找回来),或者希望把这些代码分享给别人,那么你可以在Github上通过远程仓库来管理它们。

Github的定位是开源项目托管平台,网站用户可以在这里看到最优秀的项目代码,包括Linux、chromium、jQuery等。Github倡导开源,希望通过分享促进计算机技术的发展。但是如果你需要管理自己的私人项目或者企业项目,那你就可以使用GitLab。GitLab最初就是为了解决github不便于管理私人和企业项目的问题出现的,现在几乎已经成为了企业开发的首选。

分布式与集中式版本管理

传统的项目管理工具,如CVS、SVN等,主要是进行集中式的版本管理。所谓的集中式,就是整个项目都由一台“中央服务器”来管理,每个开发人员需要从“中央服务器”拉取代码进行开发,开发完毕后把代码提交回中央服务器。由于拉取的只是代码本身,不包括提交记录等项目信息,所以一旦服务器中的数据损坏,所有的提交记录都会丢失,会给项目开发带来巨大的损失(图片来自网络)。
在这里插入图片描述

而分布式管理工具Git会在每台主机上维护一个完整的版本仓库,并且它不存在“中央服务器”,每台主机都可以认为是一台“服务器”。主机之间通过交换修改记录来保证项目进度的统一,Git会根据修改记录快速更新代码。这样即使一台主机的数据损坏,仍然可以从其他主机获取完整的项目数据,这非常有利于多人协同开发。
在这里插入图片描述
如果各个主机之间无法直接通信,也可以使用一台服务器作为中介,用于交换修改记录。或者直接在这台服务器上构建一个项目仓库,所有的开发者都向该服务器提交修改记录,服务器会保留这些记录,并依据它们来更新代码。然后每台主机就可以从服务器上拉取修改记录,本地的Git就会根据修改记录来更新本地仓库,以此来保证项目进度的统一。而Github和GitLab通常就可以看作这样一台“服务器”,它们为我们托管了一个远程版本的项目仓库。

厘清了这些概念,我们就来看一下Git的原理。

Git原理简介

版本库

Git中一个非常重要的概念叫repository,中文称为版本库,是Git管理项目所使用的项目仓库。通过git命令,你可以向向Git提交代码,或者查看对该项目进行过的所有修改,也可以快速地回到某次修改前的状态。如果是协同开发,还可以查到其他开发者的提交记录。这些功能都依赖Git提供的这个版本库。

关于Git的安装,由于不同平台下安装方法有一定差异,而且网上的教程相当多,这里不再详述。安装完Git后,打开命令行,输入git --version,如果可以看到这样的输出,就表示Git安装成功了:
在这里插入图片描述
现在你可以找一个合适的目录,新建一个空文件夹(请尽量避免路径中出现中文)。然后在命令行中进入该文件夹,输入git init,如图:
在这里插入图片描述
一个Git版本库就初始化完成了。现在该文件夹内就会出现一个.git文件夹,
在这里插入图片描述
这个.git文件夹就是Git的版本仓库,里面包含了Git管理项目所需要的所有文件,之后所提交的所有修改也都会被记录在该文件夹内的特定文件内。你可以把项目代码添加进来,如:
在这里插入图片描述
然后在命令行中使用 git add index.js 这样的命令将index.js添加到git中进行管理:
在这里插入图片描述
此时Git的结构如下(图片来自网络):
在这里插入图片描述
index.js所在的目录,就是图中左侧的工作区(Working Directory),它是我们进行代码开发的目录。如果是实际的项目开发,我们通常会在IDE(如eclipse、webstorm、idea等)中操作该目录下的文件。而.git文件夹就是图中右侧的版本库,它主要包含一个暂存区(图中的stage)和一个默认的master分支(图中的master)。

暂存区用于记录文件修改。当使用git add index.js这样的命令向Git提交代码时,Git就会把该文件中发生的变化记录在暂存区(注意,Git只记录修改的地方,比如某行新增了一个单词,或删除了某行等,这样可以加快更新速度)。

在命令行中输入git commit -m "xxx"可以把暂存区中的修改记录提交到主干分支,Git会根据修改记录来更新master分支的代码。-m后面的内容是关于本次提交的描述信息,你可以在这里记录修改了哪些内容,方便以后查看和回退。提交了修改之后,工作区的项目代码就和master分支的代码一致了。

每次执行commit都会在master分支上生成一个新的节点,用于记录本次commit后该分支的状态:
在这里插入图片描述
Git是使用C语言编写的,它使用一个名为HEAD的指针来指向当前分支中最新的节点,用另一个名为master的指针指向master分支中最新的节点(之所以使用两个指针,是因为Git存在分支管理,当你切换到其他分支时,HEAD会指向那个分支中最新的节点,后面会详细介绍),每次的commit产生的节点连起来就构成了我们的master分支。使用git status命令可以查看当前分支所有的commit,这就是你对该分支的所有修改记录。

所以如果某次commit出现了问题,只需要根据你所写的描述信息找到这个commit,然后用git reset命令回退到该commit之前的状态,就可以轻松回退代码。对于Git而言,只是把指针指向之前的某个节点,因此操作速度非常快。使用Git命令,你可以清楚地看到项目的整个迭代过程。

远程仓库

上面介绍的是在本地使用Git,此时你可以在完全断网的情况下使用Git进行正常的项目管理。但这种模式在多人协作开发的情况下并不适用,因为每个开发者每次进行commit,都必须把修改记录发送给团队其他成员,才能保证项目进度统一,这样效率非常低。

此时你可以搭建一个服务器,在服务器上新建一个远程仓库。团队的每个成员只要保持与这个版本库统一,就可以保证整个团队进度统一。

不过大多数情况下我们并不需要这样一个单独的服务器,你可以借助项目托管平台github或gitlab来做这件事。如果你想要开发一个开源项目,那么你可以在github上构建一个远程仓库,将它与本地仓库建立联系,通过在本地仓库和远程仓库之间进行代码的拉取(pull)和推送(push)来保持版本统一。如果你想要开发一个私人项目,或者正在参与公司项目,那么可以用GitLab进行版本管理。

远程仓库不仅可以作为本地项目的备份(对于个人项目,这可以增强安全性),还可以作为团队开发的管理平台,对项目管理有很大的帮助。

分支管理

上面说到,Git默认会创建一个master分支来管理项目代码。但是如果项目需要多人合作,往master分支上提交的各个commit就可能发生冲突(比如同时修改了某部分的代码),这样每个人每次提交代码时都必须手动解决冲突之后才能提交上去。更糟糕的是,如果某个开发者在解决冲突时无意间改动了其他开发者提交的代码,整个项目就会变得混乱起来。

另一种情况,如果你希望在项目中试验性地开发一个新功能,而这个新功能可能涉及到项目中相当多的文件。为了不影响项目中其他成员的正常开发,你就只能在本地保存你的修改。假如有一天你的本地数据发生了损坏,那么你为这个功能所编写的代码都将付诸东流。

Git使用分支策略来解决上面的问题,如图:
在这里插入图片描述
我们之前讲到,master分支是由一个个commit构成的链式结构,每次提交commit,这个结构就会长一点。Git会使用一个专门的指针master指向master分支的最新节点。如果我们现在通过git branch命令创建并切换到一个名为dev的分支,Git就会创建一个新的指针dev,并将master指针锁定在之前的位置(图中蓝色箭头指向的位置)。之后你在dev分支上所做的修改都会沿着之前的节点继续产生新的节点,但是master指针并不会移动,只有dev指针和HEAD指针在移动(从这里可以看出,HEAD指针永远指向当前节点位置,无论你切换到哪个分支)。

也就是说现在master分支的代码停留在了切换分支时的位置,你在dev分支上所做的修改都会沿着切换分支的节点产生一条新的链式结构。如果你现在切换回master分支,Git会直接把HEAD指针指到master指针所在的位置,于是你可以从图中蓝色箭头的位置继续master分支的开发。这样你在dev分支上所做的任何修改都不会影响到master分支。

下图可以更容易帮你理解分支切换的过程:
在这里插入图片描述
如图,每个分支都有一个专门的指针来指向最新的节点,你切换到哪个分支,Git就会把HEAD指针切向哪里(如切换到master分支时,Git直接把master指针赋值给HEAD),之后你所提交的commit就会在这个分支上产生新的节点。

但问题是,随着分支越来越多,我们如何把各个分支上的功能整合到一起呢?因为最终我们需要打包上线的是master分支中的代码,所以这个问题就是如何把创建出来的这些分支归并到master分支上。

通常情况下,作为团队开发的一员,我们没有向master分支提交代码的权限。管理员会给每个团队成员开放developer(开发者)权限,它允许我们从master上创建自己的分支,然后在自己的这个分支上进行开发。当我们开发完毕后,就需要向管理员提交一个归并请求(merge request),表示希望将当前的分支归并到master分支上去。管理员接收到这个请求,就会把当前分支和master分支的最新节点进行合并,在master上产生一个新的节点,这样我们在分支上所做的修改就纳入到master分支上了。

不过如果master产生的分支很多,在向master提交归并请求的时候就可能产生冲突(比如两个人都修改了某个文件,但是他的分支比你更早地归并到了master上,这个文件就可能发生冲突),这时候就需要管理员手动解决冲突。因为Git记录修改非常精确,所以在文件发生冲突时,它可以告诉管理员具体是哪些行发生了冲突,并且使用特殊的标记将这些冲突行标注出来。管理员手动解决冲突后,就可以把代码合并到master分支上。

这个时候,如果当前分支所做的工作已经全部完成,就可以清理掉该分支了。如果以后有新的功能要写,可以重新从master上创建一个分支,进行新的功能开发,然后按同样的策略进行分支合并。

有人可能觉得,有了分支之后不是仍然需要解决冲突吗?确实,多人协同开发时冲突是无法避免的。不过使用了分支策略后,我们解决冲突的次数大大减少,因为提交归并请求的次数远远少于提交commit的次数。

在实际的项目开发中,Git分支经常看起来是这样的:
在这里插入图片描述
master可以看做是实际的产品线,每个开发者都基于这个产品线独立地开发功能,然后不停地归并代码,直到最终项目开发完成。master分支上的每一个节点通常都对应正式产品一个小的版本。如果进行了一次大规模的归并,就会在master分支上产生一个相对稳定的节点,对外发布的时候就作为一个大的版本升级。

总结

本文只是对Git原理的简介,并没有涉及到Git的使用。如果想要学习Git的使用,可以参考廖雪峰的官方网站,讲得非常通俗易懂,很适合作为git的入门课程。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值