这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记
Git的介绍
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
图中有四个空间,是Git工作流程的精髓所在:
- Remote:远程仓库,即你在
Github或者Gitee等平台上创建的项目仓库 - Repository:本地仓库
- Index:暂存区,
.git文件夹里面的index文件,它保存即将提交到本地仓库的文件列表信息 - workspace:工作区,在编译器中正在编译的代码
版本控制
本地版本控制(RSC)
- 依托于本地磁盘进行版本控制
集中式版本控制(SVN)
- 存在一个统一的远端服务器,用于版本控制,本地不存储版本控制
分布式版本控制(Git)
- 每个库都拥有所有的版本控制信息,远端服务器用于不同库之间进行版本信息同步
Git的基本命令
暂时无法在文档外展示此内容
目录介绍
项目初始化
mkdir study
cd study
git init
Windows下使用tree.com .git/生成树状目录
Git Config
不同级别的Git配置
- --global 用户级别优先级居中
- --system 系统级别优先级最低
- --local 仓库级别,优先级最高
每个级别的配置都可能重复,但是低级的配置会覆盖高级的配置
git config --global -l`` 查看用户配置
用户名配置
git config --global user.email "youremail"
git config --global user.name "yourname"
git config -l查看所有的配置信息,依次是系统级别、用户级别、仓库级别
Git Remote
查看git remote --v
添加remote :
git remote add origin_ssh git@github.com:git/git.git
git remote add origin_http https://github.com/git/git.git
使用SSH密钥配置免密访问:
ssh-keygen -t rsa -b 4096 -C "youremail"
回车输入y生成密钥输入cat ~/.ssh/id_ed25519.pub查看密钥并到github的个人设置中找到下图位置复制即可
Git Add
git add .提交添加新文件,git status查看状态
Git Commit
git commit -m "提交信息"
Objects
commit/tree/blob在git里面统一称为Object,此外还有个tag的object
- blob:存储文件内容
- tree:存储文件目录
- commit:存储提交信息,一个commit可以对应一版本的代码
使用git log查看commit的tree ID,每个commit都会存储对应的tree ID
git cat-file -p ID
通过tree存储的信息,找到目录树信息
从tree中获取blob的ID,通过Blob ID获取对应文件内容
Refs
查看Refs文件存储的内容cat .git/refs/heads/master
refs的内容就是对应的commit ID,因此把ref当作指针,指向对应的Commit来表示当前Ref对应的版本
git checkout -b test新建一个分支
Windows下执行tree命令并没有显示新的test分支(这个tree命令显示的目录补全不太了解为啥)
老师的就有显示
refs/heads前缀表示的是分支,除此之外还有其他种类的ref,比如refs/tags前缀表示的是标签。
Branch
git checkout -b可以创建一个新分支,分支一般用于开发阶段,是可以不断添加Commit进行迭代
Tag
标签一般表示的是一个稳定版本,指向的Commit一般不会变更通过**git tag命令生成tag.
Annotation Tag
一种特殊的Tag,可以给Tag提供一些额外的信息,通过**
git tag -a**命令来完成附注标签的创建。
追溯历史版本
- 获取当前版本代码
通过Ref指向的Commit可以获取唯一代码版本
- 获取历史版本代码
Commit里面会存有parent commit字段,通过commit的串联获取历史版本代码。
- 修改文件,并提交创建新的commit
- 查看最新的commit,新增了parent信息
修改历史版本
- Commit- amend
通过**git commit --amend**这个命令可以修改最近的一次commit信息,修改之后commit id会变,这里修改了commit message多加了!!!,并且commit ID变了
修改Commit后我们可以发现git object又出现了变化,旧的并没有被删除称为悬空的object没有ref指向
通过git fsck --lost-found查找悬空的object
- Rebase
通过**git rebase-i HEAD~3**可以实现对最近三个commit的修改:
- 合并commit
- 修改具体的commit message
- 删除某个commit
- Filter- branch
该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
Git GC
- GC
通过**git gc**命令,可以删除一些不需要的object,以及会对object进行一些打包压缩来减少仓库的体积。
- Reflog
reflog是用于记录操作日志,防止误操作后数据丢失通过reflog来找到丢失的数据,手动将目志设置为过期。 git reflog expire --expire=now --all
- 指定时间
git gc --prune=now指定的是修剪多久之前的对象,默认是两周前
目录发生变化:
Git的完整视图
Git Clone & Pull & Fetch
- Clone
拉取完整的仓库到本地目录,可以指定分支,深度。
- Fetch
将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改refs/remote内的分支信息、,如果需要和本地代码合并需要手动操作。
- Pull
拉取远端某分支,并和本地代码进行合并,操作等同于git fetch+git merge也可以通过
git pull --rebase完成git fetch+git rebase操作。可能存在冲突,需要解决冲突。
Git Push
将本地代码同步至远端的方式
- 常用命令
一般使用**git push origin master**命令即可完成
- 冲突问题
- 如果本地的commit记录和远端的commit历史不一致,则会产生冲突,比如
git commit --amend or git rebase都有可能导致这个问题。
- 如果该分支就自己一个人使用,或者团队内确认过可以修改历史则可以通过
git push origin master-f来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送。
- 推送规则限制
可以通过保护分支,来配置一些保护规则,防止误操作,或者一些不合规的操作出现,导致代码丢失。
Git研发流程
集中式工作流
只依托master分支进行研发活动
- Gerrit 平台
围绕主分支进行开发
工作方式
- 获取远端master代码
- 直接在master分支完成修改
- 提交前拉取最新的master代码和本地代码进行合并(使用rebase),如果有冲突需要解决冲突
- 提交本地代码到master
分支管理工作流
- Git Flow 分支类型丰富
- Github Flow 只有主干分支和开发分支,规则简单
- Gitlab Flow 在主干分支和开发分支之上构建环境分支,版本分支,满足不同发布or环境的需要
Github工作流
Github的工作流,只有一个主干分支,基于Pull Request往主干分支中提交代码。
选择团队合作的方式
- Ownr创建好仓库后,其他用户通过Fork的方式来创建自己的仓库,并在fork的仓库上进行开发
- Ownr创建好仓库后,统一给团队内成员分配权限,直接在同一个仓库内进行开发
新建一个代码仓库
通过ssh将仓库复制到本地
创建文件提交并push到远程仓库
- vim readme
- git add .
- git commit -m "add readme"
- git push origin main
可以看到出现push的文件
创建一个Pull Request
- 创建一个main主分支
- 创建一个feature分支
git checkout -b feature - 创建一个feature到main的Pull Request
git push origin feature
github上会你feature分支已经push
点击向main分支合入,点击create即可
确认无误后点击merge合并代码
合并变化成功
切换到main分支使用git pull origin main拉取代码,在查看本地分支
Gitab工作流
Gitlab推荐的工作流是在GitFlow和Github Flow上做出优化,既保持单一主分支的简便,又可以适应不同的开发环境。原则上游优先
代码合并
- Fast-Forward
不会产生一个merge节点,合并后保持一个线性历史,如果target分支有了更新,则需要通过rebase操作更新source branch后才可以合入。
- Three-Way Merge
三方合并,会产生一个新的merge节点
选择工作流
- 选择原则
没有最好的,只有最合适的
针对小、型团队合作,推荐使用Github工作流知可
- 尽量保证少量多次,最好不要一次性提交上千行代码
- 提交Pull Request后最少需要保证有CR后再合入
- 主千分支尽量保持整洁,使用fast-forward合入方式,合入前进行rebase
大型团队合作,根据自己的需要指定不同的工作流,不需要局限在某种流程中。
参考文章
青训营Git的正确使用姿势与最佳实践PPT