【git】【一站式学习git】跟进案例,从浅到深

- GIT与SVN的区别

  GIT是分布式版本控制系统,它和svn的区别在于它并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。 要浏览项目的历史,Git 不需外连到服务器去获取历史,然后再显示出来——它只需直接从本地数据库中读取。 你能立即看到项目历史。 如果你想查看当前版本与一个月前的版本之间引入的修改,Git 会查找到一个月前的文件做一次本地的差异计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再来本地处理。   这也意味着你离线或者没有 VPN 时,几乎可以进行任何操作。
  举个例子:如你在飞机或火车上想做些工作,你能愉快地提交,直到有网络连接时再上传。 又比如你回家后 VPN 客户端不正常,你仍能工作。 使用其它系统,做到如此是不可能或很费力的。 比如,用 Subversion 和 CVS,你能修改文件,但不能向数据库提交修改。 这看起来不是大问题,但是你可能会惊喜地发现它带来的巨大的不同。

-结合案例分析: GIT目录下文件的状态流转

现在在你的GIT目录工程中,输入以下命令

git status

看看我的输出内容:

enter image description here

从上图中可以看到有三个红色的选中框,我们自下而上一一介绍。


(1)Untracked files:(未跟踪的文件:也就是说,处于这个状态的文件,无论你修改与否,都不会被git识别处理)
(2)changes not staged commit:
处理这个状态的文件,已经被git识别跟踪,但是本次修改未提交到暂存区。
(3)changes to be committed:(处于该状态的文件,已经在暂存区中,等待被commit)


那么以上三种状态是如何流转的呢?


我们以黑色图中未被跟踪的(Untracked files 下).idea 文件为例子:

(1)未被跟踪的文件.idea 通过add命令,进入被跟踪状态

git add .idea    

(2)我们对.idea 文件随便做一些修改,然后你会发现,它已经处于“changes not staged commit”状态。

(3)处于“changes not staged commit”状态的文件,通过add命令进入暂存区

 git add .idea    

(4)将暂存区的文件提交,.idea 文件状态恢复到“未改变的状态”,等待下一次的更改,如果再次更改,文件状态如以上(2)中的说明。

git commit -m “描述”
说到这里,要逐重说一下add 命令的作用:
(1)可以用它开始跟踪新文件
(2)把已跟踪的文件放到暂存区
(3)还能用于合并时把有冲突的文件标记为已解决状态

- 结合案例分析:Git 的基础原理

  我们现在通过add命令告诉Git系统,我要跟踪三个文件,A,B,C,那么git系统会为我们做些什么呢? 哈哈,git 会给这些文件照一个“照片”,留个小小的纪念,就这样,我们有了一张“照片”,这张照片是这个样子的。

在这里插入图片描述

  此时,我想修改以下文件A和文件C,修改完成之后,由于该文件被git跟踪,此时A 和 C文件处于“changes not staged commit”,也就是以上黑色图中第二个红色选中框的位置。那此时git为我们做了什么呢?你猜的没错,它又给文件再次“照相”。但是此时,它不是所有的文件都照了照片。它只给A 和 C 2个修改之后的文件做了快照。此时,他的结构是这样的:

在这里插入图片描述

  想必大家根据以上案例,已经了解了git的原理,git存储的是文件的快照,它只关系文件是否变化,但是不关心文件到底变化了啥。只要文件变化,它会为该文件生成新的快照,而不是存储变化了的细节。

- 结合案例分析:Commit,我们提交了什么

  上面说到,git 帮我们存储的是一个一个的文件快照,那文件快照,这张照片到底长什么样子呢?我们一起来看一下:

在这里插入图片描述

  如果我们一次提交A,B,C三个文件的文件快照,那么commit都包含什么呢?它会包含:author ,commiter,和tree(一个指向暂存区的指针)。这个指针包含了暂存区文件的快照地址。我们看一下它的结构:

在这里插入图片描述

我们看一下完成的commit的内容吧:

在这里插入图片描述

  作些修改后再次提交,那么这次的提交对象会包含一个指向上次提交对象的指针( parent 对象)。

在这里插入图片描述

# - 什么是分支   现在来谈分支。Git 中的分支,其实本质上仅仅是个指向 commit 对象的可变指针。如下图:

在这里插入图片描述

分支其实就是从某个提交对象往回看的历史

- 分支的新建

  Git 又是如何创建一个新的分支的呢?答案很简单,创建一个新的分支指针。比如新建一个 testing 分支,可以使用 git branch 命令:

git branch testing

  我们基于第三次提交,创建一个testing分支,上面说到,分支本质上是一个指向提交记录的指针,那么也就是说,我们创建了一个指向第三次提交的testing指针,我们来看一下效果图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20181210223424678.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3p6MjAxMDQ1MzQ=,size_16,color_FFFFFF,t_70)
# -解读 HEAD指针   我们现在有了2个分支,那怎么决定我们在哪个分支上开发呢?这就要说到HEAD指针了,HEAD指针标示了我们正在工作的分支。比如说我现在在新建的testing分支上开发,那么HEAD 指针就会指向我的testing分支,HEAD 可以理解成分支的别名,让我们一起看下效果图。

在这里插入图片描述

-结合案例分析:merge的Fast forward

  我们现在有2个分支,master 和 testing,现在我们在testing分支上,进行第四次提交。那么我们提交的样子就会编程以下这个样子:

在这里插入图片描述

  假设,我们现在要将testing分支合并到master 上,那要怎么做呢?   我们当前在testing分支上,我们要做的是:回到 master 分支并把hotfix合并到master
$ git checkout master
$ git merge testing
Updating f42c576..3a0874c
Fast-forward
 README | 1 -
 1 file changed, 1 deletion(-)
  请注意,合并时出现了“Fast forward”的提示。由于当前 master 分支所在的提交对象是要并入的 hotfix 分支的直接上游,Git 只需把 master 分支指针直接右移。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)。

-结合案例分析:更为复杂的merge

  经过以上的合并,我们会得到这样的结果图,master指针指向了第四次提交。

在这里插入图片描述

假设,我们有三个分支:master ,testing 和 branch3,他们的结构是这个样子的。

在这里插入图片描述

第一步,我们切换到testing分支,并做第四次提交,那么结构就会变成:

在这里插入图片描述

第二步:我们将master 和 testing 合并,我们的结构会变成以下的样子:

在这里插入图片描述

第三步,我们切换到branch3分支,做第五次提交,那么我们的结构就会变成:

在这里插入图片描述

第四步:接下来,我们让master 合并branch3

    $ git checkout master
    $ git merge iss53

那么会发生什么呢?

这次合并操作的底层实现,并不同于之前 testing的并入方式。因为这次你的开发历史是从更早的地方开始分叉的。由于当前 master 分支所指向的提交对象(第四次提交)并不是 branch3 分支的直接祖先,Git 不得不进行一些额外处理。就此例而言,Git 会用两个分支的末端以及它们的共同祖先(第三次提交)进行一次简单的三方合并计算。这次,Git 没有简单地把分支指针右移,而是对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象(第六次提交),这个提交对象比较特殊,它有两个祖先(第四次提交和 第五次提交)。

在这里插入图片描述

# -分支的合并:变基 rebase   把一个分支中的修改整合到另一个分支的办法有两种:merge 和 rebase。   我们回到上一章节:如图:

在这里插入图片描述

  我们将branch3 合并到 master,除了用merge还可以用rebase,及(将branch3里面的变化补丁在master),那要怎么做呢?
第一步:切换分支到branch3,生成补丁,把 branch3 里产生的改变到 C4 上重演一遍。
$ git checkout branch3
$ git rebase master
  它的原理是回到两个分支最近的共同祖先(第三次提交),根据当前分支(branch3)后续的历次提交对象,生成一系列文件补丁,然后以基底分支( master)最后一个提交对象(第四次提交)为新的出发点,逐个应用之前准备好的补丁文件,最后会生成一个新的合并提交对象,从而改写 branch3 的提交历史,使它成为 master 分支的直接下游,如图

在这里插入图片描述

第二步:回到 master 分支,进行一次快进合并.(快进合并:Fast-forward),该内容在上一节分支合并之merge中,有详细的讲解。
git checkout master
git merge branch3

在这里插入图片描述

  merge 和 rebase 虽然最后整合得到的结果没有任何区别,但变基能产生一个更为整洁的提交历史。如果视察一个变基过的分支的历史记录,看起来会更清楚:仿佛所有修改都是在一根线上先后进行的,尽管实际上它们原本是同时并行发生的。   一般我们使用变基的目的,是想要得到一个能在远程分支上干净应用的补丁 — 比如某些项目你不是维护者,但想帮点忙的话,最好用变基:先在自己的一个分支里进行开发,当准备向主项目提交补丁的时候,根据最新的 origin/master 进行一次变基操作然后再提交,这样维护者就不需要做任何整合工作(实际上是把解决分支补丁同最新主干代码之间冲突的责任,化转为由提交补丁的人来解决。),只需根据你提供的仓库地址作一次快进合并,或者直接采纳你提交的补丁。   请注意,合并结果中最后一次提交所指向的快照,无论是通过变基,还是三方合并,都会得到相同的快照内容,只不过提交历史不同罢了。变基是按照每行的修改次序重演一遍修改,而合并是把最终结果合在一起。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值