这是我参与「第四届青训营 」笔记创作活动的第2天
你执行的Git命令都在做什么?
写在前面
- 需要协作开发,学习了Git
- 本文主要是讲 Git 的部分原理【若有误,欢迎指出】
- Git 的基本使用
- 其中包含了很多命令,都在对应的代码的后面
- 本文每一个图解都是接着上一个图解的状态来的
先来看两张图【了解一些基本概念】
- 图一【本地的几个区】
- 图二【本地和远程结合起来】
- 工作区
放你写的代码的地方。首次执行 git init之后,会生成 .git 文件。
- 暂存区
执行 git add 之后,会生成 blob 对象,也就是将文件放入本地仓库中。暂存区会出现索引,用于引用 本地仓库里的文件【注意,暂存区也会留存一份文件】
- 本地仓库
执行 git commit 之后,本地仓库会创建 tree对象和 commit 对象。master 分支会指向生成的 tree 对象,tree 会指向刚刚放入的 blob对象。
-
远程仓库
可用于做代码托管、自动化构建部署、云开发等等。开发人员将代码写好后,先提交到本地仓库,再通过push到远程仓库。另外的协作人员就可以通过pull将远程仓库的代码拉到自己的本地仓库,进行协作开发
(1)初始化本地仓库前
- 图解
- 文件夹目录
- 文件内容
# 【Linux 的命令】
# 1、查看当前文件夹和文件
ls
# 2、查看 aa.txt 的文件内容
cat aa.txt
(2)【 git init 】
主要是生成 .git 文件(是一个隐藏文件),并且生成了HEAD,一个头指针。直接指向的是一个现在所使用的分支
- 图解
- 【 .git 】 的文件目录
- 初始化命令
# 【Git命令】
# 1、本地仓库的初始化
git init
(3)【 git add . 】
将我们自己写的代码,放到本地仓库去。而且我们发现,这里相对于之前多出了一个index 文件, 这就是暂存区里面索引,该指向的是刚刚放入本地仓库的内容。而我们的代码放入本地仓库中,一个文件就生成了一个 blob 对象。文件名是文件内容生成的唯一的哈希值。
- 图解
- 目录文件【多了 index】
- 查看暂存区里面的内容
# 【Git命令】
# 1、查看暂存区里面的内容
git ls-files -s
# 2、git中查看对象中的内容【后面跟上新生成的文件名。(可以唯一标识就可以了,可以不用写全)】
git cat-file -p c20090
(4)【 git commit -m '描述信息' 】
生成tree对象,存储的有之前添加到本地仓库时 blob对象的源文件名。commit对象。每一次执行 git commit 都会生成一个commit对象。每一个commit对象就可以说是一个版本。生成commit和tree之后,就会将上一次执行 git add 时放入本地仓库的文件引用起来。
- 图解
- 目录信息【看上图,就可以知道哪个文件是什么】
- 查看本地仓库中生成的对象,分别是什么类型
# 【 Git 命令】
# 查看git对象的文件类型 【最后跟上的对象名,能唯一标识对象即可】
git cat-file -t d1fa8
(5)新增文件到本地仓库
在了解完上面的详细步骤后,你应该也了解了,每一个指令是做了什么。那下面我们就快速来看一下其他的操作吧~
- 执行的操作【 新增了 cc.txt 文件】
# 查看所有的commit对象【版本号】
git reflog
# 查看对象内容
git cat-file -p 56b32
- 图解
- 以前的commit对象会被新生成的commit引用。
- master从以前的commit对象指向新的commit对象。
(6)修改了文件内容
- 执行的操作【修改 a.txt 文件的内容】
# 查看现在的状态
git status
# 查看所有的commit对象【版本号】
git reflog
# 查看对象内容
git cat-file -p ec5c9
- 图解
- 注意索引指向的是修改后的文件
- 同新增有异曲同工之妙
(7)回退版本
- 执行的操作【回退到最开始的版本】
# 查看所有的commit对象【版本号】
git reflog
# 查看 aa.txt 的内容
cat aa.txt
# 查看当前目录的文件和文件夹
ls
# 回退指定的版本【 回到d1fa8b9 ,工作区也跟着回退】
git reset --hard d1fa8
# 回退到上一个版本【工作区也跟着回退】
git reset --hard^
# 回退到指定版本【仅仅回退本地仓库】
git reset --soft [对应版本号]
- 图解
(8)新增分支
①创建dev分支
- 执行的操作【新增 dev 分支】
# 查看所有的commit对象【版本号】
git reflog
# 查看所有分支
git branch
# 创建分支【创建dev分支】
git branch dev
# 切换分支【切换到dev分支】
git checkout dev
# 还可以直接创建并切换分支
git checkout -b dev
# 查看 .git/HEAD的文件内容
cat .git/HEAD
.git文件中HEAD用于指向现在的分支。我们直接查看他的内容,发现,它引用的是 refs/heads/dev
- 图解
②创建test分支
- 切换回master分支
- 创建test分支
- 新建test.txt文件且提交到本地仓库
- 执行的操作
# 切换到master分支
git checkout master
# 创建并且切换到test分支
git checkout -b test
# 查看分支
git branch
# 创建 test.txt 文件
touch test.txt
# 编辑 test.txt 文件
vi test.txt
# 查看所有的commit对象【版本号】
git reflog
# 查看对象内容
git cat-file -p d531
- 图解
(9)合并分支
- 图解【因为大图已经够乱了,就不继续画了】
可以看到,dev和test融合前的文件,融合之后有的文件。那是怎么来实现融合的呢?
- 三项合并原理
-
选择他们共同的最近的上游分支【base版本】。
-
将需合并的目标分支和所在分支与上游分支对比文件差异。
-
若都完全相同,则不合并【 Already up to date 】,否则进行合并。
-
若没有冲突,合并且自动提交到本地仓库。
-
若有冲突【 Merge conflict in 】,合并,自动提交会失败【Automatic merge failed;】,需要**解决冲突【 fix conflicts 】**后手动提交【 and then commit the result.】。
下图流程
-
这个图中相当于是,原先master分支有两个文件 aa.txt\bb.txt。
-
切换出两个一样的分支dev和test。
-
在test分支上面增加了新的文件test.txt。
-
第一次合并【将test合并到dev上】
-
第一次合并后。发现test.txt有bug,需要修改代码。然后拉出去一个fixbug分支,改完代码,并且添加了一个配置文件fix.config。
-
test分支切换出一个prod分支,开发了一个新的功能 cc.txt。
-
第二次合并【将fixbug分支合并到prod上】
- 执行的命令
# 切换到 dev 分支
git checkout dev
# 合并分支【将目标分支融合到现在所在的分支,这里是将 test merge to dev】
git merge test -m '描述信息'
# 查看当前目录的文件和文件夹
ls
(10)解决冲突
在开发中,一般情况下,如果出现了冲突,必须解决掉。并且,解决冲突的时候。【将先提交的代码放在前面,后提交的代码放在后面】
- 执行的操作
- 修改dev分支中 aa.txt的内容且提交
- 修改test分支中 aa.txt的内容且提交
- 合并test到dev分支上时出现冲突
- 解决冲突后手动提交
- 先来看图解
【因为与base版本相比,他们都有bb.txt且内容一样,都新增了一模一样的test.txt文件不会起冲突,我这里就讨论他们产生冲突的文件】
写在后面
- 如果看完了Git的这些原理,再来谈谈版本回退、合并、冲突啥的是不是就轻松一些了。
- 自己的文笔不好,文章写起不太好描述,肯定没有直接讲述容易,若有志合者,欢迎讨论。
- 怎么推送到远程仓库、拉取代码、远程仓库的分支、这些就不说了,也就是几个命令,都很简单。