这是我参与「第三届青训营 -后端场」笔记创作活动的的第 6 篇笔记
Git是什么
版本控制概念
- 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统
- 使用版本控制是为了更好的关注变更,了解每个版本的改动是什么,方便对改动的代码进行检查,预防事故的发生;同时也能回滚问题代码
版本控制类型
1. 本地版本控制
- 最初的方式:通过本地复制文件夹,来完成版本控制,一般可以通过不同的文件名来区分版本
- 解决方案:本地版本控制软件,其中最流行的就是RCS
- 基本原理:本地保存所有变更的补丁集,可以理解成就是所有的Diff,通过这些补丁,可以计算处每个版本的实际文件内容
- 缺点:RCS这种本地版本控制存在最致命的缺陷就是只能在本地使用,无法进行团队协作,因此使用的场景非常有限,因此衍生除了集中式的版本控制
2. 集中式版本控制
- 基本原理:提供一个远端服务来保存文件,所有用户的提交都提交到改服务器中,增量保存每次提交的Diff,如果提交的增量中和远端现存的文件存在冲突,则要本地提前解决冲突
- 优点:学习简单,支持二进制文件
- 缺点:本地不存储版本管理的概念,所有提交只能连上服务器之后进行;分支上的支持不够好,大型项目团队合作比较困难;用户本地不保存所有版本的代码,如果服务端故障容易导致历史版本丢失
3. 分布式版本控制
- 基本原理:每个库都存有完整的提交历史,可以在本地进行提交;每次提交的都是完整的文件快照,而不是增量,通过push等操作来完成远端代码的同步
- 优点:分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体;分支管理功能强大,方便团队合作,多人协同开发;校验和机制保证完整性,一般只添加数据,很少执行删除操作,不同意导致代码丢失
- 缺点:相对SVN更复杂,学习成本更高;对于大文件的支持不是特别好(如果需要提交大文件,使用git-lfs工具)
代码托管平台
- Github:全球最大的代码托管平台,大部分开源项目都在这个平台上
- Gitlab:全球最大的开源代码托管平台,项目的所有代码都是开源的,便于在自己的服务器上完成Gitlab的搭建
- Gerrit: 由Google开发的一个代码托管平台,Adroid这个开源项目就在这个平台上
Git基本操命令
Git目录介绍
- 项目初始化:
mkdir gitdir 创建目录
cd gitdir 定位到目录
git init 在目录下初始化git
其他参数:--initial-branch 指定初始化默认分支;--bare 创建一个裸仓库(纯Git目录,没有工作目录);--template 可以通过模板来创建预先构建好的自定义git目录
- 目录结构:
HEAD:存储当前指向的分支
config:配置
object:文件信息
refs:分支信息
常见Git配置
- 用户名配置
git config --global user.name "name"
git config --global user.email email
- Instead of配置
git config --global url.git@github.com:.insteadOf https://github.com/
- Git命令别名配置
git config --global alia cin "commit --amend --no-edit"
Git Remote
- 查看Remote
git remote -v
- 添加remote,ssh方式和https方式
git remote add origin_ssh git@github.com:git/git.git
git remote add origin)http https:github.com/git/git.git
- 同一个Origin设置不同的Push和Fetch URL
git remote set-url --push origin git@github.com:MY_REPOSITY/git
Git Add
将文件添加到暂存区,文件会在object目录下存有信息
Git commit
将文件提交到本地仓库,将来可以push到远程
Objects
commit/tree/blob在git里面都统一成为Objects,除此之外还有个tag的object
Blob:存储文件的内容
Tree:存储文件的目录信息
Commit:存储提交信息,一个Commit可以对应唯一版本的代码
这三个object如何串联到一起:
- 通过Commit找到Tree信息,每一个Commit都会存储对应的Tree ID
- 通过Tree存储的信息,获取对应的目录树信息
- 从tree中获得blob的ID,通过Blob ID获取对应文件的内容
Refs
refs的内容就是对应的Commit ID,因此把ref当作指针,指向对应的Commit来表示当前Ref对应的版本
不同种类的Ref:refs/heads 前缀表示的是分支,除此之外还有其他种类的ref,比如refs/tags前缀表示的表示标签
Branch:git checkout -b可以创建一个新分支,分支一般用于开发阶段,是可以不断添加Commit进行迭代的
Tag:git tag生成一个标签,标签一般表示的是一个稳定版本,指向的Commit一般不会变更
Annotation Tag:git tag -a创建一个附注标签,添加标签描述信息
追溯历史版本
- 获取当前版本代码:通过Ref指向的Commit可以获取唯一的代码版本
- 获取历史版本代码:Commit里面会存有parent commit字段,通过commit的串联获取历史版本代码
修改历史版本
commit --amend:可以修改最近的一次commit信息,修改之后的commit id会变rebase:通过git rebase -i HEAD~3:可以实现对最近三个commit的修改filter --branch:该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
Git Push
- 常用命令:一般用
git push origin master命令即可完成 - 冲突问题:如果本地的commit记录和远端的commit历史不一致,则会产生会冲突,比如
git --amend或git rebase都可能导致这个问题 - 推送规则限制:可以通过保护分支,来配置一些保护规则,防止误操作,或者一些不合规的操作出现导致代码丢失
总结
Git版本控制在团队开发过程中十分重要,能够协调各个开发成员的独立开发,也能对问题代码进行回滚操作,对于一个团队开发的工程项目版本管理,起到了非常强力的效果