Git版本控制系统之基本使用

     最早是通过接触著名的开源社区Github了解到Git的,但一直没有系统学习过。这次下定决心从头到尾系统的学一学,也将学习过程记录于此,供大家批驳。本篇文章先从以下几个方面简单了解一下Git:

  • Git的简介以及Git与GitHub的关系
  • Git的下载和初始化信息配置
  • Git的基础指令及其含义

一、Git的简介以及Git和GitHub的关系      首先Git是由Linux 的缔造者Linus Torvalds 创造的,当初这位大牛本着开源的精神将Linux 开源,那么就需要对成千上万的贡献者的代码进行管理,起初所有的代码都以邮件的形式发给Linus ,然后由他来手动整合。但是随着Linux越做越大,代码量也越来越大,已经无法完全由人来管理了。于是Linus选择使用商业系统BitKeeper来管理这些代码,BitKeeper是一个成熟的版本控制系统,直到2005年两家合作结束。于是Linus大神花了两周时间用C写出来了一个版本控制系统,就是现在已经无敌的Git。(牛就是这个样子的!),想要了解更多Git历史,可自行查阅资料,此处简单截取部分时间点以激发对git的兴趣。

     版本控制系统就是一类用于管理我们项目进度点的系统,对于每次的修改给予记录,一旦出现错误可以立即回滚。想想我们平时对于文件的修改,一旦修改之后,对于之前的内容将会丢失,就是你想要回到过去某个未修改时的状态,是无法做到的。而我们用版本控制系统追踪我们的项目文件,每次的修改都是记录在案的,可以随时回到过去。这里我们不讨论集中式版本控制系统和分布式版本控制系统的区别,我们只告诉你Git的分布式的,等学完之后你就会明白分布式的各种优点。

     相比于Git,我们可能更加熟悉的是GitHub。它是一个开源社区,是一个平台。很多优秀的项目都在上面开源,供全世界的程序员学习和完善。例如:apache/tomcat,eclipse/jetty,jquery/jquery等。我们说Git可以记录我们对工作文件的每次修改,以便于我们可以快速恢复,但是为了多人协同工作,我们就需要共享同一个项目源码,所以一般就会将项目源码放在一个服务器上,每个开发者从服务器上下载当前最新的项目并进行工作,工作结束之后向服务器推送自己所做的更改,这样每个人无时无刻都在开发(修改)着项目的各个功能,当然位于服务器上的项目也会无时无刻的记录每个人的每次提交修改记录。(出问题了可以迅速找到罪魁祸首)。而GitHub作为一个开源社区平台,它可以充当那个服务器。但是由于它是开源的,所以一般公司内部项目也是不建议利用GitHub作为公共服务器来进行开发的。一般会自建服务器配置成Git服务器,在内网中使用。

二、Git的下载和初始化信息配置      三大平台中,我从我自己使用的的windows平台介绍Git的安装,至于Linux和MacOS上的安装大家可自行查阅资料。windows平台下对Git的安装是简单的,前往https://git-for-windows.github.io下载msysgit,然后一键式安装即可。msysgit集成的是Git和Cygwin,Cygwin是一种在windows中模拟Linux/Unix环境的工具,因为Git是需要用到Linux/Unix的一些工具的,所以有人集成了两者以使得在windows平台下也能使用Git。下面我们简单说一下对Git的初始化信息的配置。      首先在安装完成之后,鼠标右键会增加了Git Bash here选项,那就是Git的命令行模式,我们点击即可展示命令行窗口。我们首先要做的就是告诉Git,本机的身份。因为以后我们在多人协作的时候,每次Git在提交的时候会署名当前提交者,而Git是如何得知提交者的信息的?就是在初始化信息的时候我们告诉它的。

$ git config --global user.name "Your name"
$ git config --global user.email "Your email"

一般我们配置以上两条信息即可,至于其他的信息配置,例如:默认编辑器等 ,大家在需要用到的时候可以查询资料简单配置一下即可。到此为止,有关Git的简单介绍基本介绍完成,下面我们看看在日常项目中最长使用的几个Git命令及其含义。

三、基本Git指令      这一小节是本篇文章的核心,主要涉及到初始化仓库,添加追踪文件,暂存文件,提交本地数据库,恢复到以前状态等。这些内容基本涵盖了日常项目中最常见的操作,但是想要更加灵活的掌握Git以发挥其在项目管理中的巨大作用,这些是仅仅不够的。下面我们看第一个指令,初始化仓库。

1、git init      这是一条用于初始化仓库的指令,执行它会在当前目录下创建.git文件夹,该文件夹就是用于管理当前目录中所有文件的改动的,至于里面都有哪些内容,后续文章会介绍,请记住,里面的内容不可随意更改,否则会破坏git结构导致无法跟踪工作区文件。例如,我在电脑 F盘中创建一个文件夹single,在git命令行中cd到该目录,然后执行git init ,结果如下:

打开当前目录,看到一个文件夹.git,这就是init命令执行之后创建的结果,它就是整个版本控制的核心。至于里面的内容结构我们在后续的文章中介绍。

从此,在f:/single目录下为工作区,在这个目录下的文件都是可以被git追踪的。

2、git add filename      我们说初始化之后,工作区中的文件是可以被追踪的,但是只有告诉git哪些文件需要追踪,它才会显式的去追踪该文件,否则git永远会在你提交的时候告诉你工作区还用哪些文件处于Untracked状态。而我们add命令就是用来显式告诉git哪些文件从此时开始追踪。例如我们在上述的工作区中创建一个文件test.txt,然后使用以下命令就可以追踪该文件的任意改动情况:

git add test.txt

当然该命令可以多次使用,以添加对多个文件的追踪。有时候,我们为了方便会使用以下命令添加所有文件的追踪:

git add .

当然这个add指令的第一个作用就是为未被追踪的文件添加追踪,第二个作用是对工作区某个文件的修改进行保存。因为git是根据你保存后的状态进行提交的,也就是说git的提交并不是提交的工作区的当前状态,他提交的是你每次保存后的所有文件状态,例如:我们创建了一个文件test,并使用add命令对其进行追踪了,下面我们为该文件输入一些内容(对文件进行了修改,随意输入一些即可)。然后我们提交一下当前状态:

你看,git告诉我们,文件test已经被修改,但是你并没有进行保存,所有此次no changes added to commit,没有东西可提交的。而当我们add保存该文件修改之后:

这次,git告诉我们本次提交已经成功添加到master分支上了,相比于上次commit状态有一个文件的修改。

2、git commit      在介绍commit提交之前,我们先简单了解一下git的大致结构。深入理解它的结构会在后续文章中学习,此处是为了更加方便的理解几个命令作用对象的不同。首先,git有三块区块,工作区,暂存区,分支。

工作区就是我们能看见的,所谓的“当前目录”。该目录下有很多的文件,这些文件就是我们版本控制所要追踪的内容。暂存区也称为stage或者index,它保存的是工作区的一次次修改情况,如上我们使用add命令保存某个文件的修改,记录下该文件当前快照。然后我们用commit命令向分支上提交,位于分支上的每个点都是一次commit留下的。当然我们在回滚的时候也是根据需要回滚到指定的点上。

有人会疑问,为什么要有暂存区呢,直接工作区对接分支不就好了吗?其实这样做具有更高的效率,一般来说,分支上的每次commit都代表着一次重要功能的完成,不能说我们每写一点代码就commit一下,这样会导致太多的commit,未来想要迅速找到想要回滚的点不易。所以git使用暂存区保存每一次小小的修改,等所有修改完成时候,commit命令将会把暂存的修改更新到分支上完成一次commit。

下面理解我们的commit命令就比较容易了,该命令会将暂存区的所有内容提交到分支上形成一次commit。一般我们只有在完成某一个完整的模块或者功能之后才进行一次commit提交,较小的修改则一般先在暂存区保存。

3、git clone      当我们遇到比较好的开源项目并想要参与其中的时候,我们就需要获取到别人项目的所有代码,这时候我们的clone命令就可以发挥作用了。我们在远程服务器上上创建一个库,新建一个文件index.txt,然后我们利用clone命令完成拷贝远程仓库的动作。

然后我们打开目录,f://1testgit下即可看到一个仓库test被完整的拷贝下来,test目录里面就是我们完整项目加上版本控制文件。这里需要说明一点,我们可以在命令后面指定拷贝下来的仓库名称,如果没有显式指定则默认和远程的一样。例如:

git clone https://github.com/Programer-yang/test.git myResptory

这样本地仓库的名称不再和远程的一样了,被显式修改成myResptory了。简而言之,想要使用clone命令,首先需要知道将要被clone的仓库的地址,可以是基于http协议的,也可以是基于git协议的,然后我们需要进入到指定目录,选择性的指定被克隆下来的仓库在本地的名称。

4、git status      该命令会和我们接下来要介绍的diff命令有点混淆,但是如果掌握他们的本质,区别也是显而易见的。首先我们要知道,status命令是用来查看当前工作区状态的,也就是说它会把当前工作区的所有文件状态和我们本地分支上最近一次的提交进行比较,并列出所有做出的修改条目。例如,我们在当前目录下创建一个文件test并键入简单内容,commit到master分支(此时工作区和暂存区以及本地分支都是干净的,一样的),而我们执行status命令也会得到以下输出:

它告诉我们工作区和分支上内容完全一样,并没有多余的修改。但是当我们修改index文件内容之后执行status命令,得到以下结果:

输出结果很显然的告诉我们,和本地分支的最近一次提交相比,工作区对index这个文件做了修改,并且还没有向暂存区保存。这是该命令额外的功能,如果是红色字体说明你不仅修改了工作区还没有向暂存区保存,如果是绿色的字体则说明你修改了工作区并向暂存区保存了。看:

以上我们简单介绍了status这个命令的基本使用,下面介绍diff命令。

5、git diff      diff命令也是用来查看当前状态的,只是它不同于status,它比较的是工作区和暂存区之间的区别。例如,我们对于干净的工作区,修改index文件,然后执行diff命令。输出如下:

从输出结果我们可以看出来,diff命令为我们列出了当前工作区和暂存区文件状态的详细区别。例如上图告诉我们,暂存区文件(红色字体代表暂存区文件的所有内容)index中只有一行信息 hello world,而当前工作区(绿色字体代表工作区文件内容)index中有两行信息。如果你是多个文件发生了更改,那么该命令会列出所有被修改文件前后所有内容供程序员查看。

当然我们以上介绍的diff命令是无参的,所以它比较的是工作区和暂存区之间的差异,我们也可以使用参数来指定工作区,暂存区,本地分支两两之间的比较。例如:

git diff --cached:比较的是暂存区和本地分支的差异

git difff HEAD:比较的是工作区和本地分支的差异

由此看来,对于git中三个不同区的状态之间差异的查看我们都可以通过diff命令来完成。显而易见,diff命令要比status命令输出内容更加详细,但是status命令也有其自己的使用场景。

6、git log      这是一个帮助我们查看历史提交信息的命令,例如:

我们可以看到,输出结果主要是历次commit对应的id以及提交者的信息时间,还有提交的描述信息。当然最重要的还是这个由40位十六进制数字组成的SHA-1值,这样每次提交都对应一个唯一的id,也方便我们回退历史版本。下面简单介绍一个该命令的一些选项参数,使用带参数或者选项的log命令可以为我们提供更加直观的信息,快速的获取到我们需要的内容。

直接使用git log命令将会输出历史所有的提交信息,有时我们只需要查看进几次的提交信息,就可以使用-<n>选项来显式指定输出的commit次数。例如:

我们也可以使用-pretty=xxx参数来指定输出的提交信息的简易程度,有以下一些参数值可供选择,oneline,short,full 和 fuller。例如:

其他参数的输出情况大家可以自行尝试实践。

还有一个选项是-p,我们往往对于某次提交都是会附带描述信息的,但是有时候这些描述信息不是很准确,而我们又想确定此次提交做出了那些修改,这时可以使用-p选项来输出此次提交的修改内容。例如:

输出结果告诉我们,该命令会列出当前提交对其中文件所有的更改情况。和我们的diff命令输出一样。

7、git reset      我们使用git最重要的一个目的就是,随时可以回退历史版本,而我们的reset命令就是完成这个工作的。例如:我们在git工作区创建一个文件index然后做一次提交(描述信息one),然后我们为index文件键入一些内容,再一次提交(描述信息two),这样我们构建了两次提交,最新一次的提交为two,我们可以利用reset回退到one。

我们看到,在回退之前最新的两次commit分别是two和one,但当我们回退到上一个版本的时候,原最新的commit被丢弃,head指针指向one。这里需要说明一点的是,head^符号表示的上一个commit的id,我们除了可以这么回退以外,还可以使用某个commit的唯一标识来回退,例如:

如图所示,我们成功的回退到描述为 ”the forth commit”的版本,很显然,我们是使用commit的唯一标识来回退的,所以针对任意的一个commit,我们都可以根据他的标识直接回退。但是这里需要注意的是,reset命令的执行将会直接导致工作区,暂存区,本地分支完全一致,也就是工作树是干净的,所以回退前要慎重检查是否有内容尚未保存,否则将会导致全部丢失。

至此,本篇文章简单介绍了git的几个常用的指令以及他们的简单应用,当然git有很多命令,我们只是列举了几个常用的,至于其他的一些命令部分会出现在后续文章中,我们还将介绍git很核心的内容:分支,这也是git能够多人协作的一个关键点。系列文章参考了一些书籍和网络教程,总结不到之处,望大家指出。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏三好码农的三亩自留地

快捷安装Flutter姿势,了解一下?

到 Flutter官网 直接下载SDK压缩包,找准你需要的平台下载并解压。为什么不用git 命令到 Flutter Github clone下来?因为你基本不可...

461
来自专栏程序员的碎碎念

云上部署Python3爬虫--以腾讯云+Ubuntu为例

以鄙人在GitHub上的辣鸡代码为例, 其他Scrapy的项目操作类似, 本文同样适用于不使用云服务器的情形(排除掉前期准备部分即可).

1094
来自专栏张戈的专栏

启用某些Linux发行版的root帐号

跟了我 5 年多的本本已步入花甲,CPU 严重老化,运行 Windows 异常吃力,于是考虑换成 Linux 试试。忙活了一天,测试了 2 个“家用”Linux...

3434
来自专栏Java技术分享

关于RBAC(Role-Base Access Control)的理解

基于角色的访问控制(Role-Base Access Control) 有两种正在实践中使用的RBAC访问控制方式:隐式(模糊)的方式和显示(明确)的方式。 今...

1805
来自专栏机器学习实践二三事

Mac无法升级six, numpy等

OS 10.10以上,会出现你无法直接使用pip升级向six, numpy等,报错就是各种权限不够,加上sudo结果也一样,原因就是MacOS的系统完整性保护(...

2278
来自专栏北京马哥教育

傻瓜式配置mutt

介绍 mutt是什么?用一句话介绍就是:它是linux终端有名的邮件客户端,它运行在终端,受到很多linux狂热分子和无限最求效率的人的热捧,我当然没有那么ge...

2774
来自专栏smy

readlink: command not found 解决方案

/c/Program Files (x86)/Yarn/bin/yarn: line 3: readlink: command not found 用gitba...

2854
来自专栏电光石火

gradle项目与maven项目相互转化

gradle 跳过测试直接编译 gradle build -x test  根据build.gradle和setting.gradle文件生成ide...

2364
来自专栏Java技术分享

关于RBAC(Role-Base Access Control)的理解

有两种正在实践中使用的RBAC访问控制方式:隐式(模糊)的方式和显示(明确)的方式。

1958
来自专栏Albert陈凯

2018-09-27 gradle项目与maven项目相互转化

gradle这几年发展迅猛,github越来越多的项目都开始采用gradle来构建了,但是并不是所有人都对gradle很熟悉,下面的方法可以把gradle转成m...

722

扫码关注云+社区