课前资料
课程链接:https://live.juejin.cn/4354/yc_Git-posture
课程导学:https://juejin.cn/post/7098182433941651492#heading-36
本篇笔记完全依照课程流程复现,已尽量确保git操作的连贯性,各位同学可以依照笔记复习git操作,或者后续结合目录进行查漏补缺。
一、使用Git
mkdir git-demo
cd git-demo
git init
1.1 Git配置
1.1.1 Git Config
分为本地、用户、系统配置,低级别会被高级别配置覆盖。
1.1.2 Git Remote
# 可以配置不同的源
git remote add origin_ssh git@github.com:git/git.git
git remote add origin_http https://github.com/git/git.git
# 也可以实现fetch和push指向不同的源
# 关于修改配置可以通过直接修改配置文件的方式
vim .git/config
# 免密配置 生成SSH ed25519(但是需要修改配置指定使用哪个公私钥)
ssh-keygen -t ed25519 -C "邮箱"
1.2 代码提交
1.2.1 Git Add(将文件加入暂存区)
新建一个readme.md
文件,这是执行git add .
之前,执行tree .git
命令。
执行git add .
之后,再次执行tree .git
命令。
1.2.2 Git Commit(真正提交至Git目录当中)
执行git commit -m"add readme"
,此时objects目录中多了两个文件。
1.3 Git存储的基本概念
1.3.1 Objects(可以回溯tree->blob->得到add的文件内容)
- Blob 存储文件内容信息
- Tree 存储目录树信息
- Commit 存储提交信息
- Tag 存储附注标签信息
- Refs(存储对应的Commit Id)
事实上在完成了readme的提交之后,refs目录也发生了变化。
文件中是Commit Id(对应着一个版本的代码)。
尝试新建分支:git checkout -b test
。
1.3.2 Annotation Tag
refs是有不同的种类的,refs/heads
前缀表示的是分支,除此之外还有其他种类的ref,比如refs/tags
前缀表示的是标签。
标签一般表示一个稳定的版本,指向的Commit一般不会变更。执行git tag v0.0.1
命令,而执行git tag -a v0.02 -m"add feature1"
可以额外添加一些注释信息,分别执行一下之后,再次执行tree .git
命令查看目录树结构。
1.3.3 追溯历史代码
下面尝试追溯历史版本的代码,先修改一下test分支的readme文件,然后提交。
通过使用git log命令可以获取最新提交版本代码的Commit Id。
使用git cat-file -p
命令可以在显示的结果中找到当前commit
版本的parent
的Commit Id
。
1.3.4 修改历史版本(追溯之后可能会涉及到修改)
git commit --amend
命令
通过这个命令可以修改最近一次的commit
的message
信息,修改之后的commit id会变化,但是其tree
和parent
指向不会发生变化。
我们执行这个命令,然后尝试为commit
的message
增加三个感叹号,Esc + :wq
保存退出。
git rebase
命令(强大)
通过git rebase -i HEAD~3
可以实现对最近三个commit的修改,比如:
- 合并commit
- 修改具体的commit message
- 删除某个commit
filter --branch
该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
1.3.5 悬空Objects
通过git fsck --lost-found
命令可以查看当前是否有悬空的Object(没有ref指向的object),通过上述操作,git commit --amend
命令使得之前的那个commit id
指代的代码版本已经没有作用了。
1.3.6 Git GC
- GC
通过git gc命令,可以删除一些不需要的object,以及对object进行一些打包压缩来减少仓库的体积
- Reflog
reflog用于记录操作日志,防止误操作之后数据丢失,通过reflog来找到丢失的数据,手动将日志设置为过期
- 指定时间
git gc prune=now
指的是修剪多久之前的对象,默认是两周前
再次执行tree .git
命令查看目录结构有很大变化
1.3.7 完整的Git视图
1.3.8 Git Clone & Pull & Fetch
- Clone
拉取完整的仓库代码到本地目录,可以指定分支,深度。
- Fetch(不清楚远端情况)
将远端的某些分支最新代码拉取到本地,不会执行merge操作,会修改refs。remote内的分支信息,如果需要和本地代码合并需要手动操作。
- Pull(清楚远端情况)
拉取远端分支,并和本地代码进行合并,操作等同于git fetch + git merge
,也可以通过git pull --rebase
完成 git fetch + git rebase
操作。可能存在冲突,需要解决。
1.3.9 Git Push
常用命令:
一般使用 git push origin master
命令。
冲突问题:
- 本地的commit 记录和远端 commit 不一致,会产生冲突,如
git commit --amend
orgit rebase
命令都有可能导致这个问题。
- 如果该分支只有自己使用,或者团队内确认可以修改历史,则可以通过
git push origin master -f
来完成强制推送,一般不推荐主干分支执行该操作,正常都应该解决冲突后再进行推送。
推送规则:
设置一些分支保护规则防止误操作(Branch protection rules)
二、Git研发流程
2.1 集中式工作流
- 获取远端master分支代码
- 直接在master分支完成修改
- 提交前拉取最新master代码和本地代码合并使用(rebase),如果有冲突解决冲突
- 提交本地代码到master
2.2 分支管理工作流
2.2.1 Git Flow
分支类型丰富,规范严格
- Master:主干分支
- Develop:开发分支
- Feature:特性分支
- Release:发布分支
- Hotfix:热修复分支
2.2.2 Github Flow
只有主干分支和开发分支,规则简单,基于Pull Request 往主干分支中提交代码。
选择团队的合作方式:
- owner 创建好仓库之后,其他用户通过Fork的方式创建自己的仓库,并在fork的仓库上进行开发。
- owner 创建好仓库之后,统一给团队内成员分配权限,直接在同一个仓库内进行开发。
接下来模拟一下github-flow的工作流模式,先到自己的GitHub中创建一个仓库:github-flow-demo
,并克隆到本地。
然后在本地项目中创建一个readme
文件后提交到远程仓库。
创建一个feature
分支,修改readme文件后提交。
上图中GitHub自动生成了一个向main分支合入的pull request链接,复制后去浏览器打开。
点击Create pull request。
在确认代码没有问题之后,点击Merge pull request。
回到远程仓库的main分支,可以看到我们对readme的修改已经从feature分支合并到main分支上了。
最后回到本地仓库,切换回main分支,拉取远程main分支最新的代码。
- Branch protection rule(配置分支保护规则)
2.2.3 Gitlab Flow
在主干分支和开发分支的基础上构建环境分支,版本分支,满足不同发布or环境的需要。
原则:upstream first 上游优先
只有上游分支采纳的代码才可以进入到下游分支,一般上游分支就是master。
2.3 代码合并
2.3.1 Fast-Forward
不会产生一个merge节点,合并之后保持一个线性的历史,如果target分支又了更新,则需要通过rebase操作更新source branch 后才可以合入。
2.3.2 Three-Way Merge
三方合并,会产生一个新的merge节点
2.4 如何选择合适的工作流
没有最好,只有最合适,针对小团队合作,推荐使用 Github 工作流即可:
- 尽量保证少量多次,最好不要一次性提交上千行代码
- 提交Pull Request 后最少需要保证有CR(Code Review)后再合入
- 主干分支尽量保持整洁,使用fast-forward 合入方式,合入前进行rebase
关于git rebase可以看看这篇文章:https://blog.csdn.net/qq_24147051/article/details/118050241
小结
梳理了Git的知识,体验很棒。