git 使用手册
- 版本:v1.0.3
- 初始日期:2020-10-18
- 最后修订日期:2022-05-18
- 官方文档 https://git-scm.com/book/zh/v2
- 下载链接 https://git-scm.com/downloads
- 视频教程 https://www.bilibili.com/video/BV1PL411t7Xi?spm_id_from=333.999.0.0
基础概念
分布式版本控制系统
三种状态
区域 | 描述 |
---|---|
工作区 | 本地的工作目录 |
暂存区 | stage 或者叫 index 的暂存区,Git 自动创建的第一个分支 master,以及指向 master 的一个指针叫 HEAD |
Git仓库 | 工作目录里的一个隐藏目录 .git |
状态 | 描述 |
---|---|
已提交(committed) | 数据已经提交到本地仓库中,提交命令:git commit |
已修改(modified) | 数据在工作区已修改,未提交到暂存区 |
已暂存(staged) | 数据已保存到暂存区,可批量提交到本地仓库,暂存命令 git add |
基本工作流程
- 工作区中修改文件
- 对修改的文件进行快照,添加到暂存区
- 提交更新,将保存在暂存区的文件快照永久存储到 Git 仓库中
基本配置
Git 自带一个 git config
的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:
/etc/gitconfig
文件: 包含系统上每一个用户及他们仓库的通用配置。 如果在执行git config
时带上--system
选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)~/.gitconfig
或~/.config/git/config
文件:只针对当前用户。 你可以传递--global
选项让 Git 读写此文件,这会对你系统上所有的仓库生效。当前使用仓库的 Git 目录中的
config
文件(即.git/config
):针对该仓库。 你可以传递--local
选项让 Git 强制读写此文件,虽然默认情况下用的就是它。(当然,你需要进入某个 Git 仓库中才能让该选项生效。)
每一个级别会覆盖上一级别的配置,所以 .git/config
的配置变量会覆盖 /etc/gitconfig
中的配置变量。
在同时对多个 git 服务器操作时,需要确认你的当前用户名和邮箱,建议全部使用 --local
级别的配置。
# 查看版本
git --version
# 查看配置
git config --list
git config -l
# 设置用户名
git config --global user.name "姓名"
git config --local user.name "姓名"
# 没有参数默认等于 --local
git config user.name "姓名"
# 设置邮箱
git config --global user.email "邮箱地址"
git config --local user.email "姓名"
# 修改用户名、邮箱
git config --global --replace-all user.name "姓名"
git config --global --replace-all user.email "邮箱地址"
# 删除
git config --global --unset user.name "yourName"
git config --global --unset user.email "[email protected]"
本地仓库
# 在已存在目录中初始化仓库,在 IDEA 中需要重新启动后能看到项目文件状态的改变
git init
# 添加文件到暂存区
git add ...
git add *
git add .
# 提交更新
git commit -m 'initial project version'
# 跳过暂存区域提交更新
git commit -a -m 'added new benchmarks'
# 检查当前文件状态
git status
# 状态简览
git status -s
# 查看本地仓库
git ls-files
# 查看已暂存和未暂存的修改
git diff
# 查看提交历史
git log
# oneline 会将每个提交放在一行显示
git log --pretty=oneline
# -p 或 --patch,-2 选项来只显示最近的两次提交
git log -p -2
# 图形化分支显示日志
git log --graph --pretty=oneline
# 删除文件,如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。
git rm
# 我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。
git rm --cached
# 移动文件
git mv
# 取消暂存的文件
git reset HEAD ...
# 取消三个版本的暂存文件
git reset --hard HEAD^^^
git reset --hard HEAD~3
git reset --hard <版本标识符>
# 撤消对文件的修改、还原工作区删除的文件
git checkout -- ...
远程仓库
# 克隆远程仓库,通过 https,需要输入账号密码
# 还可以使用 ssh 方式 git@ 协议,需要本地生成公钥、私钥,公钥配置到 git 服务器,不用输入账号密码,比较方便
# 克隆完毕后,根据需要切换分支
git clone
# 使用本地 GIt 客户端生成秘钥
ssh-keygen -t rsa -C "GitHub 账号邮箱"
# 测试公钥是否生效
ssh -T [email protected]
# 查看本地已经链接的远程仓库
cd
git remote -v
# 添加远程仓库
git remote add
# 查看远程分支、检索远程分支(IDEA 中需要此命令刷新分支)
git fetch
# 从远程仓库中抓取与拉取, 为远程仓库的缩写
git fetch
# 推送到远程仓库
git push -u
# 查看某个远程仓库
git remote show
# 提交本地新项目到远程空白仓库流程
# 拉取远程仓库到本地的一个空白文件夹、本地的代码覆盖到新创建的文件夹(注意不要覆盖 .gig 文件夹)
# git add \ git commit \ git push
标签
# 列出标签
git tag
# 模糊查询,按照通配符列出标签,可使用 -l 或 --list 选项
git tag -l ""
git tag -l "v1.8.5*"
# 创建标签,Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。多数情况使用附注标签,如果只是想用一个临时的标签, 或者因为某些原因不想要保存这些信息,那么可以用轻量标签
# 创建附注标签,指定 -a 选项
git tag -a -m "备注"
git tag -a v1.4 -m "my version 1.4"
# 创建轻量标签,不需要使用 -a、-s 或 -m 选项,只需要提供标签名字
git tag
git tag v1.4
# 后期打标签,可以对过去的提交打标签
git tag -a v1.2 9fceb02
# 共享单个标签,把本地标签推送到远程仓库
git push
git push origin v1.4
# 共享全部标签,一次性把所有不在远程仓库的本地标签全部推送到远程仓库
git push --tags
git push origin --tags
# 删除标签,注意需要 push 推送
git tag -d
# 删除一个远程标签
git push :refs/tags/
分支
分支的新建与合并参考
https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%9A%84%E6%96%B0%E5%BB%BA%E4%B8%8E%E5%90%88%E5%B9%B6
# 创建分支
git branch
# 创建并切换到分支
git branch -b
# 查看本地和远程仓库分支
git branch -a
# 切换分支,当前分支的代码必须全部已提交
git checkout
# 删除分支
git branch -d
# 查看所有分支,* 标记当前所在分支
git branch
# 合并分支
git merge
# 重命名分支,如果 new branch 存在,则使用 -M 强制重命名,否则使用 -m 重命名
git branch -m|-M
# 推送本地分支到远程, 为远程分支名,可以跨分支推送
git push
# 删除远程分支、本地分支保留
git push :
# 拉取远程分支并在本地创建分支
get checkout -b /
# 根据 tag 创建分支
git fetch 刷新分支信息
git branch 根据 tag 创建新的分支
最佳实践
Gitflow 工作流
标准流程
[图片上传失败...(image-f10e3d-1652835548585)]
-
master 分支:
生产分支,最稳定的版本,一直是 ready to deploy 状态。不接受开发人员直接 commit,只接受从其他分支 merge 操作。在很多企业中,这个分支被默认开启分支保护,只有维护者可以操作。
-
hotfix 分支:
从 master 分支拉取的临时修复分支,用于解决一线紧急 bug。bug 解决后需要合入 master 分支并打上新的版本号,这个修改也需要同时合入 develop 分支。
-
develop 分支:
从master分支拉取的开发分支,用于功能集成。包含所有要发布到下一个 Release 的代码用于开发集成、系统测试。
-
release 分支:
临近既定的发布日,就从 develop 分支上拉取一个 release 分支,任何不在当前分支中的新功能都推到下个发布中。release 分支用于发布,所以从当前时间点之后新的功能不能再加到这个分支上,这个分支只做 Bug 修复、文档生成和其它面向发布的任务。当对外发布的工作都完成了,release 分支合并到 master 分支并分配一个版本号打好 Tag;另外,这些从 release 分支新做的修改要反向合并回 develop 分支。
-
feature 分支:
开发者使用的特性分支,父分支是 develop 分支,当新功能完成时,合入 develop 分支。新功能提交从不直接与 master 分支交互。
优点
- 使用一个用于发布准备的专门分支(release 分支),使得一个团队可以在完善当前的发布版本的同时,可以在 develop 分支并行继续开发下个版本的功能。这也打造了可视化的发布阶段,团队成员都可以在仓库网状结构中可以看到发布状态。
- 使用紧急修复分支(hotfix 分支)让团队可以处理紧急问题的同时而不打断其它工作或是等待下一个发布再合入 hotfix 修改。我们可以把 hotfix 分支想成是一个直接在 master 分支上处理的临时发布。
- 大型项目人员协作频繁,流程较多,合理的多角色分支帮助研发有条不紊进行。
- 更符合 devops 理念。
缺点
- 学习成本较高。
- 如果团队不遵守使用约定,带来的影响更大。
简化流程
简化流程去掉了 release、feature 分支。
-
master 分支:
生产分支,最稳定的版本,一直是 ready to deploy 状态。不接受开发人员直接 commit,只接受从其他分支 merge 操作。在很多企业中,这个分支被默认开启分支保护,只有维护者可以操作。
对于多模块项目,所有的代码在一个分支中,该分支代码可同时部署到 prd、uat 环境。在发版时,需要确认当前发版的模块,并打 tag 标签。
tag 标签命名规则为
v<主版本号>.<次版本号>.<修订号>_<模块>_<发版日期>_[hotfix]
。- 主版本号:全盘重构时增加、重大功能或方向改变时增加。
- 次版本号:增加新的业务功能时增加。
- 修订号:只要有改动就增加,当主版本号+次版本号变更时,修订号重置为 0
例如一个系统有 cms、auth 两个模块,tag 标签可以如下:
- v1.0.0_release_cms_20211003
-
v1.0.0_release_auth_20211003
- v1.0.1_release_cms_auth_20211005
-
v1.0.2_release_auth_20211006_hotfix
- v1.0.3_release_all_20211019
-
hotfix 分支:
从 master 分支拉取的临时修复分支,用于解决一线紧急 bug。bug 解决后需要合入 master 分支并打上新的版本号,这个修改也需要同时合入 develop 分支。
分支命名规则为
hotfix_yyyyMMdd_<功能模块>
,当修复分支部署到生产系统、并稳定运行后,需要定期删除修复分支。 -
develop 分支:
从 master 分支拉取的开发分支,用于功能集成。包含所有要发布到下一个 Release 的代码用于开发集成、系统测试。
一个完整的功能开发完毕后推送 push 一次,避免日志混乱;推送前先拉取 pull 远程的仓库代码,避免代码冲突。
常见任务
增加新功能
(dev)$: git checkout -b feature/xxx # 从 dev 建立特性分支
(feature/xxx)$: blabla # 开发
(feature/xxx)$: git add xxx
(feature/xxx)$: git commit -m 'feat comment'
(dev)$: git merge feature/xxx --no-ff # 把特性分支合并到 dev
修复紧急bug
(master)$: git checkout -b hotfix/xxx # 从 master 建立 hotfix 分支
(hotfix/xxx)$: blabla # 开发
(hotfix/xxx)$: git add xxx
(hotfix/xxx)$: git commit -m 'fix comment'
(master)$: git merge hotfix/xxx --no-ff # 把 hotfix 分支合并到 master,并上线到生产环境
(dev)$: git merge hotfix/xxx --no-ff # 把 hotfix 分支合并到 dev,同步代码
测试环境代码
(release)$: git merge dev --no-ff # 把 dev 分支合并到 release,然后在测试环境拉取并测试
生产环境上线
(master)$: git merge release --no-ff # 把 release 测试好的代码合并到 master,运维人员操作
(master)$: git tag -a v0.1 -m '部署包版本名' # 给版本命名,打Tag
Git 约定式提交
参考 https://www.jianshu.com/p/eb44ae2e5016
提交说明的结构如下所示
<类型>[(可选的作用域)]: <描述>
[可选的正文]
[可选的脚注]
每个提交都必须使用类型字段前缀,它由一个名词组成,诸如
feat
或fix
,其后接一个可选的作用域字段,以及一个必要的冒号(英文半角)和空格。作用域字段可以跟随在类型字段后面。作用域必须是一个描述某部分代码的名词,并用圆括号包围,例如:
fix(parser):
可以在类型/作用域前缀之后,
:
之前,附加!
字符,以进一步提醒注意破坏性变更。当有!
前缀时,正文或脚注内必须包含BREAKING CHANGE: description
类型
feat: 新增 feature
fix: 修复 bug
docs: 仅仅修改了文档,比如 README, CHANGELOG, CONTRIBUTE 等等
style: 仅仅修改了空格、格式缩进、逗号等等,不改变代码逻辑
refactor: 代码重构,没有加新功能或者修复 bug
perf: 优化相关,比如提升性能、体验
test: 测试用例,包括单元测试、集成测试等
chore: 改变构建流程、或者增加依赖库、工具等
revert: 回滚到上一个版本
示例
包含了描述以及正文内有破坏性变更的提交说明
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
包含了可选的 ! 字符以提醒注意破坏性变更的提交说明
chore!: drop Node 6 from testing matrix
BREAKING CHANGE: dropping Node 6 which hits end of life in April
不包含正文的提交说明
docs: correct spelling of CHANGELOG
包含作用域的提交说明
feat(lang): add polish language
为 fix 编写的提交说明,包含(可选的) issue 编号
fix: correct minor typos in code
see the issue for details on the typos fixed
closes issue #12
FAQ
如果提交符合多种类型我该如何操作?
回退并尽可能创建多次提交。约定式提交的好处之一是能够促使我们做出更有组织的提交和 PR。
冲突是怎么产生的,如何避免?
- 本地分支冲突,在本地主干与分支对同一个文件进行了修改并进行了提交,在合并分支时会产生冲突
- 多人协同冲突,多人在同一个分支下,对同一个文件进行了修改,在提交远程仓库时产生冲突
- 推送 push 前,先拉取 pull 可以降低冲突
参考
https://support.huaweicloud.com/bestpractice-codehub/codehub_practice_1005.html
http://team.bulo.cn/2019/11/21/git%E5%88%86%E6%94%AF%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/
https://www.zybuluo.com/Interista/note/107676
https://www.jianshu.com/p/9801b98c1de4
https://blog.csdn.net/weimingjue/article/details/88424758
https://www.jianshu.com/p/d46da933c180?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
培训内容
- 基础概念
- 华为云新建空白仓库
- IDEA git、svn切换
- 上传已有项目到仓库
- 创建分支
- 切换分支
- 日常提交(约定式注释)
- 合并分支
- 发版本打标签