一、背景介绍
近期在开发过程中因为 Git 操作不当以及使用不熟,带来了不少团队协作问题,比如:分支被覆盖、提交日志杂乱、分支创建很随意,同时在上线日当天需求被推迟上线,前端又需要对代码进行回滚以及 rebase
操作等系列问题。针对以上内部遇到的 Git 问题梳理了相关操作规范和 Git 使用指南。
二、Git 介绍
Git 是一个分布式版本控制工具,它可以非常轻松帮你管理任何时间任何人做的任何提交。 知识虽旧,历久弥坚。本文总结了在日常工作中是如何玩弄 Git 的,希望这篇总结对部分 Git 操作不熟的同学有所帮助。
概念理解
使用 Git 之前先了解 Git 仓库运转流程,共分为4个概念:本地空间、暂存区、本地仓库和远程仓库。如下图:
- 本地空间:存放的本地代码
- 暂存区:存放修改后的文件
- 本地仓库:存放提交修改后的文件
- 远程仓库:存放远程推送代码
是不是有点像 Vuex
: Action
-> Mutation
-> State
三、Git 工作使用
安装配置
- 下载 Git 软件
- 全局配置邮箱和账号
git config --global user.name "zhangsan"
git config --global user.email "zhangsan@github.com"
复制代码
- 配置账号和邮箱后,提交代码会显示提交人,便于问题追查和 CR 。
- 想要托管账户,可使用
ssh-keygen -t rsa -C "xxx@github.com"
生成公钥,把id_rsa.pub
内容复制到SSH keys
。
常用操作
日常工作中,对于 Git 的掌握用好了,也是一种提效,以下总结一些日常必备的 Git 技能。
远程仓库
- 克隆远程仓库
git clone <repo-url>
复制代码
- 关联远程仓库
git remote add origin <repo-url>
复制代码
本地已存在的项目关联到已有的仓库中。
代码提交
- 代码拉取
git pull
复制代码
- 文件暂存
git add .
复制代码
注意后面是一个点,点代表暂存所有,单个文件暂存改成文件路径即可。
- 本地仓库提交
git commit -m "feat: 开发订单" -a
复制代码
-m 代表提交备注,-a 代表提交所有文件。提交描述可参照下文的提交规范。
代码合并
如果想要把 feature/order
合并到 release
# 切换到 release 分支
git checkout release
# 合并功能分支到当前 release 分支
git merge feature/order
复制代码
分支合并是基本操作,合并的过程中很多时候会产生冲突,如果不确定使用谁的代码,最好跟当事者沟通一下。
远程推送
git push <remote> <branch>
复制代码
如果推送的时候被驳回了,大概率是冲突了,优先解决冲突并从新推送;如果确认使用本地代码,则可以使用
--force
强制推送。
分支操作
- 查看本地分支:git branch
- 查看远程分支:git branch -r
- 查看所有分支:git branch -a
- 切换分支:git checkout
- 切换并创建新分支:git checkout -b
- 删除本地分支:git branch -d
- 删除远程分支: git push origin :
- 合并分支:git merge
代码回滚
- 本地代码丢弃
# 单个文件丢弃
git checkout main.js
# 所有文件丢弃
git checkout .
复制代码
- 撤销某次提交
如上图,可以看到有2条记录,如果想要撤回log 1
的提交代码,可使用 git revert <commit-hash>
进行回滚。
git revert 0ac68bc3a99a351b4ef9e475436efffa307e7288
复制代码
使用
git revert
会生成一条新的提交记录
- 软回滚
同样以上图为例,如果发现log 2
的提交只是部分代码写错了,我们想要撤回来从新修改一下再提交,并不是完全舍弃,可使用 git reset --soft <commit>
进行软回滚。
git reset --soft <commit>
复制代码
需要注意的是,commit
指要回滚到哪个版本,此版本以后的提交都会被回滚(不包含当前版本),而 revert
只能撤销某一条提交。
回滚以后,从新执行 git status
你会发现这 log 2
文件变成了 modify
,也就是跟刚做完未提交是一个状态,此时我们可以若无其事的正常开发,正常提交。但是推送的时候由于跟远程仓库不一致,我们需要执行--force
进行强制推送。
- 硬回滚
同样以上图为例,如果发现 log 2
完全提交错误,想要舍弃,此时可使用 git reset --hard <commit>
进行回滚。
git reset --hard <commit>
复制代码
执行完硬回滚一下,本地仓库会完全删除 log 2
的代码,我们只需要强制推送即可。
软回滚本地会保留提交代码,硬回滚本地会删除对应提交代码。最后都必须通过
--force
才能推送到远程。为了方便起见,可使用[HEAD]
进行快捷操作,比如:git reset --soft HEAD~3
回退到前3次。
四、规范
多人协作时,为了更好管理分支以及提交日志,我们最好建立相关规范,提高协作效率。
分支规范
分支 | 介绍 | 环境 |
---|---|---|
master | 仓库默认分支,暂无使用 | - |
release | 线上保护分支 | Prd |
release-pre | 预发环境分支,用于QA做固定Pre测试 | Pre |
test | 测试环境分支,用于QA做固定Test测试 | Test |
feature/xxx | 功能开发分支 | Dev/Test |
hotfix/xxx | 热修复分支 | Pre/Prd |
release-2022xxx | 上线分支;上线当日部署到Pre进行验证,通过以后直接作为上线分支使用 | Pre/Prd |
日常开发中,对于线上环境、预发环境和测试环境建议使用固定分支进行部署,所有分支以 release
作为基线分支。之所以不用release-pre
或者 release
作为上线分支,是因为上线当天经常因为各种原因导致只有部分feature
是可以上线的。上线当天创建 release-20220818
并部署到Pre,如果验证通过直接部署上线,如果部分上线,则直接丢弃,再创建一个新的上线分支即可,避免污染 release
。
提交规范
提交代码时,务必填写提交日志,日志清晰明了,说明本次提交的目的。同时需要遵循一定的提交规范。
<type>(<scope>): <subject>
复制代码
- Header:包括三个字段:type(必需)、scope(可选)和subject(必需)。
- Type:提交commit的类别,建议使用下面标识
- feat: 加入新特性
- fix: 修复bug
- improvement: 在现有特性上的改进
- docs: 更改文档
- style: 修改了代码的格式
- refactor: 代码重构,不包含bug的修复以及新增特性
- perf: 提升性能的改动
- test: 测试用例的改动
- build: 改变了构建系统或者增加了新的依赖
- ci: 修改了自动化流程的配置文件或者脚本
- chore: 除了源码目录以及测试用例的其他修改
- revert: 回退到之前的一个commit
- Scope:用于说明 commit 影响的范围,默认可忽略。
- Subject:简短精炼的提交描述。
五、超实用技巧
场景一
如果我们正在开发一个功能,突然告知有线上问题,我们做了一半的代码如何保存?
# 缓存本地开发文件
git stash
# 取出最后一条缓存记录并删除
git stash pop
# 查看所有缓存列表
git stash list
# 应用某一条缓存
git stash apply stash@{index}
复制代码
- 使用
git stash
可以临时存储本地所有变动的文件,并从当前分支删除修改的代码。 - 切换到
release
创建hotfix-xxx
修复问题。 - 切换到
feature/xxx
,执行git stash pop
还原刚刚开发的代码。
一切都像没发生一样,很丝滑。
场景二
release-pre
合并了 5 次提交,最终QA
反馈只有一个功能对应的2次提交可以上线,我们如何把其中 2 次提交代码合并到release
?
- 方法一:把需要上线的功能分支直接合并到
release
进行上线。 - 方法二:使用`git revert 回滚其中不必要的提交。
- 方法三:使用
git cherry-pick
挑选需要的提交进行合并。
# 把某一次提交应用到当前分支
git cherry-pick <commit-hash>
# 把某几次提交应用到当前分支
git cherry-pick <commit-hash> <commit-hash>
# 把某个区间的提交应用到当前分支,注意不包含起始提交
git cherry-pick <start-commit>..<end-commit>
复制代码
如上图,如果想要挑选 4 和 5 的提交代码到 feature/order
分支,则执行:git cherry-pick 0c20eb75..6938e5e0
即可,注意不包含起始提交,左开右闭。
场景三
某需求做完以后,提测的时候通过 git log
发现 feature/order
分支有无数的提交记录,如下图,如何在提测的时候,让提交日志更干净?
通过git rebase -i <start-commit> <end-commit>
- 执行命令,弹出交互式界面
git rebase -i 6938e5e0
复制代码
- 修改指令
我们只需要把最后三次提交的pick
指令改为squash
或者fixup
即可,更多参数可参考如下:
- pick:保留该commit(缩写:p)
- reword:保留该commit,但我需要修改该commit的注释(缩写:r)
- edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
- squash:将该commit和前一个commit合并(缩写:s)
- fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
- exec:执行shell命令(缩写:x)
- drop:我要丢弃该commit(缩写:d)
- 输入
:wq
保存后,会进入到从新修改提交日志界面
- 我们只需要删除这些日志,从新输入我们本次功能开发的日志即可:
- 再次输入:
:wq
保存退出即可,最后查看日志如下:
这个世界真的很美好!!!
场景四
多人协作时,分支提交错综复杂,如何让分支提交变的更加线性?
现实是这样的?
使用 rebase
变基前后对比
已知线上分支 release
和 功能分支 feature/order
,当功能分支开发的同时,release
也同步做了修改(hotfix合并进来),此时我们通过 rebase
进行变基
# 切换到功能分支
git checkout feature/order
# 执行变基
git rebase release
复制代码
相当于临时保存 feature/order
分支代码,从新拉取 release
最新代码到本地,然后把 feature/order
合并进来,这个过程称之为变基,如果中间发生冲突,我们需要正常处理冲突,处理完以后,使用 git add .
添加到暂存区,使用git rebase --continue
继续执行,直到所有冲突解决完为止。如果中途想要放弃,可使用 git rebase --abort
进行终止。
git merge
是以提交的时间为先后顺序,而git rebase
不同,release
代码提交在前,功能分支提交在后,哪怕功能分支先提交的也不行。
以上就是给大家准备的Git指北,看完如果有问题可以在评论区留言,如果感觉有帮助,请点个赞,最后附上一张我收藏多年的宝藏图。
作者:HuolalaFE
链接:juejin.cn/post/712263…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。