在以前的文章中,咱们已经对仓库和提交已经有必定的了解了,在该篇文章中,咱们将学习git tag
、git branch
、 git checkout
和 git 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(标签)
通常表示比较重要的节点信息。编辑器
即便更多的提交被添加到仓库中(在下图中,咱们假设在D提交以后又陆续的提交了E、F、G三个提交),Tag(标签)
仍然锁定着某个提交,以下所示:ide
既然标签有着如此重要的做用,那如今咱们来看看在Git中如何建立标签吧。在Git中标签有两种类型:轻量标签
与附注标签
。工具
建立轻量标签的方式很是简单使用git tag
+标签名称
。以下所示:学习
git tag v1.0.0
复制代码
建立附注标签很是简单,须要在建立轻量标签的方式上,添加选项-a
。以下所示:ui
git tag -a v1.0.0
复制代码
经过上述方式,Git会运行你配置的文本编辑器输入标签信息。以下所示:idea
上图中,我配置的是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 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
复制代码
而建立的轻量标签中,是不包含该信息的,以下所示:
须要注意的是,建立的标签老是与commit进行绑定的。好比在上图中,标签是指向 441796...
这个提交的。
要删除掉本地的标签,咱们可使用命令 git tag -d <tagname>
。例如使用下面的命令删除标签:
git tag -d v1.0.0
Deleted tag 'v1.0.0' (was 3132ff5)
复制代码
其中 -d
选项表示delete(删除)
。
经过运行 git tag -a v1.0.0
,咱们能够给最近的commit添加标签,可是若是你想向仓库中好久以前的commit添加标签呢?很简单!咱们能够在原来的命令基础上,直接添加对应的commit的 SHA
便可。
使用
git log
命令查看历史提交记录。这里咱们能够提供完整的SHA
,或SHA
的前七个
字符,
git tag -a v1.0.0 abd12d0
复制代码
在上述命令中,咱们为 abd12d0
这个提交打上了标签。
在Git中,分支就像是科幻电影中的平行世界
。每一个平行世界都运行在独立的环境中,在正常状况下,每一个平行世界中所做的事,对于现实世界或另外一个平行世界是无感知的且不影响的。在某些特殊的状况下,平行世界与现实世界可能重合,那么就会产生混乱与冲突。那这个时候就须要咱们来解决这些冲突与问题。
扯太远了,分支在Git中,主要用于项目的开发或者对项目进行修正。由于全部的修改都是在分支中进行,因此并不会影响到项目(项目通常在主分支上,通常是 master
分支)。当咱们在分支中进行更改后,咱们能够将分支中的内容合并到分支上,这种分支组合过程,称为合并(merge)
。后续咱们会一一讲解这些内容。
那么接下来,咱们来看看Git中分支的使用方式和重要的概念。
在下图仓库中,咱们建立了一些提交,并在提交D
中建立了名为 v1.0
的标签,除了标签之外还包含一个隐藏的 master
分支。在咱们没有建立分支的状况下,Git会为咱们建立一个名为 master
的分支。其实 master
的本质实际上是一个 指针
。
master 并无什么特殊的意义,它只是第一个默认分支名。
随着咱们不断向仓库进行提交,这些提交都会添加到该分支上。同时 master指针
也会指向对应提交。以下所示:
在上图中,masetr
指针随着提交而不断移动。图中红线
所链接的提交都属于 master
分支。
相对于
Tag(标签)
,分支指针不会永久的指向某次提交,而是会随着提交不断的移动。
在某些状况下,咱们可能会建立另外一个分支。在下图中,咱们又建立了另外一分支 branch1
。
这个时候若是咱们再进行一个提交,哪一个分支会移动呢?是 master
仍是 branch1
分支呢?这里就涉及到另外一个知识点----> HEAD
指针。
在Git中,HEAD
老是指向当前活跃的分支。在你没有切换分支的状况下,默认指向 master
分支。以下图所示。
由于当前 HEAD指针
指向 master
分支,因此当咱们再向仓库提交一个I
提交对象时,该提交仍然会在 master
分支上。以下所示:
固然咱们能够改变 HEAD
指针所指向的内容, 使用 git checkout
命令,咱们能够切换 HEAD
指针所指向的分支。好比咱们能够经过命令git checkout branch1
,将 HEAD
指针指向 branch1
。
当咱们切换分支到 branch1
后,咱们后续的提交,都会添加到 branch1
分支上。好比下图,咱们又建立了一个 A提交
,那么这时 branch1
分支指针会指向该提交。
须要注意的是,分支中的提交对于其余分支来讲是不可见的。
在上图中,若是咱们当前切换到了 master
分支,那么在咱们的工做目录与文件系统中, branch1
分支的 A
与 branch2
分支中的 J
,这两个提交对文件形成的更改,将不会出如今 master
分支上的任何文件中。若是须要查看这个两个对应的文件修改,只须要切换到咱们想要查找的提交所在的分支就好了。
咱们基本已经熟悉了分支的相关概念与总体流程后,下面咱们来学习一下 相关命令的使用。
建立分支其实很简单,只需使用 git branch + 分支名称
。若是你想建立一个叫作 "branch1"
的分支,只需运行如下命令:
git branch branch1
复制代码
须要注意的是,若是你在某个提交上建立了一个分支,那么该提交以前的全部提交也是属于当前分支,在下图中,在 H
提交中使用了建立分支命令建立了 branch1
分支,那么在 H
提交以前的 D、E、F、G
也都属于 branch1
分支。
上图中 branch1
分支如蓝线所示。
固然,与建立标签同样,咱们也能够向之前的提交的 commit 添加分支。在下述命令中,咱们在 SHA
为 dfs14fo
的提交中建立了test分支。
git branch test dfs14fo
复制代码
要切换到另外一个分支,咱们须要使用命令 git checkout
命令,好比咱们须要切换到分支dev
上,那么咱们可使用以下命令:
git checkout dev
复制代码
经过上述操做,HEAD
指针会指向 dev
,须要注意的是,当你切换分支时,在你的工做目录中,会删除其余分支中 commit
引用的全部文件,同时会引用 dev
分支中的 commit
引用的文件。固然你不用担忧真的删除了你另外一分支上的文件。Git会将它们都存储在仓库中。当你切换回来后,又会将对应分支引用的文件显示在你的工做目录中。
若是你须要查看当前项目的分支,可使用 git branch
命令,经过该命令咱们不只能够知道仓库中所建立的分支,还能查看当前活跃的分支,也就是 HEAD
指针指向的分支。
在下图中,星号(*)
标记的为当前活跃的分支。
经过使用 git branch
命令,咱们只能查看当前活跃的分支,若是说咱们的项目有不一样的分支,咱们又想查看全部分支提交内容,那么咱们又该怎么办了呢?还记得咱们以前提到过的 git log
指令吗,这里咱们将添加 --graph
与 --all
选项。
--graph
选项:将条目和行添加到输出的最左侧。--all
选项:将显示仓库中的全部的分支信息。那么咱们可使用以下命令:
git log --oneline --graph --all
复制代码
--oneline
能够省略掉 commit 中的日期、做者等信息。以最简单的形式显示commit信息。
经过此命令,咱们能查看仓库中的全部的分支和 commit 信息:
在上文中,咱们提到,分支通常用于进行开发或对项目进行修正。当咱们将分支的更改 合并(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)
的方式有两种类型。一种是普通合并,另外一种是快进合并。下面咱们就来分别了解这两种合并方式。
假设咱们的项目存在这两条分支 master
与 branch1
两条分支。
这个时候咱们想将 branch1
合并到 master
分支上,因为当前HEAD
指向 master
分支,因此当两个分支合并时,将会生成一个合并提交 B
将放置在 master
分支上,而且 master指针
将会向前移动。以下所示:
须要注意的是, B提交
会连接branch1
中的 4
与 A
提交。同时当分支进行合并时,并不会影响到以前的分支,好比咱们仍然能够切换到branch1
分支上,并建立一个新的提交 J
,以下图所示:
假设咱们的项目存在这两条分支master
与branch1
支。且branch1
分支在master
分支前面。以下所示:
由于master
中是不包含 branch1
中的提交(I,K,2)
。若是这个时候咱们想将这些提交归入master
分支中,也就是须要将 branch1
分支 合并(merge)
到 master
分支中。当咱们在master
分支中使用命令 git merge branch1
时,由于 branch1分支
在 master分支
前,Git会作一个所谓的快进合并
。以下图所示:
在上图中,master
分支移动到了branch1
分支指向的commit。须要注意的是,快进合并并不像普通合并那样再建立一个提交。
大部分状况下,咱们都能成功的合并分支,可是某些状况下,Git没法自动的进行合并,当合并失败时,就称为合并冲突
。当出现冲突时,咱们须要手动的去修复文件中的冲突。看下面的例子:
在例子中,咱们已经建立了一个名为GitTestProject
的仓库,在仓库中咱们已经添加了一个名为Jvm系列之总目.md
文件到仓库中,以下所示:
其中 Jvm系列之总目.md
文件中的内容以下
这个时候咱们经过 git branch dev
命令建立了 dev
分支,并切换到该分支中,这个时候咱们原文中添加了下图中红框
中的内容。
注意的是,你须要常用
git branch
来查看活跃分支
在修改该文件并保存后,咱们能够经过git status
查看当前仓库的状态,而后咱们将在dev
分支修改的内容进行commit。内容以下所示:
咱们在原来的文件中,添加了一句Java class文件格式
。接下来,咱们经过git checkout master
切换到 master
分支,而后继续修改该文件,一样的修改的内容如红框所示:
一样的,在咱们完成修改后,咱们将在master
分支修改的内容进行commit。内容以下所示:
当提交完毕后,若是咱们想将dev
分支合并到 master
分支中,使用 git merge dev
命令,咱们能够看到以下报错:
当使用
git merge
命令时,你必定要注意当前所在的分支,你能够经过git branch
或者git status
来查看。
在上图中,Git告诉咱们文件 Jvm系列之总目录.md
出现了冲突。这个时候咱们再打开该文件,咱们可能看到以下内容:
在该文件中显示了一些特殊的一些符号,其实这些符号是Git定义的合并冲突指示符
,下面对这些指示符进行介绍:
<<<<<<< HEAD
此行下方的全部内容(直到下个指示符)显示了当前分支上的行=======
表示原始行内容的结束位置,以后的全部行(直到下个指示符)是被合并的当前分支上的行的内容>>>>>>> dev
是要被合并的分支(此例中是 dev 分支)上的行结束指示符注意一个文件可能在多个部分存在合并冲突,所以检查整个文件中的合并冲突指示符,搜索 <<< 可以帮助你找到全部这些指示符。
当出现冲突时,咱们须要手动的删除掉这些指示符,在该例子中,咱们想保留两个分支提交的内容,那么咱们能够进行以下操做:
注意:由于
dev
分支与master
分支修改的是同一文件,那么结合上文咱们所讲解的合并的类型,那么上例中的提交为普通合并
,故须要一个新的提交。
固然,当咱们解决冲突后,咱们仍然须要将修改的内容 add
到暂存区中,而后提交。以下所示:
当提交完毕后,咱们再使用git log
命令,咱们就能看到咱们的提交记录啦。
在上述提交记录中,咱们能够看到 master
分支上不只包含了 dev
分支上的提交,还包括了一个合并的提交(merge branch 'dev')。
最后仍是回到咱们熟悉的图形化界面的使用流程中。咱们来看看IDEA为咱们提供了哪些便利吧。
经过依次点击编译器底部的 Version Control
-> Log
,选择咱们想建立 Tag
的 commit ,而后点击鼠标右键,依次选择 New
-> Tag
,并输入你想输入的 Tag 名称就行啦,具体以下所示:
在建立Tag
成功后,在该commit记录中会有一个灰色的标签。
标签的删除也特别简单,在Git提交记录中点击包含咱们所建立的标签的commit,而后点击随便右键,依次选择标签名称
->delete
。就能够完成标签的删除啦。具体以下所示;
在 IntelliJ IDEA
or Android Sutdio
中,建立分支的地方大概有三个。我先说一下他们的具体位置,与他们之间的区别。
在编译器中,咱们只要选择工具栏中的VCS
->Git
->Branches
,就能够从建立分支啦。
根据上述操做后,会弹出以下选择框,这个时候咱们只要选择 New Branch
选项就能够建立分支了。
下面对该选择框中的内容进行简单的介绍:
须要注意的是:经过该种方式建立的分支。分支指针所指向的commit,是你所在分支下最新的commit!!!!
。
第二种方式建立分支,是经过点击编译器最右下角
的 Git:master
(该左下角的内容可能变化,好比你切换到了dev分支上,那么这个时候显示的是 Git:dev
。这里以 master
分支为例,来建立分支。
经过该种方式建立的分支。分支指针所指向的commiit,是你所在分支下最新的commit!!!!
。
经过依次点击编译器底部的Version Control
->Log
,而后选中咱们须要建立分支的commmit,而后点击鼠标右键,选择 New
->Branch
经过上述这种方式所建立的分支,分支指针所指向的commit为你选中的commit。
分支的删除也比较简单,经过依次点击编译器底部的Version Control
->Log
,而后找到有分支的commit,点击鼠标右
键,找到你要删除的分支名称,而后选择 delete
就能够删除分支了。这里以删除分支 fix-23
为例:
分支的合并也一样的简单。
VCS
->Git
->Branches
弹出下列选择框,最右下角
的 Git:master
(该左下角的内容可能变化,好比你切换到了 dev
分支上,那么这个时候显示的是 Git:dev
)而后咱们就能够选择相应的分支合并到对应分支下了,好比这里咱们以 master
分支须要合并 dev
分支为例:
在上述图中,咱们只用选择 Merge into Current
就能够了,须要注意的是,当咱们选择合并分支时,咱们须要切换到正确的的分支上。
怎样切换分支?参考上图,当咱们选择了 dev
分支后,右方有一个 Checkout
选项,只要点击该选项,咱们就能切换到对应分支啦~~~
当合并分支出现冲突的时候,编译器会提示咱们合并冲突,会弹出以下代码框:
整个代码块分为三个部分:
Left
) Your version
: 表明你当前分支上的更改。Right
) Change from branch
:表明你合并的分支。Result
表明通过处理后的内容。内容区域的代码颜色分为四个部分:
对于冲突与更改,咱们均可以使用左侧或右侧的 >>
按钮来应用你想应用的更改,若是你并不想应用这些更改你可使用 X
按钮。最终你的全部的操做都会应用到中间的Result
代码中。
当全部的冲突都被解决,全部更改都被应用后。咱们能够点击 Apply
按钮来完成咱们最终的合并操做。
固然你也能够点击 Accept Left
仍是 Accept Right
按钮来选择应用当前分支的内容仍是其余分支的内容。这个根据你直接的实际需求而定。
深度学习:查看 IntelliJ IDEA 中的官方介绍:Resolve Conflicts
若是说当你合并冲突的时候,不当心点击了 Abort
按钮,不用担忧,你仍然能够点击鼠标右键
,依次选择 Git
-> Resolve Conflicts
选项来解决冲突。 以下所示:
站在巨人的肩膀上,才能看的更远~