大多数人,都低估了编程学习的难度,而高估了自己的学习能力和毅力。
当前系列: 软件工程 修改讲义


版本控制工具

最基本的功能就是:记录代码的每一次改动,或者说,保存代码的改动历史。

@想一想@:这有什么用呢?

  • 有案可查:是谁、在什么时候、干了些啥事?一目了然。(飞哥的黑历史 / 同学们的作业检查)
  • 备份恢复:既然记录了所有改动,当然就应该可以根据改动进行恢复,是不是?所以,git相当于一个升级版的ctrl+z!永久有效且可以回退到任意一个(提交记录的)时间点。

git就是一个目前非常流行的、开源的、分布式的版本控制工具

PS:git最早用于Linux的开发,本身是命令行操作的,但微软将其嵌入到VS之中,大部分功能都可以由图形界面方便的完成(一些高级功能还是需要命令行)。

除git以外,还有SVN、TFS等源代码版本控制工具。


先讲原理

关键点:

  • 提交commit的是改动change
  • 仓库repository里记录所有改动:哪怕是删除,也会记录删除了那些内容,是增加而不是减少改动记录history
  • 首先是提交到本地local仓库
  • 需要的话,才在本地仓库(不是工作区)和远程remote仓库之间进行推送push和拉取pull
@想一想@:离职删库跑路有没有用?为什么?

区别svn

svn的仓库没有:本地 vs 远程之分,工作区内容直接提交到(远程)仓库。所以:

  • svn一般要联网才能提交;git不用
  • svn只有一个中央仓库,一旦中央仓库损坏,凉凉;git可以将任意一个本地仓库再指定为中央仓库


Github

全球最大同性交友网站欢迎你!

PS:作为最大的开源社区已经被微软收购。微软说:这是他们拥抱开源的重要一步,^_^!开源世界说:我们的基地被攻陷了……o(╥﹏╥)o

区分 github 和 git :

  • github,是一个网站
  • git,是一个工具

但github这个网站的核心功能就是:提供一个公共的、易用的git repository服务器。

使用github,同学们需要(演示:略)

  1. 在github上注册一个账号
  2. 在github上新建一个裸(bare)仓库代码:一点内容没有,全新的仓库,得到一个仓库地址
  3. 利用该仓库地址,将本地仓库中的内容推送到github
PS:但因为众所周知的愿意,github在国内访问,不太稳定。所以建议大家在接下来的学习中使用和github几乎一模一样的gitee

改动change

一旦建立本地仓库,git默认就会追踪(track)仓库所在文件夹下所有文件的改动(change)。

改动又细分成三种:

  • add:新添加一个文件
  • edit:在现有文件上编辑
  • deleted:文件被删除

我们可以通过对比(compare)查看这些改动内容。

staged

git在commit前,还设置了一个步骤:staged。

理论上,change最开始是unstaged,所以首先要被staged又被称之为加入index,可以理解为放置在“缓存区”,最后才能commit。

stage可以将改动“部分/分批次”提交。但是,这样操作首先有风险,然后又没什么用的:建议同学们总是把所有改动一次性staged and commit。

撤销

change在commit之前还可以撤销(undo或discard)

.gitignore

有些文件(比如bin文件夹下),我们不想将其加入repository,就可以在repository文件夹下面,添加一个.gitignore文件,里面记录被需要被ignore的文件/文件夹

.gitignore可以由IDE自动生成,也可以从第三方获得,开发人员还可以手动更改。

但是,.gitignore能把已经track并存放在repository中的文件移出,需要我们手动的将其删除后再commit。

commit

必须在填写commit message之后,才能将改动提交到本地repository。

注意

  • message是这一次提交内容的描述,一定要认真填写养成习惯
  • 如果你不能很清晰的写出message,多半是因为你没有很好的组织每一次提交。
  • 每一次提交的内容越少,越容易描述。

此外,飞哥再三强调

  • 在commit之前,查看change内容,养成习惯

一旦提交,就会被记录到历史(History)中。

@想一想@:文件被删除,然后被提交,repository如何处理?

历史History

记录了每一次提交的

  • Id:只显示前8位
  • 提交人:是由自己设置的
  • 提交时间:
  • Message:非常重要

HEAD

在所有的历史记录中,git用一个HEAD指针,指向当前版本。

所以撤销(discard)未提交更改,实际上就是:Replace with HEAD Revision(用HEAD版本替换工作区内容)

HEAD非常有用,通过调整HEAD的指向位置(配合其他组件/机制),git可以完成令人耳晕目眩的各种花式操作。

Reset

历史记录不仅可以被查看,还可以被“回退”。

Reset:首先移动HEAD指针到指定版本,然后,根据相应区域(work/index/repository)是否变动,分为:

  • soft:只回退HEAD(PS:Visual Studio暂未支持),不做其他任何操作
  • mixed:在soft的基础上,还回退index中的记录,但保留工作区内容
    以上两种模式都会形成change,但soft是staged的,mixed是unstaged。
  • hard:在mixed的基础上,还回退工作区更改。这种操作要慎重
@想一想@:为什么要搞这么多模式呢?只要hard不香么?

RefLog

为了以防万一,git还“偷偷的”把所有(只要HEAD发生变化, 就会被记录)的本地更改都放在RefLog里面。

所以即使被hard reset的记录在reflog里也可以查找到。

PS:Visual Studio暂未支持

Revert

这是一种非常安全的方式。它实际上是新建的一次提交:参照你想回退到的那个版本(历史记录),对当前内容进行更改,然后提交。

如果你对git的操作不太熟练,我建议你总是使用这种方式进行回退。


远程同步

注意之前所有操作,都是在本地(你自己的电脑上)进行的。要想和别人分享你的代码,你需要有一个远程仓库(一般放在github/gitee上):

publish

飞哥把:

  1. 在github上新建一个裸(bare)仓库
  2. 将本地仓库内容推送(push)到github裸仓库

的过程称之为publish。

其本质还是一个push的过程。

有些IDE(比如Visual Studio)会将publish过程合二为一,一次性执行。

clone

把github上面的仓库,复制/拷贝/弄到本地的过程,就是clone。

注意这个单词:clone

要想在两个仓库之间同步,仓库和仓库之间必须“基因”相同。

一定要理解:两个仓库(DNA)一样 ≠ 两个仓库里面的内容一样。

怎么才能相同呢?以下情形任选其一:

  1. A仓库是从B仓库clone的
  2. A仓库向一个从未被使用过的(bare,不是empty)B仓库推送
只有DNA相同的两个仓库之间才能进行同步操作。

同步(sync)

同步会首先比较远程repository和本地repository的差异。然后,

拉取(Fetch和Pull)

如果远程repository上有比本地repository上更“新”的更改,

@想一想@:这是怎么造成的?

本地就可以:

  • Fetch:获取更改到本地repository,但不更新本地工作区(飞哥也不知道这样有啥用,^_^,谨慎?先看看?)
  • Pull:获取更改到本地repository,同时更新(merge)本地工作区(pull=fetch+merge)

推送(Push)

如果本地repository上有比远程repository上更“新”的更改,

本地就可以通过push,将本地的更改直接推送到远程repository

先拉取再推送

我们来看更复杂一点的情形:

  1. 你clone/pull了远程仓库
  2. 你在本地commit,更新了本地仓库
  3. 在你做2的同时,张三往push了一些内容到远程仓库
  4. 当你想push本地仓库内容时,git会自动检查到张三的push,要求你先拉取再pull

冲突conflict

拉取的过程中就可以产生冲突。比如同一个文件的同一行代码

  • 你写的是:飞哥真帅
  • 张三写的是:飞哥真衰

这时候git没法自动处理(是两个都要呢?还是一个覆盖另外一个?两个都要,谁在前谁在后呢?),就报一个冲突(conflict),让开发人员自行解决(resolve)。

开发人员需要更改工作区内容,然后再commit+pull,确定最终版本。


作业

使用你选用的git插件,完成:

  1. 新建一个git本地repository并已包含文件Article和Problem(.cs/.java/.html)
    1. 在本地repository中新增一次提交,包含以下操作:
      1. 添加文件Suggest
      2. 删除文件Article
      3. 在Problem中添加一行内容:作业3.3
    2. 查看git的history,确保完成上述作业(以下不再赘述)
    3. 再增加一次提交,包含以下操作:Problem被更名为Problme-1
    4. revert作业3,即再将Problem-1改回Problem
    5. 使用reset删除3和4的操作
  2. 将本地repository发布到github/gitee
  3. 在另一个地方clone之前repository
  4. 利用本地的两个repository交替提交并推送到远程,观看其history

学习笔记
源栈学历
键盘敲烂,月薪过万作业不做,等于没学

作业

觉得很 ,不要忘记分享哟!

任何问题,都可以直接加 QQ群:273534701

在当前系列 软件工程 中继续学习:

多快好省!前端后端,线上线下,名师精讲

  • 先学习,后付费;
  • 不满意,不要钱。
  • 编程培训班,我就选源栈

更多了解 加:

QQ群:273534701

答疑解惑,远程debug……

B站 源栈-小九 的直播间

写代码要保持微笑 (๑•̀ㅂ•́)و✧

公众号:源栈一起帮

二维码