Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

Git与Svn的区别

存储方式的区别

  • Git把内容按照元数据的方式存储类似key/value数据库
  • Svn把内容按照文件的方式存储,把文件的元信息隐藏在一个类似 .svn、.cvs等文件夹里

Git的存储方式 类k/v数据库:

例:初始化一个名称为git_test的Git仓库:

git init git_test

进入到git_test目录

cd git_test

在git_test仓库内新建一个hello.txt文件并追加内容为“Hello World”

echo "Hello World" > hello.txt

计算对象ID并将实际对象写入数据库(blob类型)

git hash-object -w hello.txt

根据对象ID打印出对象的内容

git cat-file -p 557db03de997c86a4a028e1ebd3a1ceb225be238

git-1

使用方式的区别

从本地把文件推送到远程服务:

  • svn:只需要commit
  • git:需要 add、commit、push

svn使用过程:

git-2

git使用过程:

git-3

版本管理模式的区别

  • git是一个分布式的版本管理系统
  • svn远程集中式的管理系统

git-4

核心命令的使用

安装git客户端

官方客户端: httpsd://git-scm.com/downloads

其它客户端:https://tortoisegit.org/download/

git的基本使用

git项目创建与克隆

  • 基于远程仓库克隆至本地
git clone <remote url>
  • 当前目录初始化为git本地仓库
git init <directory>
  • 基于maven模板创建仓库
mvn archetype:generate

文件提交与推送

  • 添加指定文件到暂存区
git add <fileName>
  • 添加指定目录到暂存区
git add <direactory>
  • 添加所有到暂存区
git add -A
  • 指定目录或文件移除暂存区
# 指定目录
git rm --cached <direactory> -r
# 指定文件
git rm --cached <fileName>
  • 添加忽略配置文件 .gitignore

  • 提交至本地仓库

git commit <fileName> -m "提交内容"
  • 提交所有至本地仓库
git commit -am "提交内容"
  • 推送
git push <远程主机名> <本地分支名>:<远程分支名>

分支管理

  • 查看当前分支
git branch [-avv]
  • 基于当前分支新建分支
git branch <branch name>
  • 基于提交新建分支
git branch <branch name> <commit id>
  • 切换分支
git checkout <branch name>
  • 合并分支
git merge <merge target>
  • 删除分支
git branch -d {dev}
  • 解决冲突:如果引冲突导致自动合并失败。此时status为mergeing 状态,需手动修改后重新提交(commit)

远程仓库管理

  • 查看远程配置
git remote [-v]
  • 添加远程地址
git remote add origin http://xxx.xxx
  • 删除远程地址
git remote remove origin 
  • 上传新分支至远程
git push --set-upstream origin master 
  • 将本地分支与远程建立关联
git branch --track --set-upstream-to=origin/test test

Tag管理

  • 查看当前Tag
git tag
  • 创建分支
git tag <tag name> <branch name>
  • 删除分支
git tag -d <tag name>

日志管理

  • 查看所有提交的日志
git log
  • 查看当前分支下提交的日志
git log <branch name>
  • 单行显示日志
git log --oneline
  • 比较两个版本的区别
git log master..experiment
  • 以图表的方式显示提交合并网格
git log --pretty=format:'%h %s' --graph
  • 查看详细修改
git show <branch name>

Git底层原理

Git存储对象

Git是一个内容寻址文件系统,其核心是一个简单的键值对数据库,可以向数据库中插入任意内容,它会返回一个用于取回该值的hash键。

基于键获取指定内容:

git cat-file -p  79362d07c

Git基于该功能把每个文件的版本中内容都保存在数据库中,当要进行回滚的时候就通过其中一个键将内容取回来并替换。

所以我们平常使用的 git add 其实就是把修改后的内容插入到键值库中。当我们执行 git add 等同于执行了 git hash-object -w 把文件写到数据中。

Git树对象

Git存储对象解决了存储的问题,但只是能存储内容并没有存储文件名,如果进行回滚,怎么知道那个内容对应哪个文件呢?树对象解决了文件名存储的问题。

树对象的目的是将多个文件名组织在一起,其内容包含多个文件名称与其对应的Key和其他树对象的引用,可以理解成操作系统当中的文件夹,一个文件夹包含多个文件和多个其他文件夹。

git-5

每一个分支当中都关联了一个树对象,它存储了当前分支下所有的文件名及对应的Key。通过以下命令可以查看

# 查看分支树
git cat-file -p master^{tree}

Git提交对象

一次提交即为当前版本的一个快照,该快照就是通过提交对象进行存储的,其存储内容为:一个顶级树对象、上一次提交的对象哈希、提交者用户名及邮箱、提交时间戳、提交评论。

通过存储对象、树对象、提交对象可以推测出修改一个文件到提交的过程总共生成了三个对象:

  • 一个内容对象:存储文件内容
  • 一个树对象:存储文件名及内容对象的Key
  • 一个提交对象:存储了树对象的Key及提交评论

Git引用

当执行 git branch 时创建了一个分支,其本质就是在git基于指定提交创建了一个引用文件,保存在 .git/refs/heads/ 目录下。

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

  • 分支引用
  • 远程分支引用
  • 标签引用
# 查询比较两个版本
git log master..experiment
# 版本提交历史网格
git log --pretty=format:'%h %s' --graph
# 查看分支树
git cat-file -p master^{tree}

Git支持的四种通信协议

Local(本地协议)

基于本地文件系统或共享(NFS)文件系统进行访问

优点:简单,直接使用现有的文件权限和网络权限,小团队小项目建立一个这样的版本管理系统是非常轻松的一件事。

缺点:这种协议缺陷就是本身共享文件系统的局限,只能在局域网,而且速度慢

适应场景:小团队,小项目临时搭建版本服务

本地协议使用方式:

# 从本地 d/git/atals 目录克隆项目
git clone d/git/atals/

# 即使是 brae 仓库也可以正常下载
git clone d/git/atals.git

# 基于 file 协议克隆本地项目
git clone file:///d/git/atals/

如果URL开头明确指定file://,那么Git的行为会略有不同。如果仅是指定路径,Git会尝试使用硬链接(hard link)或直接复制所需要的文件、如果指定file://,Git会触发平时用于网路传输资料的进程,传输过来的是打包好的文件,更节约硬盘空间。

ssh协议

Git支持利用ssh协议进行通信,这是绝大部分Linux、Uninx系统都支持的,所以利用该协议架设Git版本服务是非常方便的

优点:首先ssh架设相对简单,其次通过ssh访问是安全的、另外ssh协议很高效,在传输前也会尽量压缩数据。

缺点:权限体系下不灵活,必须提供操作系统的账户密码,哪怕是只需要读取版本。

适应场景:小团队、小项目、临时项目

http协议(dumb、smart)

Git http协议实现是依赖web容器(apache、nginx)及cgi组件进行通信交互,并利用web容器本身权限体系进行授权验证。在Git1.6.6前只支持http dumb(哑)协议,该协议只能下载不能提交,通常会配合ssh协议一起使用,ssh分配提交账号,http dumb提供只读账号。1.6.6之后Git提供了git-http-backend的CGI用于实现远程推送等功能。

优点:解决了local与ssh权限验证单一的问题、可基于http url提供匿名服务,从而可以放到公网上去。而local与ssh是很难做到这一点,必须实现一个类似github这样的网站。

缺点:架设复杂一些需要部署web服务器和HTTPS证书之类的配置

场景:大型团队、需要对权限精准控制。需要把服务部署到公网上去

注:http smart协议是基于CGI配个Git git-http-backend脚本进行使用,配置较复杂,现在一般不会这么去做,而是采用Gitlab、gogs之类的文本管理进行替代。

Git协议

Git协议是包含在Git里的一个特殊的守护进程;它监听在一个特定的端口(9418),类似于ssh服务,但是访问无需任何授权。

优点:目前Git协议是Git使用的网络传输协议里最快的。如果你的项目有很大的访问量,或者你的项目很庞大并且不需要为写进行用户授权,架设Git守护进程来提供服务是不错的选择。它使用与ssh相同的数据传输机制,但是省去了加密和授权的开销。

缺点:Git协议缺点是缺乏授权机制。而且9418是一个非标准端口,一般防火墙不会开放。