这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记
如果有错误和其他意见,麻烦留言指正💖
Git 简介
Git 是分布式版本控制工具
基本原理
- 每个库都存有完整的提交历史,可以直接在本地进行代码提交
- 每次提交记录都是完整的文件快照,而不是记录增量
- 通过 Push 等操作来完成和远端代码的同步
优点
- 分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体
- 分支管理功能强大,方便团队合作,多人协同开发
- 校验和机制保证完整性,一般只添加数据,很少执行删除操作,不容易导致代码丢失
缺点
- 相对 SVN (集中版本控制)更复杂,学习成本更高
- 对于大文件的支持不是特别好 (git-lfs工具可以弥补这个功能)
Git 命令
查阅文档
遇到不清楚的指令最好的方式还是查阅官方文档
git help [指令] 或者 git [指令] --help 查看详细指令说明,windows系统会在浏览器打开本地的文档
git [指令] -h 或 git [指令] -help 可以查看指令参数帮助
初始化
init
使用 git init 创建一个空的存储库,之后目录下会生产一个 .git 文件夹
init 常用参数:
- --initial-branch 初始化的分支
- --bare 创建一个裸仓库(纯Git目录,没有工作目录)
- --template 可以通过模板来创建预先构建好的自定义 git 目录
git 目录
执行 tree .git/ 可以看到 git 的目录结构,不同版本git 会有一些差异
Git 配置
config
通过 git config 获取和设置存储库或全局选项
git config 可以配置三种级别:global,system,local 。
常见配置
1. 用户名配置
git config --global user.name "xiaoming"
git config --global user.email xiaoming@qq.com
2. url 替换配置 insteadOf
url.<base>.insteadOf 任何以此值开头的 URL 都将被重写为以 开头,一般用于协议替换
例如下面将 github.com/ 替换为git@github.com:
git config --global url.git@github.com:.insteadOf https://github.com/
3. git 命令别名配置 alias
alias.* 用来设置别名,一般用于简化命令
例如下面将commit --amend --no-edit 简化为 cin 命令
git config --global alias.cin "commit --amend --no-edit"
远程仓库
remote
git remote 管理一组跟踪的存储库
1. 添加 remote
下面执行 add 来分别添加 ssh 和 http 两个源
git remote add origin_ssh git@github.com:git/git.git
git remote add origin_http https://github.com/git/git.git
2. 查看remote
通过 git remote -v 查看
3. 为同一个 Origin 设置不同的 Push 和 Fetch URL
git remote set-url --add --push origin git@github.com:my_repo/git.git
ssh remote 配置
基本操作
add
在工作目录下创建一个文件,并用 add 命令添加到暂存区,.git 目录下的 objects 目录变化如下。
3b 和后面的一长串合起来组成了这个文件的 id
通过git cat-file -p [文件id]命令可以查看加密后的文件内容
git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
commit
通过 commit 命令将暂存区的内容添加到版本库中
默认 commit 使用的是 nano 文本编辑器。可以通过 git config --global core.editor vim 设置为 vim 编辑器
再次查看目录变化
这里涉及到的 object :
- blob:存储文件的内容
- tree:存储文件的目录信息
- commit:存储提交信息,一个commit可以对应唯一版本的代码
- 通过commit 寻找 tree 信息,每个 commit 都会存储对应的 tree ID
- 通过 tree 存储的信息,获取对应的目录树信息
- 从 tree 中获得 blob 的 ID, 通过 blob ID 获取对应的文件内容
checkout
创建新分支
git checkout -b test
refs 文件存储的内容就是对应的 commit ID
refs/heads 前缀表示的是分支,除此之外还有其他种类的 ref,比如 refs/tags 前缀表示的是标签
tag
- branch : 分支一般用于开发阶段,是可以不断添加 commit 进行迭代的
- tag:标签一般表示的是一个稳定版本,指向的commit一般不会变更
1. 创建标签
git tag v0.0.1
tag 指向的也是对应的 commit ID
2. 创建附注标签
git tag -a v0.0.2 -m "add feature 1"
生成一个 tag 和新的 object,这个object 属于 tag 类型
tag中的内容指向 tag object
tag object 中存储了 commit ID 和 tag的注释信息
版本控制
amend
commit --amend 可以修改最近一次的commit信息,修改之后 commit id 会变,objects 中新增了一个 commit,tree和blob 不变
老的 commit 变成了一个 悬空的 object
可以通过 git fsck --lost-found来查找悬空 commit
如何清理这些悬空的 commit,涉及后面的 Git GC
rebase
- 合并 commit
- 修改具体的 commit message
- 删除某个 commit
filter --branch
该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
GC
gc
通过 git gc命令,可以删除一些不需要的 object,以及会对 object 进行一些打包压缩来减少仓库的体积
reflog
reflog 是用于记录操作日志,防止误操作后数据丢失,通过reflog来找到丢失的数据,手动将日志设置为过期。
指定时间
git gc prune = now 指定的是修剪多久之前的对象,默认是两周前
多人协作命令
push
Git 版本控制原理
追溯历史版本
-
获取当前版本代码
通过 ref 指向的 commit 可以获取唯一的版本代码
-
获取历史版本代码
commit 里面会存有 parent commit 字段,通过 commit 的串联获取历史版本代码
实践
- 更新文件,然后commit,观察目录结构
-
可以发现 objects 下多了三个文件,也就是 blob,tree,commit
-
通过
git log查看最新的commit id
- 根据 id 查看最新的commit
- 发现里面有个 parent 指向上一次commit