Git 的正确使用姿势与最佳实践 | 青训营笔记

162 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记

如果有错误和其他意见,麻烦留言指正💖

Git 简介

Git 是分布式版本控制工具

基本原理

  1. 每个库都存有完整的提交历史,可以直接在本地进行代码提交
  2. 每次提交记录都是完整的文件快照,而不是记录增量
  3. 通过 Push 等操作来完成和远端代码的同步

优点

  1. 分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体
  2. 分支管理功能强大,方便团队合作,多人协同开发
  3. 校验和机制保证完整性,一般只添加数据,很少执行删除操作,不容易导致代码丢失

缺点

  1. 相对 SVN (集中版本控制)更复杂,学习成本更高
  2. 对于大文件的支持不是特别好 (git-lfs工具可以弥补这个功能)

Git 命令

查阅文档

遇到不清楚的指令最好的方式还是查阅官方文档

git help [指令] 或者 git [指令] --help 查看详细指令说明,windows系统会在浏览器打开本地的文档

git [指令] -hgit [指令] -help 可以查看指令参数帮助

初始化

init

使用 git init 创建一个空的存储库,之后目录下会生产一个 .git 文件夹

init 常用参数:

  • --initial-branch 初始化的分支
  • --bare 创建一个裸仓库(纯Git目录,没有工作目录)
  • --template 可以通过模板来创建预先构建好的自定义 git 目录

git 目录

执行 tree .git/ 可以看到 git 的目录结构,不同版本git 会有一些差异

image.png

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 查看

image.png

3. 为同一个 Origin 设置不同的 Push 和 Fetch URL

  git remote set-url --add --push origin git@github.com:my_repo/git.git

image.png

ssh remote 配置

image.png

基本操作

add

在工作目录下创建一个文件,并用 add 命令添加到暂存区,.git 目录下的 objects 目录变化如下。

3b 和后面的一长串合起来组成了这个文件的 id

image.png

通过git cat-file -p [文件id]命令可以查看加密后的文件内容

 git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad

commit

通过 commit 命令将暂存区的内容添加到版本库中

默认 commit 使用的是 nano 文本编辑器。可以通过 git config --global core.editor vim 设置为 vim 编辑器

再次查看目录变化

image.png

这里涉及到的 object :

  • blob:存储文件的内容
  • tree:存储文件的目录信息
  • commit:存储提交信息,一个commit可以对应唯一版本的代码
  1. 通过commit 寻找 tree 信息,每个 commit 都会存储对应的 tree ID

image.png

  1. 通过 tree 存储的信息,获取对应的目录树信息

image.png

  1. 从 tree 中获得 blob 的 ID, 通过 blob ID 获取对应的文件内容

image.png

checkout

创建新分支

 git checkout -b test

image.png

refs 文件存储的内容就是对应的 commit ID

image.png refs/heads 前缀表示的是分支,除此之外还有其他种类的 ref,比如 refs/tags 前缀表示的是标签

tag

  • branch : 分支一般用于开发阶段,是可以不断添加 commit 进行迭代的
  • tag:标签一般表示的是一个稳定版本,指向的commit一般不会变更

1. 创建标签

 git tag v0.0.1

image.png

tag 指向的也是对应的 commit ID

image.png

2. 创建附注标签

 git tag -a v0.0.2 -m "add feature 1"

生成一个 tag 和新的 object,这个object 属于 tag 类型

image.png

tag中的内容指向 tag object

image.png

tag object 中存储了 commit ID 和 tag的注释信息

image.png

版本控制

amend

commit --amend 可以修改最近一次的commit信息,修改之后 commit id 会变,objects 中新增了一个 commit,tree和blob 不变

image.png

老的 commit 变成了一个 悬空的 object

可以通过 git fsck --lost-found来查找悬空 commit

image.png

如何清理这些悬空的 commit,涉及后面的 Git GC

rebase

  1. 合并 commit
  2. 修改具体的 commit message
  3. 删除某个 commit

filter --branch

该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作

GC

gc

通过 git gc命令,可以删除一些不需要的 object,以及会对 object 进行一些打包压缩来减少仓库的体积

reflog

reflog 是用于记录操作日志,防止误操作后数据丢失,通过reflog来找到丢失的数据,手动将日志设置为过期。

指定时间

git gc prune = now 指定的是修剪多久之前的对象,默认是两周前

多人协作命令

image.png

push

image.png

Git 版本控制原理

追溯历史版本

  • 获取当前版本代码

    通过 ref 指向的 commit 可以获取唯一的版本代码

  • 获取历史版本代码

    commit 里面会存有 parent commit 字段,通过 commit 的串联获取历史版本代码

实践

  1. 更新文件,然后commit,观察目录结构

image.png

  1. 可以发现 objects 下多了三个文件,也就是 blob,tree,commit

  2. 通过 git log 查看最新的commit id

image.png

  1. 根据 id 查看最新的commit

image.png

  1. 发现里面有个 parent 指向上一次commit