Git入门指导

写给zct小可爱的GitGithub入门学习材料。:laughing:

1. 一些场景

在学习Git或者Github之前,我们先来看一些生活中很常见的场景。如果你对这些场景有所体会,后面可以更好地理解我们为什么要学习使用GitGithub

毕业论文撰写

开题后第一周,你洋洋洒洒地写完了论文的初稿,然后高高兴兴地发给老师审阅。老师拿到论文一看,脱口而出就是一句:“这写的什么玩意”。“背景介绍这里,引用呢?这个句子,念都念不通顺。这个系统设计,写得比做作业还简单。还有这里的错别字……”老师毫不留情地给你指出了一堆错误,让你回去先修改。

场景一:历史版本丢失

回去之后,你就开始了慢长的修改历程。但是在这个修改过程中,你全部都是在同一个doc文件上进行修改的。有一天,你辛辛苦苦修改了一整天的文档,在半夜的时候突然睡着了:sleepy:。最糟糕的是,你之前的文档没有保存。你睡着的时候不小心趴在的键盘上,把前面写的文字变成了”sa1243UASI&DA*&Shasdf”这样的乱码,而且还保存了!早上你起来一看,简直想死的心都有了:tired_face:。全都要重新写了。

场景二:历史版本不明

这一次,你学聪明了。在每修改完一部分,你就将这份文档另存为一份。久而久之,你依次保存了以下这些文件

  • 毕业论文初稿(副本1).doc
  • 毕业论文初稿(副本2).doc
  • 毕业论文初稿(副本3).doc

然后你又兴高采烈地把改好的论文拿给老师看。老师一看,说:“嗯,改得还行,错误比之前少了很多。诶,你怎么把算法设计的地方给改了啊,那个地方你写得挺好的。你改了之后还没有以前的好呢。你这篇论文,其它部分暂时不用动,先把算法设计部分换回以前的部分”。

可是,头晕脑胀的你,根本不记得之前的算法设计是怎么写的了。突然,你灵光一现:“对啊,我不是有存副本吗!”。然而,回到家里的之后的你,看着电脑上那些“副本1”,“副本2”,“副本3”,根本不知道哪个副本做了什么修改,只好一个个打开这么文档去看,到底是在哪个文档中对“算法设计”这个部分做了修改。

场景三:历史版本差异不明

吃一堑,长一智。这一次,你又改变了你的文档保存策略。现在,你做完文档的修改之后,都会根据你对哪里做了修改来命名你的文档。然后,你依次保存了以下这些文件:

  • 毕业论文初稿(修改摘要版).doc
  • 毕业论文初稿(修改错别字版).doc
  • 毕业论文初稿(修改系统设计版).doc
  • 毕业论文初稿(恢复算法设计版).doc

修改完成后,你又一次去找指导老师评阅论文。老师看完你的论文之后对你说:“做得不错。但是系统设计这部分还是有些问题。这样吧,你之后改完之后在线上发给我看一下,如果还是有小问题的话,我直接让你改,你就不用每次都来我这里了”。于是,你又开始了你的论文修改工作。经过了多次与老师的交流,你又产生了以下的这些文件:

  • 毕业论文初稿(系统设计修改版1).doc
  • 毕业论文初稿(系统设计修改版2).doc
  • 毕业论文初稿(系统设计修改版3).doc

这段时间,你一直都在修改系统设计这些部分,通过文件名也可以很容易找到你在哪些文档对系统设计做了修改。但是,面对这么多的“系统设计修改版”的文档,你不知道到底哪个文档相比起上一次做了什么修改。于是,你又要一个个打开这些文档,去比较你到底做了什么修改……

场景四:多人协作不方便

慢慢地,你开始着手算法实现的工作。虽然你自己也会写代码,但是有些地方你不知道应该怎么实现,于是你去找了几个学霸来帮助你一起coding。你把你要实现的代码分成了几个模块:

  • main —> ct同学完成
  • module A —> 学霸A完成
  • module B —> 学霸B完成
  • module C —> 学霸C完成

因为学霸A、B、C 互不认识,所以他们的代码都是发给你来整理和调度。每次他们发来的代码,你都要自己去调整位置,因为他们都不知道你写的代码是怎样的。

有一天,学霸A对你说:“我这个模块需要调用module B里的一个函数,不提供的话我没法继续写“。这个函数刚好是学霸B在写,但是学霸A又不知道学霸B什么时候写好,于是他就天天问你,你再去询问学霸B,然后等到学霸B回复你之后再进行转告……

然后另一天,学霸C又对你说:“哎呀这个module A里写的funA函数怎么有Bug啊”。然后你又开始了与学霸A、C之间的相互转告工作……

于是你始终没有办法很好地继续你的工作,因为你总是因为要进行各种转告、合并工作,导致效率极低,多人工作甚至还不如你自己工作……

2. Git是什么?

Git是一款免费的、开源的、分布式的版本控制系统。(小声BB:“所以Git到底是个啥东西啊?什么是分布式啊?什么是版本控制啊?”)

3. 说人话

前面的介绍Git还是不够直观,那么我们来看看,Git是如何帮助我们处理前面提到的那些场景的。

版本控制

前面的场景一我们提到,由于没有历史的版本,导致我们无法回溯到以前的工作。而Git恰恰提供了版本控制的功能,能帮助我们回溯到文件的历史版本。假如我现在有一个名为my-big-project的项目要开始进行了,那么Git是如何帮助我们实现版本控制的呢?

后面的操作命令,如果你不懂也没有关系,你只需要大概知道我每一步干了什么就行了。具体操作可以以后再学习。

  1. 首先我们需要先初始化一个Git仓库(repository)。

    所谓仓库呢,就是我们就进行版本控制的地方。就好像你在写论文时,你会找的参考资料,正在写的稿子放到某个文件夹里。这里以my_big_project文件夹为例

    1
    git init
  2. 开始我们的工作,并在完成一定的工作后将文件进行提交

    假设我现在在my_big_project文件夹下创建了一个essay.md的文档,并编辑这个文档写入了如下内容:

    1
    2
    3
    4
    # My Big Project
    ## 摘要

    我完成了摘要的工作啦哈哈哈。我现在要先保存一下这些内容。

    现在我们把已经完成的工作保存一份历史记录。

    1
    2
    $ git add essay.md
    $ git commit -m "完成摘要编写"

    虽然你可能还不知道我干了什么,但是现在我确实已经完成了一次历史版本的提交。

    同样的操作,接下来我们继续编写我们的essay.md文档,添加背景介绍内容:

    1
    2
    3
    4
    5
    6
    7
    8
    # My Big Project
    ## 摘要

    我完成了摘要的工作啦哈哈哈。我现在要先保存一下这些内容。

    ## 背景介绍

    我完成了背景介绍的工作啦哈哈哈。我现在要再一次保存一下这些内容!

    和之前的操作一样,我们再保存一份历史记录

    1
    2
    $ git add essay.md
    $ git commit -m "完成背景介绍编写"

    现在我们可以使用Git的一些GUI图形界面程序来看一下,我们到底完成了什么工作

    image

    在上图我们可以明显看出,Git帮助我们保存两份essay.md的副本。这样子我们就解决了历史版本丢失的问题

  3. Git commit message帮助我们解决历史版本不明的问题

    也许你注意到了我前面使用commit命令提交时,加上了一个-m参数。这个参数就是给本次提交添加一个描述,例如”完成摘要编写“,”完成背景介绍编写等等“。这样子,我们通过commit message,就能很容易区分不同的历史版本了。

  4. Git可以帮助我们比较历史版本间的差异

    image

    假设我们在之前的基础上,又依次完成了系统设计、算法设计、改善算法设计几个步骤。我们过了很长一段时间没有写这篇文档了,已经忘记了之前做了什么工作。那么Git可以帮助我们比较不同历史版本间文件的差异。

    例如我们这里想要看一下,改善算法设计到底在完成算法设计的基础上做了什么工作。

    image

    通过这里我们很方便地看出,原来我们在essay.md的文档的第16行,添加了2+3=5

多人协作

正如下图所示,我们可以找多个人来帮我们协同完成一个项目,每个人分别负责不同的板块。

image

Git里面,我们可以用不同的branch分支来划分不同的工作,例如:

  • 学霸A在学霸Abranch里开发module A
  • 学霸B在学霸Bbranch里开发module B
  • 学霸C在学霸Cbranch里开发module C

当他们的工作完成之后,ct同学就可以将他们的工作merge到自己的master分支上,这样就可以把大家的工作协同起来了。当然,在合并大家的工作时,有时候可能会产生“冲突”(conflict),这时候需要手动去解决一下冲突。

那么,怎么体现Git的分布式特性呢?所谓分布式,通俗点来理解就是把一份东西分到了多个不同地方去。当我们在协同工作时,我们可以通过git clone命令来克隆别人仓库。用上面的例子来说的话,就是学霸A、B、C他们每个人都可以有一份你的仓库的副本,其中这个仓库副本里包括所有人的历史版本信息。

也就是说,只要学霸A定时将它的仓库与你的仓库保持更新,他就能获取到你、学霸B、学霸C所完成的工作,而不必像以前一样必须通过你才能知道别人完成到了什么程度,是不是非常方便呢?:sunglasses:

并且,学霸A、B、C都可以在他们克隆下来的仓库下面随便操作,因为他们操作的都是他们本地的副本仓库,根本不会影响到远程仓库或者别人克隆的仓库。这样子就避免了大家在同一个开发环境下一起工作,导致出现混乱的场面。例如,由于学霸A不小心把学霸B的文件给删除了,导致学霸B无法工作这样的场景是绝对不可能出现的!因为他们在各自不同的本地仓库local repository上操作。

4. 总结一下

至此,我们已经通过列举一些十分常用的场景里会遇到的坑,以及Git是如何帮助我们解决这问题的,来认识到Git的一些重要特性——版本控制、协同工作。当然,Git的功能十分强大,远远不止我上面提到的这些。虽然理解和学习Git的过程可能会有一点困难,但我个人而言还是十分推崇学习Git的。

前面提到的例子,是我以比较通俗的语言去介绍Git的一些使用场景。如果Git刚好有满足到你的痛点,那么赶紧来学习吧~

至于Github到底是什么❓有什么用❓怎么用❓我会在下一篇文章里告诉你。所谓Github,可以看成是Git+Hub啦。所以先理解了Git的思想,你才会更会地学习后面的内容。

5. 推荐学习资料