Git新手教程-标签、分支和合并(六)

前言

在以前的文章中,咱们已经对仓库和提交已经有必定的了解了,在该篇文章中,咱们将学习git taggit branchgit checkoutgit merge。下面简单的介绍一下几个命令的功能:html

  • 使用 git tag 你能够为特定提交添加标签。标签是提交的额外标记,能够指示有用的信息。
  • 使用 git branch 你能够建立分支。用于并行开发项目的不一样功能。而不会对哪些提交属于那个功能而感到困惑。
  • 使用 git checkout 你能够在不一样的分支和标签之间进行切换。
  • 使用 git merge 能够将不一样分支上的更改自动合并在一块儿

标签

咱们先从最简单的标签开始。git

假设咱们已经向仓库提交了 A、B、C、D 四个commit,其中最后的一个提交也就是D,标志着咱们项目的1.0版本。如何在Git中指出这一点呢?你们可能会以为,咱们能够在D的提交中说明这是咱们的版本1.0。可是这并非最理想的。Git像其余版本控制系统同样,提供了给提交打Tag(标签)的功能。也就是说咱们能够给D提交打上标签。以下所示:bash

Tag(标签)通常表示比较重要的节点信息。编辑器

Tag展现.jpg

即便更多的提交被添加到仓库中(在下图中,咱们假设在D提交以后又陆续的提交了E、F、G三个提交),Tag(标签)仍然锁定着某个提交,以下所示:ide

Tag展现2.jpg

既然标签有着如此重要的做用,那如今咱们来看看在Git中如何建立标签吧。在Git中标签有两种类型:轻量标签附注标签工具

  • 轻量标签在Git中,是不存储任何的信息,只是一个特定提交的引用。
  • 附注标签存储在Git数据中,且附注标签中包含了打标签者的名称、电子邮件,日期等信息,通常状况咱们都会使用附注标签。

建立轻量标签

建立轻量标签的方式很是简单使用git tag+标签名称。以下所示:学习

git tag v1.0.0
复制代码

建立附注标签

建立附注标签很是简单,须要在建立轻量标签的方式上,添加选项-a。以下所示:ui

git tag -a v1.0.0
复制代码

经过上述方式,Git会运行你配置的文本编辑器输入标签信息。以下所示:idea

git_tag_3.png

上图中,我配置的是Sublime Text,固然你也可使用git config --global core.editor命令配置你喜欢的编辑器。spa

除了使用上述方式建立附注标签之外,咱们还可使用 -m 选项来指定存储在标签中的信息,若是你添加了 -m 选项,那么Git就会绕过你配置的编辑器。以下所示:

git tag -a v1.0.0 -m "发布新版本v1.0.0"
复制代码

轻量标签与附注标签的区别

在讲解了轻量标签与附注标签的使用以后,咱们来看一下这两个标签的实际区别,咱们能够经过git show命令查看实际的区别,咱们先查看附注标签,以下所示:

git_show_1.png

经过使用git show v1.0.0,你能够看到命令行的输出中是包含Tag信息的:

tag v1.0.0
Tagger: AndyJennifer <1225868370@qq.com>
Date:   Sun Sep 15 18:20:28 2019 +0800

发布新版本v1.0.0
复制代码

而建立的轻量标签中,是不包含该信息的,以下所示:

git_show_2.png

须要注意的是,建立的标签老是与commit进行绑定的。好比在上图中,标签是指向 441796... 这个提交的。

标签的删除

要删除掉本地的标签,咱们可使用命令 git tag -d <tagname> 。例如使用下面的命令删除标签:

git tag -d v1.0.0
Deleted tag 'v1.0.0' (was 3132ff5)
复制代码

其中 -d 选项表示delete(删除)

向之前的提交的 commit 添加标签

经过运行 git tag -a v1.0.0 ,咱们能够给最近的commit添加标签,可是若是你想向仓库中好久以前的commit添加标签呢?很简单!咱们能够在原来的命令基础上,直接添加对应的commit的 SHA 便可。

使用 git log 命令查看历史提交记录。这里咱们能够提供完整的SHA,或SHA前七个 字符,

git tag -a v1.0.0 abd12d0
复制代码

在上述命令中,咱们为 abd12d0 这个提交打上了标签。

分支

在Git中,分支就像是科幻电影中的平行世界。每一个平行世界都运行在独立的环境中,在正常状况下,每一个平行世界中所做的事,对于现实世界或另外一个平行世界是无感知的且不影响的。在某些特殊的状况下,平行世界与现实世界可能重合,那么就会产生混乱与冲突。那这个时候就须要咱们来解决这些冲突与问题。

平行世界.jpg

扯太远了,分支在Git中,主要用于项目的开发或者对项目进行修正。由于全部的修改都是在分支中进行,因此并不会影响到项目(项目通常在主分支上,通常是 master 分支)。当咱们在分支中进行更改后,咱们能够将分支中的内容合并到分支上,这种分支组合过程,称为合并(merge)。后续咱们会一一讲解这些内容。

那么接下来,咱们来看看Git中分支的使用方式和重要的概念。

master 分支与 HEAD 指针

在下图仓库中,咱们建立了一些提交,并在提交D中建立了名为 v1.0 的标签,除了标签之外还包含一个隐藏的 master 分支。在咱们没有建立分支的状况下,Git会为咱们建立一个名为 master 的分支。其实 master 的本质实际上是一个 指针

分支1.png

master 并无什么特殊的意义,它只是第一个默认分支名。

随着咱们不断向仓库进行提交,这些提交都会添加到该分支上。同时 master指针 也会指向对应提交。以下所示:

分支2.png

在上图中,masetr 指针随着提交而不断移动。图中红线所链接的提交都属于 master 分支。

相对于 Tag(标签) ,分支指针不会永久的指向某次提交,而是会随着提交不断的移动。

HEAD指针

在某些状况下,咱们可能会建立另外一个分支。在下图中,咱们又建立了另外一分支 branch1

分支3.png

这个时候若是咱们再进行一个提交,哪一个分支会移动呢?是 master 仍是 branch1 分支呢?这里就涉及到另外一个知识点----> HEAD 指针。

在Git中,HEAD 老是指向当前活跃的分支。在你没有切换分支的状况下,默认指向 master 分支。以下图所示。

分支4.jpg

由于当前 HEAD指针 指向 master 分支,因此当咱们再向仓库提交一个I提交对象时,该提交仍然会在 master 分支上。以下所示:

分支5.jpg

固然咱们能够改变 HEAD 指针所指向的内容, 使用 git checkout 命令,咱们能够切换 HEAD 指针所指向的分支。好比咱们能够经过命令git checkout branch1,将 HEAD 指针指向 branch1

当咱们切换分支到 branch1 后,咱们后续的提交,都会添加到 branch1 分支上。好比下图,咱们又建立了一个 A提交 ,那么这时 branch1 分支指针会指向该提交。

分支6.jpg

分支中的提交的可见性

须要注意的是,分支中的提交对于其余分支来讲是不可见的。

分支7.jpg

在上图中,若是咱们当前切换到了 master 分支,那么在咱们的工做目录与文件系统中, branch1 分支的 Abranch2 分支中的 J ,这两个提交对文件形成的更改,将不会出如今 master 分支上的任何文件中。若是须要查看这个两个对应的文件修改,只须要切换到咱们想要查找的提交所在的分支就好了。

咱们基本已经熟悉了分支的相关概念与总体流程后,下面咱们来学习一下 相关命令的使用。

建立分支

建立分支其实很简单,只需使用 git branch + 分支名称 。若是你想建立一个叫作 "branch1" 的分支,只需运行如下命令:

git branch branch1
复制代码

须要注意的是,若是你在某个提交上建立了一个分支,那么该提交以前的全部提交也是属于当前分支,在下图中,在 H 提交中使用了建立分支命令建立了 branch1 分支,那么在 H 提交以前的 D、E、F、G 也都属于 branch1 分支。

分支3.png

上图中 branch1 分支如蓝线所示。

之前的提交的 commit 添加分支

固然,与建立标签同样,咱们也能够向之前的提交的 commit 添加分支。在下述命令中,咱们在 SHAdfs14fo 的提交中建立了test分支。

git branch test dfs14fo
复制代码

切换分支

要切换到另外一个分支,咱们须要使用命令 git checkout 命令,好比咱们须要切换到分支dev上,那么咱们可使用以下命令:

git checkout dev
复制代码

经过上述操做,HEAD 指针会指向 dev ,须要注意的是,当你切换分支时,在你的工做目录中,会删除其余分支中 commit 引用的全部文件,同时会引用 dev 分支中的 commit 引用的文件。固然你不用担忧真的删除了你另外一分支上的文件。Git会将它们都存储在仓库中。当你切换回来后,又会将对应分支引用的文件显示在你的工做目录中。

分支的查看

若是你须要查看当前项目的分支,可使用 git branch 命令,经过该命令咱们不只能够知道仓库中所建立的分支,还能查看当前活跃的分支,也就是 HEAD 指针指向的分支。

在下图中,星号(*) 标记的为当前活跃的分支。

git_branch.png

查看全部分支

经过使用 git branch命令,咱们只能查看当前活跃的分支,若是说咱们的项目有不一样的分支,咱们又想查看全部分支提交内容,那么咱们又该怎么办了呢?还记得咱们以前提到过的 git log指令吗,这里咱们将添加 --graph--all选项。

  • --graph 选项:将条目和行添加到输出的最左侧。
  • --all 选项:将显示仓库中的全部的分支信息。

那么咱们可使用以下命令:

git log --oneline --graph --all
复制代码

--oneline 能够省略掉 commit 中的日期、做者等信息。以最简单的形式显示commit信息。

经过此命令,咱们能查看仓库中的全部的分支和 commit 信息:

显示全部分支信息.png

分支删除

在上文中,咱们提到,分支通常用于进行开发或对项目进行修正。当咱们将分支的更改 合并(merge)master 分支后,咱们可能就再也不须要该分支了。那么这个时候若是咱们想删除分支,那么咱们使用命令 git branch -d + 分支名称来删除咱们想要删除的分支。这里咱们以删除dev分支为例:

git branch -d dev
复制代码

在删除分支的时候,咱们须要注意如下两点:

  • 若是咱们已经使用 git checkout dev 命令切换到dev 分支上的话,那么咱们是不能删除 dev 分支的。咱们须要切换到其余分支上,才能删除该分支。
  • 若是 dev 分支上有任何的commit,那么经过 -d 选项是不能删除该分支的,你须要使用大写的 D 选项,也就是使用 git branch -D dev

合并

分支的主要做用就是让咱们作出不影响 master 分支的更改,当咱们在非 master 分支上作出更改后,若是以为不须要该分支上的更改,则能够删掉该分支,或者你能够将给分支上的内容与其余分支进行合并。

将分支组合到一块儿的这种行为,咱们称之为合并(merge)

在Git中使用 git merge 命令来合并分支:

git merge <other-branch>
复制代码

在Git中 合并(merge) 的方式有两种类型。一种是普通合并,另外一种是快进合并。下面咱们就来分别了解这两种合并方式。

普通合并

假设咱们的项目存在这两条分支 masterbranch1 两条分支。

普通合并1.jpg

这个时候咱们想将 branch1 合并到 master 分支上,因为当前HEAD指向 master 分支,因此当两个分支合并时,将会生成一个合并提交 B 将放置在 master 分支上,而且 master指针 将会向前移动。以下所示:

普通合并2.jpg

须要注意的是, B提交 会连接branch1中的 4A 提交。同时当分支进行合并时,并不会影响到以前的分支,好比咱们仍然能够切换到branch1分支上,并建立一个新的提交 J ,以下图所示:

普通合并3.jpg

快进合并

假设咱们的项目存在这两条分支masterbranch1支。且branch1分支在master分支前面。以下所示:

快速合并1.jpg

由于master中是不包含 branch1 中的提交(I,K,2)。若是这个时候咱们想将这些提交归入master分支中,也就是须要将 branch1 分支 合并(merge)master 分支中。当咱们在master分支中使用命令 git merge branch1 时,由于 branch1分支master分支 前,Git会作一个所谓的快进合并。以下图所示:

快速合并2.jpg

在上图中,master分支移动到了branch1分支指向的commit。须要注意的是,快进合并并不像普通合并那样再建立一个提交。

合并冲突

大部分状况下,咱们都能成功的合并分支,可是某些状况下,Git没法自动的进行合并,当合并失败时,就称为合并冲突。当出现冲突时,咱们须要手动的去修复文件中的冲突。看下面的例子:

在例子中,咱们已经建立了一个名为GitTestProject的仓库,在仓库中咱们已经添加了一个名为Jvm系列之总目.md文件到仓库中,以下所示:

合并演示1.gif

其中 Jvm系列之总目.md 文件中的内容以下

合并演示2.png

这个时候咱们经过 git branch dev 命令建立了 dev 分支,并切换到该分支中,这个时候咱们原文中添加了下图中红框中的内容。

注意的是,你须要常用git branch来查看活跃分支

合并演示3.png

在修改该文件并保存后,咱们能够经过git status查看当前仓库的状态,而后咱们将在dev分支修改的内容进行commit。内容以下所示:

合并演示4.png

咱们在原来的文件中,添加了一句Java class文件格式。接下来,咱们经过git checkout master切换到 master 分支,而后继续修改该文件,一样的修改的内容如红框所示:

合并演示5.png

一样的,在咱们完成修改后,咱们将在master分支修改的内容进行commit。内容以下所示:

合并演示6.png

当提交完毕后,若是咱们想将dev分支合并到 master分支中,使用 git merge dev命令,咱们能够看到以下报错:

当使用 git merge 命令时,你必定要注意当前所在的分支,你能够经过 git branch 或者 git status 来查看。

合并演示7.png

在上图中,Git告诉咱们文件 Jvm系列之总目录.md 出现了冲突。这个时候咱们再打开该文件,咱们可能看到以下内容:

冲突文件显示.png

在该文件中显示了一些特殊的一些符号,其实这些符号是Git定义的合并冲突指示符,下面对这些指示符进行介绍:

  • <<<<<<< HEAD 此行下方的全部内容(直到下个指示符)显示了当前分支上的行
  • ======= 表示原始行内容的结束位置,以后的全部行(直到下个指示符)是被合并的当前分支上的行的内容
  • >>>>>>> dev 是要被合并的分支(此例中是 dev 分支)上的行结束指示符

注意一个文件可能在多个部分存在合并冲突,所以检查整个文件中的合并冲突指示符,搜索 <<< 可以帮助你找到全部这些指示符。

当出现冲突时,咱们须要手动的删除掉这些指示符,在该例子中,咱们想保留两个分支提交的内容,那么咱们能够进行以下操做:

冲突合并.gif

注意:由于 dev 分支与 master 分支修改的是同一文件,那么结合上文咱们所讲解的合并的类型,那么上例中的提交为普通合并,故须要一个新的提交。

固然,当咱们解决冲突后,咱们仍然须要将修改的内容 add 到暂存区中,而后提交。以下所示:

合并演示9.png

当提交完毕后,咱们再使用git log命令,咱们就能看到咱们的提交记录啦。

合并演示10.png

在上述提交记录中,咱们能够看到 master 分支上不只包含了 dev 分支上的提交,还包括了一个合并的提交(merge branch 'dev')。

IntelliJ IDEA or Android Sutdio 图形化界面的使用

最后仍是回到咱们熟悉的图形化界面的使用流程中。咱们来看看IDEA为咱们提供了哪些便利吧。

Tag的建立

经过依次点击编译器底部的 Version Control -> Log ,选择咱们想建立 Tag 的 commit ,而后点击鼠标右键,依次选择 New -> Tag ,并输入你想输入的 Tag 名称就行啦,具体以下所示:

建立Tag.gif

在建立Tag成功后,在该commit记录中会有一个灰色的标签。

Tag的删除

标签的删除也特别简单,在Git提交记录中点击包含咱们所建立的标签的commit,而后点击随便右键,依次选择标签名称->delete。就能够完成标签的删除啦。具体以下所示;

删除标签.gif

分支的建立

IntelliJ IDEA or Android Sutdio中,建立分支的地方大概有三个。我先说一下他们的具体位置,与他们之间的区别。

第一种方式

在编译器中,咱们只要选择工具栏中的VCS->Git->Branches,就能够从建立分支啦。

建立分支方式1.png

根据上述操做后,会弹出以下选择框,这个时候咱们只要选择 New Branch 选项就能够建立分支了。

建立分支方式1.2.png

下面对该选择框中的内容进行简单的介绍:

  • New Branch: 建立新的分支。
  • Checkout Tag or Revision...:切换到相应Tag或分支。
  • Local Branches:本地全部的分支。
  • Remote Branches:远程分支。(关于远程分支,会在后文介绍)。

须要注意的是:经过该种方式建立的分支。分支指针所指向的commit,是你所在分支下最新的commit!!!!

第二种方式

第二种方式建立分支,是经过点击编译器最右下角Git:master(该左下角的内容可能变化,好比你切换到了dev分支上,那么这个时候显示的是 Git:dev 。这里以 master 分支为例,来建立分支。

建立分支方式2.png

经过该种方式建立的分支。分支指针所指向的commiit,是你所在分支下最新的commit!!!!

第三种方式

经过依次点击编译器底部的Version Control->Log,而后选中咱们须要建立分支的commmit,而后点击鼠标右键,选择 New ->Branch

建立分支方式3.png

经过上述这种方式所建立的分支,分支指针所指向的commit为你选中的commit。

分支的删除

分支的删除也比较简单,经过依次点击编译器底部的Version Control->Log,而后找到有分支的commit,点击鼠标键,找到你要删除的分支名称,而后选择 delete 就能够删除分支了。这里以删除分支 fix-23 为例:

分支的删除.png

分支的合并

分支的合并也一样的简单。

  • 要么咱们只要选择工具栏中的VCS->Git->Branches 弹出下列选择框,
  • 要么是经过点击编译器最右下角Git:master(该左下角的内容可能变化,好比你切换到了 dev 分支上,那么这个时候显示的是 Git:dev

而后咱们就能够选择相应的分支合并到对应分支下了,好比这里咱们以 master 分支须要合并 dev 分支为例:

分支的合并展现.png

在上述图中,咱们只用选择 Merge into Current 就能够了,须要注意的是,当咱们选择合并分支时,咱们须要切换到正确的的分支上。

分支的切换

怎样切换分支?参考上图,当咱们选择了 dev 分支后,右方有一个 Checkout 选项,只要点击该选项,咱们就能切换到对应分支啦~~~

解决冲突

当合并分支出现冲突的时候,编译器会提示咱们合并冲突,会弹出以下代码框:

冲突展现框.png

整个代码块分为三个部分:

  • 左边(Left) Your version : 表明你当前分支上的更改。
  • 右边(Right) Change from branch :表明你合并的分支。
  • 中间的 Result 表明通过处理后的内容。

内容区域的代码颜色分为四个部分:

  • 红色区域:表明当前分支和合并分支都编辑过的内容,属于冲突
  • 蓝色区域:表明被单方面编辑过的内容,属于更改。
  • 灰色区域:表明被删除的内容,属于更改。
  • 绿色区域:表明新增的内容,属于更改。

对于冲突与更改,咱们均可以使用左侧或右侧的 >> 按钮来应用你想应用的更改,若是你并不想应用这些更改你可使用 X 按钮。最终你的全部的操做都会应用到中间的Result代码中。

当全部的冲突都被解决,全部更改都被应用后。咱们能够点击 Apply 按钮来完成咱们最终的合并操做。

固然你也能够点击 Accept Left 仍是 Accept Right 按钮来选择应用当前分支的内容仍是其余分支的内容。这个根据你直接的实际需求而定。

深度学习:查看 IntelliJ IDEA 中的官方介绍:Resolve Conflicts

小提示

若是说当你合并冲突的时候,不当心点击了 Abort 按钮,不用担忧,你仍然能够点击鼠标右键,依次选择 Git -> Resolve Conflicts选项来解决冲突。 以下所示:

遗忘解决的冲突.png

最后

站在巨人的肩膀上,才能看的更远~

相关文章
相关标签/搜索