Git 的原理与使用(中)(一)

简介: 分支是Git的杀手级功能之一。

Git 的原理与使用(上)中介绍了Git初识,Git的安装与初始化以及工作区、暂存区、版本库相关的概念与操作,本文接着上篇的内容,继续深入介绍Git在的分支管理远程操作方面的应用。


五、分支管理


1.理解分支


分支是Git的杀手级功能之一。


它就像是科幻电影里面的平行宇宙,当你正在电脑前努力学习C++的时候,也许另一个平行宇宙里的另一个你正在努力学习JAVA。这两个平行宇宙互不干扰,而在某个时间点,它俩发生了合并——于是,你既精通了C++,又精通了JAVA!


在版本回退章节里我们已经知道,Git会把每次提交串成一条时间线,这条时间线就可以理解为是一个分支。截止到目前我们的Git仓库里中只有一条时间线,这个分支叫主分支,即master分支(也叫main分支)。


然后再来理解一下HEAD。HEAD严格来说指向的不是“提交(commit)”,而是当前所在的分支,而分支才是指向“提交(commit)”的。比如当前我们所在的分支是master,那么HEAD指向的就是master,master指向的才是“提交”。如下图所示:



每次执行commit操作,master分支都会向前移动一步以指向最新的“提交”。这样,随着你不断commit,master分支的线也会越来越长。而HEAD则一直指向指向当前分支不变,即现在我们所在的master分支。



可以通过


git cat-file -p <commit ID>

命令来查看提交信息:




2.创建分支 branch


如何查看当前本地仓库中已有的所有分支?


在工作目录下执行


git branch

命令,系统就能为我们打印出当前本地仓库中有哪些分支:


hyb@139-159-150-152:~/gitcode$ git branch #查看当前本地所有分支
* master    # 显示结果

这里查询到当前本地仓库中只有一个master主分支。


在我们创建本地仓库时,git会自动给我们创建出一个master主分支。master前面有一个  *  ,*master 既表示master是当前的工作分支,也表示master分支正在被HEAD指针所指向。


关于HEAD:


HEAD不仅可以指向master主分支,也可以指向其它任意分支。


被HEAD指向的分支是当前正在工作的分支。由于之前我们的HEAD一直指向的是master分支,因此add操作、commit操作都是在master主分支上完成的。


为了演示多分支的情况,这里我们来创建第一个新的分支dev,对应的命令为:


git branch <分支名>


hyb@139-159-150-152:~/gitcode$ git branch dev #新建分支dev
hyb@139-159-150-152:~/gitcode$ git branch
  dev
* master


当我们创建新的分支后,Git 便新建了一个指针叫 dev。而 *HEAD 表示当前的 HEAD 仍然指向 master 分支,并没有发生变化。

也就是说,单纯的创建分支,是不会自动切换分支的。



# 打印一下HEAD指针的内容,可见HEAD指向的还是master
hyb@139-159-150-152:~/gitcode$ cat .git/HEAD
ref: refs/heads/master

此时,cat一下dev和master的内容,会发现它们两个指向的是同一个修改(即commit Id),这是因为dev分支是站在当前的版本去创建的,所以dev分支初始情况下也指向了最新的提交:




一张图总结:




3.切换分支


我们要想在dev上进行操作,就必须把dev分支当作工作分支。那如何切换到dev分支下进行开发呢?使用


git checkout <分支名>


命令即可完成切换。示例如下:



执行 git checkout dev切换分支后,HEAD就指向了dev,表示我们已经成功地切换到了dev上。随后,我们在dev分支下修改ReadMe文件,在末尾新增了一行内容 aaa on dev branch,并进行了一次提交操作。




现在,dev分支的工作完成,我们切换回master分支:


hyb@139-159-150-152:~/gitcode$ git checkout master 
Switched to branch 'master'


切换回master分支后再查看ReadMe文件内容,此时发现ReadMe文件中刚才新增的内容不见了:




而再切回dev查看,刚才新增的内容又有了:



为什么会出现这个现象呢?


我们来看看dev分支和master分支的指向,发现dev和master两者此时指向的提交已经不一样了:


hyb@139-159-150-152:~/gitcode$cat.git/refs/heads/dev
bdaf528ffbb8e05aee34d37685408f0e315e31a4    # dev和刚创建时相比已经发生了改变
hyb@139-159-150-152:~/gitcode$cat.git/refs/heads/master
5476bdeb12510f7cd72ac4766db7988925ebd302

进一步的,可以通过命令


git cat-file -p bdaf528ffbb8e05aee34d37685408f0e315e31a4

来查看此时dev所指向的提交的详情。查询到的详情中,parent关键字标识了当前commit的上一个commit是哪一个。可以看到,dev当前指向的上一个指向,正是刚创建dev时dev的指向。因为我们是在dev分支上提交的,所以dev会指向最新的提交;而master分支此刻的指向并没有改变(正如两个平行宇宙之间彼此独立的)。


master的视角下,当然就看不到在dev下的提交了,因此在master和dev两个分支下的ReadMe文件内容会有差别。


4.合并分支


为了在master主分支上能看到新的提交,就需要将dev分支合并到master分支。


使用


git merge dev

命令,示例如下:




git merge命令用于合并指定分支到当前分支。合并后,master分支上就能看到dev分支提交的内容了。此时的状态如图如下所示:





仍然可以用 cat .git/refs/heads/master命令和 cat .git/refs/heads/dev命令分别查看master和dev的指向,此时发现二者指向再次相同,dev中存储的commitID也被同步给了master。


By the way,细心的朋友可能注意到,刚才merge操作后,结果其实有些特殊:




这里的 Fast-forward 代表“快进模式”,它是Git分支合并的一种方式。快进模式意味着合并的方式是直接把master指向dev的当前提交,所以合并速度非常快。当然,也不是每次合并都是Fast-forward,我们后面会讲其他方式的合并。


5.创建、切换、合并分支流程图


1、创建新的dev分支。





2、git checkout dev:切换至dev分支。





3、在dev分支上commit。




4、切换回master分支,git merge dev





6.删除分支

合并完成后,dev分支对于我们来说就没用了,那么dev分支就可以被删除掉。删除分支的命令为:


git branch -d <分支名>


注意,如果当前正处于dev分支下,是不能删除dev分支本身的:


hyb@139-159-150-152:~/gitcode$ git branch
*dev
 master
hyb@139-159-150-152:~/gitcode$ git branch -d dev
error:Cannot delete branch 'dev' checked out at'/home/hyb/gitcode'

要删除当前分支,只能先切换到其他分支下,再执行删除操作,如:

hyb@139-159-150-152:~/gitcode$ git checkout master
Switched to branch 'master'
hyb@139-159-150-152:~/gitcode$ git branch -d dev
Deleted branch dev(was bdaf528).
hyb@139-159-150-152:~/gitcode$ git branch
* master

此时的状态如图如下所示:



因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全(“安全”正是使用分支的一个原因)。


7.合并冲突

在实际中,分支并不是想合并就一定能合并成功的,有时可能会遇到代码冲突的问题。


为了演示这问题,我们创建一个新的分支 dev1 ,并切换至目标分支。


注意,可以使用


git checkout -b dev1

一步完成创建并切换的动作,示例如下:




it checkout -b dev1

git branch dev1 + git checkout dev1

效果是相等的。

我们在dev1分支下修改ReadMe文件,将 aaa on dev branch 改为 bbb on dev branch,然后提交:




此时在dev1分支中,ReadMe文件最终修改并提交的结果为 bbb on dev branch。

切回master分支,然后在master分支下将ReadMe文件最终修改并提交为 ccc on dev branch:




现在master分支和dev1分支中都各自有了新的提交:





Git只能试图把各自的修改合并起来,但这种合并可能会有冲突。

在master分支中执行 git merge dev1 ,将dev1分支与master分支上提交的修改合并,结果如下:



发现ReadMe文件有冲突后,可以直接查看文件内容来查看冲突详情。Git会用<<<<<<<,=======,>>>>>>>来标记出不同分支冲突的具体内容,如下所示:




此时我们要做的是手动调整发生冲突的代码(将不要的内容手动删除,把要的内容保留下来),并需要再次提交修正后的结果!!

(再次提交很重要,切勿忘记)






到这里冲突就解决完成,此时的状态变成了:





Git 的原理与使用(中)(二)

+https://developer.aliyun.com/article/1521973?spm=a2c6h.13148508.setting.17.439a4f0eWJ4WIw


相关文章
|
7月前
|
Linux 网络安全 开发工具
1.Git使用技巧-基础原理
1.Git使用技巧-基础原理
69 0
|
Linux 网络安全 开发工具
【Git】Git 原理和使用
【Git】Git 原理和使用
420 4
|
7月前
|
存储 开发工具 git
Git的基本操作和原理
Git的基本操作和原理
|
4月前
|
存储 开发工具 数据库
Git的工作原理是什么
【8月更文挑战第24天】Git的工作原理是什么
57 0
|
6月前
|
前端开发 持续交付 开发工具
详细介绍Git的基本原理、在前端开发中的应用以及如何使用Git来优化团队协作
【6月更文挑战第14天】Git是前端开发中的必备工具,它通过分布式版本控制管理代码历史,支持分支、合并和冲突解决,促进团队协作。在前端开发中,Git用于代码追踪、版本控制、代码审查和持续集成部署,优化团队协作。制定分支策略、编写清晰提交信息、定期合并清理分支以及使用Git钩子和自动化工具能进一步提升效率。理解并善用Git,能有效提升前端项目的质量和开发效率。
84 3
|
7月前
|
运维 测试技术 开发工具
Git 的原理与使用(下)(二)
新特性或新功能开发完成后,开发人员需合到 develop 分支。
58 2
|
7月前
|
Java 网络安全 开发工具
Git 的原理与使用(中)(三)
别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
48 1
|
7月前
|
存储 安全 开发工具
Git 的原理与使用(中)(二)
Fast Forward 模式(ff模式) 通常合并分支时,如果可以,Git 会采用 Fast forward 模式。
44 1
|
7月前
|
存储 算法 开发工具
Git 的原理与使用(上) (二)
如果直接将某个文件拷贝到 .git 文件的同级目录gitcode下,此时这个文件是不会被Git管理的。
59 1
|
7月前
|
Linux 开发工具 git
Git 的原理与使用(下)(一)
在完成origin/dev分支合并到origin/master分支的操作后,origin/dev分支对于我们来说就没用了,那么dev分支就可以被删除掉。
68 0