前两篇博客集中的聊了git的一些常用命令,具体请参见《Git知识总览(一) 从 git clone 和 git status 谈起》、《Git知识总览(二) git常用命令概览》。本篇博客主要涉及了在git版本管理中的分支的创建、切换以及合并。并且罗列了在merge分支使发生冲突时的解决方式。同时还介绍了如何删除本地分支以及远程分支。本篇博客除了参考ProGit中的内容,还参考了learngitbranching这个网站进行的git分支内容的学习和梳理。下方的示例有的给出了基于LearningBranching的示例,有的是基于真实分支操作的示例。本篇博客只是git分支管理的部分知识,下篇博客会继续总结git分支的相关操作。
一、分支创建与切换
1、创建新的分支并切换到该分支上进行提交
首先我们先从最简单的来,下方演示了git分支的创建和切换的最基本的操作,具体步骤如下:
-
git branch <分支名> : 首先使用 git branch bugfix01,在当前分支也就是master分支上创建了一个名为bugfix01的新分支。
-
git checkout <分支名> : 然后使用 git checkout bugfix01 命令来切换到我们新创建的bugfix01的新分支上。
-
git commit : 最后使用 git commit 命令在新的分支上进行代码提交。
从上面的操作上我们不难看出,其中的星号*表示git的 HEAD 指针,指向当前所在分支。开始时 HEAD指针指向的是master分支,也就是用户当前所操作的分支是master。使用 git branch 创建一个新的分支后,HEAD的指向并没有改变,仍然指向的是master分支。当使用 git checkout 命令后,HEAD 指针就由 master 分支转向了 bugfix01 分支了,这样我们就可以对bugfix01进行操作了。
上面还需要注意的时,在创建好分支后,如果在新的分支上没有提交的话,那么 bugfix01 分支和 master 分支所指向的提交号是一致的,上面都是 C1。 这个 C1 表示的就是每次提交的哈希值,也就是提交号。当使用 git commit 时,说明在分支上有新的提交了,就会在之前的提交的基础上往下延伸一个提交,也就是 C2。后提交的 C2 会有一个指针指向上一个提交C1。
2、上述操作在终端的表现
接下来我们来看一下终端的具体操作。下方是最初的状态,目前所在的分支为master分支。从下方可以看出该分支上的Tag号,以及HEAD指针指向的master。
然后我们使用 git branch bugfix01 创建一个新的分支。从下方可以看出 bugfix01分支的指针指向的commit号和master的commit号一致,原因是我们从master中开出来的分支。不过当前所操作的分支仍然是master (HEAD -> master)。
因为我们从master分支上切换到了bugfix01分支上,所以此刻的HEAD指针指向的是bugfix01。
然后我们在bugfix01上提了一些代码,此刻我们看到bugfix01指向最新的commit,但是HEAD一直是指向当前分支bugfix的。
上面这些操作所使用的命令如下所示:
3、创建并切换分支
我们可以使用一个简写的命令来创建并切换到该分支上,下方就演示了这一操作:
-
git checkout -b <分支名> : 首先使用 git checkout -b bugfix02 命令在当前所在分支bugfix01上创建一个新的分支并且切换到新创建的bugfix02上。
-
git commit : 然后就可以使用 git commit 在新的分支 bugfix02 上进行提交了。
上述命令在终端上的执行结果就不做过多赘述了,请参见第二部分。
4、切换到之前的分支并提交
下方的使用场景是切换到之前已经创建好的分支上,并在切换后的分支上进行提交。下方操作后就会形成分叉。
-
git checkout <分支名> :目前所在分支是bugfix02, 然后使用 git checkout bugfix01 命令将分支切换到 bugfix01上。
-
git commit : 切换后就可以在bugfix01上进行提交操作了。
上篇博客中也聊到了,在终端中,我们可以使用 git log --oneline --graph --all 来查看所有分支情况。具体如下所示:
二、分支的合并与删除以及冲突解决
上一部分是如何创建分支和在各个分支间进行切换,接下来我们就来看一下分支的合并与删除。
1、分支的合并-merge
我们还以上面那个示例来看一下分支的合并。下方的操作主要是分支的合并、当在两个分支 bugfix01 和 bugfix02 上修改了相关bug, 并且需要将修改后的代码合入到master分支上。下方就是这一系列的操作:
-
首先使用 git checkout master 命令切换到master分支上。
-
然后使用 git merge bugfix01 命令将 bugfix01 分支的修改合入到master分支上,在合入成功后会将合入后的新文件进行提交,此刻会有一个新的commit号,也就对应着下方的C9。
-
然后使用 git merge bugfix02,在将 bugfix02上的修改合入到master分支上,merge 对应的commit号为C10。
-
最后还是可以在master分支上进行正常提交的。
下方就是我们在真正的分支中进行的分支合并的操作,我们将 bugfix01 分支merge到了master分支上。从下方可以看到 bugfix02 还尚未合入Master分支。稍后我们会在处理冲突的示例中将bugfix02分支合入到master分支中。
2、分支的删除
上面可以看到,虽然 bugfix01 和 bugfix02 的分支已经被合入到master分支上了,但是这两个分支还是存在的。如果我们不需要这两个分支指针了,可以将两个分支指针进行删除:
-
首先使用 git branch -d bugfix01 对分支 bugfix01 进行删除。
-
然后使用 git branch -d bugfix02 对分支 bugfix02 进行删除。
从下方的操作上来看对分支的删除只是删除的指向该commit号的指针,并不会删除其相关的提交号, 在日志中仍然可以找到之前的commit记录,也仍然可以在该commit上创建新的分支。如果你想删除远端的分支的话,那么得使用 $ git push origin --delete <分支名> 了。
还是要依附于实例,下方对上一部分已经合入master分支的bugfix01分支执行了删除操作,删除成功后会提示 “Delete branch bugfix01 ( was 223aefb)”, 后边这个就是删除分支所对应的commit号的前7位。
从下方截图中可以看到,其中bugfix01这个分支被删除了,不过删除的只是指向该commit号的一个指针或者别名,其他的都没改变。
3、冲突解决
上面是不冲突时的正常流程,如果在分支合并时,两个分支同时修改了同一个文件的同一个地方。此刻分支合并时就会冲突,就需要人工介入来解决冲突的代码了。上面我们说留着 bugfix02 这个分支是有用的,现在就来看一下bugfix02 这个分支的用处。从下方的 log 中不难发现,bugfix02分支和 master 分支都修改该了README.md文件的第二行数据。接下来我们就将 bugfix02 合入 master分支上。
下方截图的内容就是我们将 bugfix02 分支合入到 master分支时所报的冲突。冲突的大概意思就是在合并 README.md 文件时产生了冲突,自动合并失败了,需要修复这个冲突,在修复之后再对结果进行提交。我们可以使用 git status来查看一下当前的状态(配置的别名 git st)。从 git status的提示中也可以看到,你可以修复该冲突,然后使用 git commit 进行提交,或者 使用 git merge --abort 命令放弃本次合并。如果放弃本次合并就会回到合并之前的状态,当然,这并不是我们想要的,下方会对冲突进行解决,并提交,
接下来我们就来看一下冲突的具体内容,从<<<<<<<<开始到>>>>>>>>>结尾是冲突的部分,两个分支的内容由========进行分割。上方是当前分支所修改的内容, 我们需要将冲突的内容进行合并,根据具体情况具体分析,看那些需要保留那些不需要保留。还是都需要保留。
下方就是我们修改冲突后的内容,修复策略是保留了master的修改,删除了bugfix02分支的修改。然后将修改的文件进行提交即可,在此就不做过多赘述了。
4、使用工具进行冲突解决
输入 git mergetool 然后根据提示输入opendiff, 在Mac下会打开Xcode自带的FileMerge工具。
下方就是启动的 FileMerge 工具, 在使用该工具进行文件merge时,可以选择几种文件合并策略。比如以左边为准,以右边为准等。
上述工具位于Xcode的开发工具中,如下所示:
三、分支的查看以及强制删除
首先我们使用 git log --oneline --graph --all 命令来可视化的看一下目前的分支状态。从下方的截图中我们可以看到,目前共有三个分支 master、bugfix02、bugfix03。并且我们可以看出bugfix02已经合入master分支,bugfix03尚未合入。
下方是一系列查看分支的一些方法:
-
git branch : 查看所有分支,其中前面有星号的是当前所在分支,下方即为master分支。
-
git branch -v : 查看所有分支和该分支上最后的一次提交。
-
git branch --merged : 查看已经合入当前分支的所有分支。
-
git branch --no-merged : 查看未被合入分支。
今天博客关于git分支管理的内容就先到这吧,下篇博客会详细介绍 rebase 以及 cherry-pick 等相关内容。