写点什么

GIT 基本概念与核心命令

用户头像
IT视界
关注
发布于: 2021 年 06 月 15 日

一、GIT 体系概述:

  1. 大家公司是用什么工具来管理代码版本?SVN、CVS、GIT

  2. GIT 和 SVN 有什么区别呢?

GIT 与 svn 主要区别:

  1. 存储方式不一样

  2. 使用方式不一样

  3. 管理方式不一样

  4. 存储方式区别:GIT 把内容按元数据方式存储类似 k/v 数据库,而 SVN 是按文件存储的(新版 SVN 已改成元数据存储)GIT 内部是有一个 key/value 的数据库,可以理解为一个 Map,内容提交到数据库中时就会返回一个 key,key 是唯一的。git init demo 创建一个 git 项目 cd demo 进入项目 echo "test demo" >> README.MFgit hash-object -w README.MF 把文件提交到数据库中 会返回一个 keygit cat-file -p [key] 查看文件的内容回滚的话就可以通过 key 把值取出来进行回滚

  5. 使用方式区别:从本地把文件推送远程服务,SVN 只需要 commit,而 GIT 需要 add,commit,push 三个步骤 SVN 基本使用过程

从图中可以看出无论是谁开发的代码都是直接 commit 就提交到了 SVNGIT 基本使用过程

git 要提交内容的话,先要把修改的代码 add 进暂存区,然后 commit 到本地仓库,然后在 push 到远程仓库

  1. 版本管理模式区别 git 是一个分布式的版本管理系统,而 SVN 是一个远程集中式的版本管理系统集中式:

当远程仓库服务挂掉了之后,本地项目就不能做任何操作了分布式:

从图片中可以看出每个项目里都有一个本地的 git 仓库,因此当远程 git 服务挂掉之后,不会影响到本地的项目,仍然可以提交创建切换分支本地仓库很明显是可以和我们的远程仓库做关联的,有四种传输协议支持与远程仓库进行连接(传输协议会在下一篇文章进行详细的讲解),如果网络和服务是正常的,本地仓库就可以推送拉取代码,并且 git 还支持本地仓库关联多个远程仓库现在大家可以思考一下,为什么要关联多个远程仓库呢?现在假设我们的团队有 100 人,而一个仓库的人员最多只能有 50 人,因此需要分两个仓库去供开发人员使用,如果 git 只能关联一个仓库,那么推送的时候就只有一个仓库开发人员能够拉取到代码

二、GIT 核心命令使用

  1. 安装 git 客户端安装官方客户端: httpsd://git-scm.com/downloads其它客户端:https://tortoisegit.org/download/

  2. 认识 git 的基本使用

  3. git 项目创建与克隆

  4. 文件提交与推送完整模拟从项目添加到 push 的过程

  • 创建项目

  • 初始化 git 仓库

  • 提交文件

  • 远程关联

  • push 至远程仓库

本地初始化 GIT 仓库:git clone <remote_url> 从远程仓库克隆到本地 git init <directory> 在本地创建裸项目 mvn archetype:generate 基于 mvn 模板创建项目本地添加 git add <fileName> 添加指定文件至暂存区 git add <directory> 添加指定目录至暂存区 git add -a 或者 git add . 添加所有 git rm --cached target -r 将指定目录及子目录移除暂存区.gitignore 添加忽略配置文件本地提交 git commit -m '提交评论' 提交至本地仓库 git commit -am '快添加与提交' 快捷提交至本地仓库推送至远程 git push origin <分支名称>

  1. 分支管理 git branch [-avv] 查看本地分支 git branch <branch name> 基于当前分支创建分支 git branch <branch name> <commit id> 基于提交新建分支 git checkout <branch name> 切换分支 git merge <branch name> 合并指定分支如果因冲突导致自动合并失败,此时 status 为 mergeing 状态需要手动修改后重新 commit

  2. 远程仓库管理 git remote [-v] 查看远程配置 git remote add origin http:xxx.xxx 添加远程地址 git remote remove origin http:xxx.xxx 删除远程地址 git branch --track --set-upstream-to = origin/test test 本地分支与远程分支建立关联

  3. tag 管理 git tag 查看当前 git tag <tag name> <branch name> 创建分支 git tag -d <tag name> 删除分支

  4. 日志管理 git log 查看当前分支下所有提交日志 git log <branch name> 查看指定分支下所有提交日志 git log --oneline 单行显示日志 git log master..experiment 比较两个版本的区别

三、git 底层原理

  • GIT 存储对象

  • GIT 树对象

  • GIT 提交对象

  • GIT 引用

  1. GIT 存储对象(HashMap)Git 是一个内容寻址文件系统,其核心部分是一个简单的键值对数据库(key-value data store),你可以向数据库中插入任意内容,它会返回一个用于取回该值的 hash 键。

echo 'luban is good man' | git hash-object -w --stdin GIT 键值库中插入数据 git cat-file -p 79362d07cf264f8078b489a47132afbc73f87b9a 基于键获取指定内容 find .git/objects/ -type f 查找文件夹下所有的文件 在.git/objects 文件夹下就是查找所有的 git 对象向数据库中提交同样的代码返回的 key 是相同的

从图片可以看出插入到键值库的代码最后会变为 git 对象存储在.git/objects 文件夹下模拟演示 git 版写入与回滚过程 find .git/objects/ -type f 查找所有的 git 对像 echo 'version1' > README.MF; git hash-object -w README.MF; 写入版本 1echo 'version2' > README.MF; git hash-object -w README.MF; 写入版本 2echo 'version3' > README.MF; git hash-object -w README.MF; 写入版本 3git cat-file -p c11e96db44f7f3bc4c608aa7d7cd9ba4ab25066e > README.MF 回滚指定版本 Git 基于该功能 把每个文件的版本中内容都保存在数据库中,当要进行版本回滚的时候就通过其中一个键将期取回并替换我们平常用的 git add 其实就是把修改之后的内容 插入到键值库中。当我们执行 git add README.MF 等同于执行了 git hash-object -w README.MF 把文件写到数据库中。我们解决了存储的问题,但其只能存储内容却并没有存储文件名,如果要进行回滚 怎么知道哪个内容对应哪个文件呢?接下来我们要说的就是树对象,它解决了文件名存储的问题 ,使我们知道存储的对象对应的是哪个文件的内容。

  1. GIT 树对象树对像解决了文件名的问题,它的目的是将多个文件名组织在一起,其内包含多个文件名称与其对应的 Key 和其它树对像的引用,可以理解成操作系统当中的文件夹,一个文件夹包含多个文件和多个其它文件夹。git add . 把所有修改的文件插入到键值库内,每个文件生成一个 git 对象存储在.git/objects 下 git commit -m 'first commit' 在.git/objects 下会生成两个对象,一个提交对象,一个树对象 git cat-file -p master^{tree} 查看树对象内容

前两个字段是文件的类型,第三个字段是 key,第四个字段是生成这个 git 对象的文件名提交后如果要回滚的话就是根据树对象中的文件名找到对应的 key,在根据 key 找到对应的内容,进行回滚上面只在项目根目录下创建了两个文件,没有文件夹包裹,所以树对象内类型只有 blob,如果有文件夹包裹的话,提交之后会有一个顶级树对象,里面会包含文件名与对应的 key,还会包含文件夹名与对应的子树对象的 key,类似于一个链表,不过存储的并不是对象,而是对象的 key 与对应的文件名或文件夹名

还记得之前说的,commit 之后会生成两个对象吗,一个树对象,一个提交对象,接下来我们就来看一下提交对象

  1. GIT 提交对象一次提交即为当前版本的一个快照,该快照就是通过提交对像保存,其存储的内容为:一个顶级树对象、上一次提交的对像啥希、提交者用户名及邮箱、提交时间戳、提交评论。怎么查看提交对象的 key 是哪个呢?git log master 查看提交日志

第一个就是最近一次提交对象的 key

里面的内容有顶级树对象的 key,以及 parent 对象的 key,也就是上一个提交对象的 key 通过上面的知识,我们可以推测出从修改一个文件到提交的过程总共生成了三个对像:一个内容对象 ==> 存储了文件内容一个树对像 ==> 存储了文件名及内容对像的 key 一个提交对像 ==> 存储了树对像的 key 及提交评论。下面请大家思考一个问题:


当我们在 main 文件夹下新增一个文件并提交,会生成几个对象,都有哪些对象会重新生成?首先提交一定会生成一个 commit 对象,新增的文件对象,由于 main 树对象的内容里会引用新生成文件的 key 等信息,所以 main 对象也会重新生成,导致 main 树对象的 key 改变,那么引用了这个 key 的 src 树对象也会改变,同理顶级树对象也会改变。总共生成五个对象。现在这种项目回滚就不像单文件回滚看起来那么简单了,想要回滚到指定版本时,会先和当前版本比较顶级树对象,如果 key 改变了就会往下遍历,查找具体改变的文件,如上面两张图,luban.txt 和 README.MF 没有改变所以不会回滚这两个文件,找到改变的文件,替换内容就回滚完成了

  1. GIT 引用其实像分支和 tag 就是 git 引用,当创建一个分支或者 tag,就是在.git/refs/heads 和 tags 文件夹下创建了一个文件,里面包含的是最近一次提交 key,回滚操作就是把里面的 key 换成回滚到的版本的提交对象的 key


git 总共有三种类型的引用:

  • 分支引用

  • 远程分支引用

  • 标签引用

发布于: 2021 年 06 月 15 日阅读数: 76
用户头像

IT视界

关注

还未添加个人签名 2021.04.02 加入

致力于帮助所有选择IT行业的人们,希望能通过我的文章使大家少走弯路,踏上坦途

评论

发布
暂无评论
GIT基本概念与核心命令