背景
本文主要目的是分享使用
git
进行代码版本管理的总结,其中对
git
原理的介绍,
git
的一般使用流程,工作中一些特殊场景的处理方式,以及对项目组成员的使用
git
的相关规范。随着后续项目中躺过的坑越来越多,相关问题也会继续记录。希望能给读者提供一些便利。
工作区、暂存区、版本库、远程仓库的关系
理解以上几个基本概念,对后续的操作会有加深印象的作用。可参考下图:
- 本地仓库,指的就是你电脑中的项目工程。
- 工作区。指的是项目工程中的目录。
- 暂存区:英文叫
stage
或index
。一般存放在.git
目录下的index
文件(.git/index
)中,所以我们把暂存区有时也叫作索引(index
)。暂存区是一个临时存储区域,它包含了即将被提交到版本库中的文件快照,在提交前,你可以选择的将工作区中的修改添加到暂存区。也可以将暂存区的变更修改。如:
git add <filename>
命令将修改后的文件重新添加到暂存区。这会用新的内容替换暂存区中的旧内容。git reset <filename>
命令。这将文件的修改从暂存区删除,保持与版本库一致。但不会修改你工作区的更改。
- 版本库:工作区有一个隐藏目录
.git
,这个不算工作区,而是 Git 的版本库。每次提交都会在版本库中创建一个新的快照,这些快照是不可变的, 确保了项目的完整历史记录。 - 远程仓库: 即项目代码在服务器上的备份。项目组成员都是基于该仓库进行联合开发。
- 其中
.git/objects
是Git
的数据存储中心,负责存放所有的版本控制信息。它通过高效的存储方式和完整性检查机制,确保了项目历史的可靠性和安全性。
注:一个文件从创建到提交到远程库的流程应该是:
工作区-(git add)-> 暂存区 -(git commit)-> master -(git push)-> 远程仓库
。
Git 使用流程
Git
作为版本管理的主流工具,它的使用流程主要分为:创建仓库、创建分支、代码提交。
创建仓库
我们在团队开发过程中,一般都会用远程git服务器,团队成员共同进行开发。但是这个远程仓库,如何被创建的呢?我操作的流程一般如下(已经在本地创建了工程,如:【项目总结】工程构建思路分析与分享中的基本CMakeList.txt框架):
- 在远程git服务器中创建新的项目。此时仓库中应该只有一个
README.md
文件。 - 本地进行
git clone
,将远程仓库同步到本地。
git clone http://192.168.3.25:8088/yhxie/myproject.git myproject
- 将本地代码工程提交到远程仓库。
cp localProject/* myproject/ -rf // 将本地仓库拷贝到仓库中
cd myproject
git checkout -b main // 创建main分支,并切换
gitadd. // 将项目工程提交到暂存区
git commit -m "init project" // 将项目工程提交到本地版本库
git push origin main // 将项目工程提交到远程仓库的main分支中。这样其他同事,就可以通过远程仓库,同步代码,进行联合开发
创建分支
在团队开发中,我一般会维护四类分支:
main
分支,
develop
分支,
feat_xxx
特性分支,
fix_xxx
修复分支。
main
分支:这是主要的分支,通常包含生产环境中稳定的代码。develop
分支:用于日常开发工作,通常是将新的功能、修复等合并到这里。版本发布,也是基于该分支进行打tag
。feat_xxx
特性分支:用于开发新特性,通常从develop
分支分出来,开发完成后再合并回develop
,再删除该特性分支。fix_xxx
修复分支:用于修复 bug,通常也是从develop
分支分出来,修复完成后合并回develop
,再删除该修复分支。
注:稳定且长期存在的分支,应该只有
main
和
develop
分支。
分支管理的相关命令:
- 创建分支。
git checkout -b <branchname>
,创建分支并切换到该分支(若分支存在,则只切换)。 - 查看分支。
git branch //查看本地所有分支
git branch -r //查看远程分支
git branch -a //查看远程及本地分支
- 合并分支。将其他分支合并到当前分支。在做特性分支开发时,时常需要执行该命令。
git merge develop (当前在特性分支上)// 将develop分支 merge到特性分支
// 原因:因为特性分支一般会开发比较久,并且最终需要合并到develop中。因此,每天早上执行下git merge,可以
// 早点发现 develop 分支与 特性分支的冲突点,及时解决。
git checkout develop
git merge feat_xxx // 特性分支开发完成后,需要合并到develop分支,执行该命令,可以发现是否有冲突,避免造成错误。
- 解决合并冲突。在合并分支过程中,若出现了冲突,需要手动解决冲突,并提交。
gitadd<conflict-file>git commit
- 删除分支。当特性分支或修复分支修改完成之后,需要删除,避免分支过多,不易管理。
git branch -d <branchname> //删除本地分支
git branch -D <branchname> // 强制删除未合并分支
git push origin --delete <branchname> //删除远程分支
- 提交分支。当你本地创建一个分支之后,若希望将该分支也同步到远程。
git push origin <brnachname> // 将本分支提交远程仓库,并命名为 <branchname>
文件修改
当我们基于特性分支或修复分支进行开发时,肯定会设置到文件的增删改查。最终验证通过后,需要将其提交到版本库或远程仓库。相关命令如下:
git status
,查看当前工作区的状态,显式有变更的文件。文件的状态有多种,如下:
- 未跟踪
untracked
。指在工作区中新创建的文件。 - 已跟踪
tracked
。git add
命令将未跟踪的文件添加到暂存区。 - 已修改
Modified
。对已跟踪的文件进行修改。 - 已暂存
staged
。将已修改的文件通过git add
添加到暂存区后。 - 已提交
commited
。使用git commit
命令将暂存区的更改提交到本地仓库后。
git add
将变化的文件提交到暂存区。git commit -m "note"
将暂存区内容,提交到本地版本库。git push
将本地修改,提交到远程仓库。
常见场景解决方式
仅仅通过上述的git使用指令,并不能完全覆盖我们的工作场景。在团队协作过程中,我们时常会遇到一些较为复杂的场景,本节介绍场景的问题并建议解决方案。
特性分支提交时,发现于develop分支有较大冲突,导致改动量较大。如何避免。
分析:特性分支的开发,往往需要较长时间。但这段时间内,develop分支可能也在不断的被其他同事更新。当你特性功能开发完成时,准备
git merge
合并时,发现有很多冲突,更甚者,可能会影响你的代码逻辑,导致需要重新构思方案。
建议:对于这种情况,我觉得是不可避免的。但是可以提前发现,提前解决。每天早上执行
git merge develop
命令,同步
develop
分支代码到特性分支,保证时刻同步 。
特性开发过程中,来了一个临时任务,如何处理?
分析:当我们在开发或解决问题时,往往会修改一些文件。但是当你还未完成时,来了一个优先级更高的任务,需要切换到其他分支进行解决。如果直接切换过去,可能会导致本地修改丢失或造成目标分支冗余。
建议:对于这种情况,我一般都是执行
git stash
,将当前
unstracked
,
Modified
的文件暂存。再切换到别的分支进行问题修改。当问题解决之后,再通过
git stash apply
恢复存储。
在工作中,不同的分支,常常会有共性问题,当一个共性问题在一个分支被解决后,如何处理?
分析:当共性问题,被别的同事解决之后,肯定也需要同步到本地。以前的本方法就是看别人的提交详情,自己一点一点的修改,效率比较低。
建议:执行
git cherry-pick <commit>
命令,可以选择特定的提交并将其应用到当前分支。
回退某一次提交
分析: 有时候,我们会不小心将一个未充分验证的提交点push到了远程分支。当发现它仍有缺陷,影响其他同事进行验证问题。如何快速解决呢?
建议:我们的做法一般有两种:
- 重新修改相关文件,提交。但是这种方式比较繁琐,麻烦些。
git revert <commit id>
撤销某个提交的更改,并将这些撤销的更改作为新的提交记录下来。
提交规范
我想强调的是,每次我们提交代码时,很多同事对提交点描述的并不详细,导致长时间回过头再看,自己也忘记了修改原由。因此,我要求每个人的每一笔提交,都要进行注释,并且注释也必须符合规范。每一笔
commit message
需要满足以下格式:
<type>(<scope>): <jira-id> <body>
介绍:
type
type 用于说明commit的类别,只允许出现以下标识:
build
:影响构建系统或外部依赖项的更改(cmake,maven,gradle,npm 等等);chore
:杂务,咋项,删除注释,修改注释(错别字、拼写等等);docs
:文档(documentation);fix
:修补 bug;feat
:新功能(feature);perf
:性能 (performance):提高代码性能的改变;revert
:Revert a commit;test
:增加测试或者修改测试;
scope
scope 用于说明 commit 影响的范围,比如数据层,协议层,进程,或者平台等。
jira-id
jira-id
指这个修改对应的
jira
号,因为我们内部任何任务:需求,bug,文档都是通过jira分配,方便后续跟踪追溯。
body
Body 部分是对本次 commit 的详细描述,可以分成多行。
范例如下:
fix(otaApp):[jira-651] 修复 FTP 升级 BLE 蓝牙模块偶发超时失败的问题由于升级 BLE 蓝牙模块时,MCU 需要将升级包转发给 BLE 并等待回复,存在偶尔耗时较多的情形,更改 otaApp 升级模块中发送升级包时数据帧的超时由 5s 增到 10s
合并请求
任何工程师都不可以直接将特性分支或修复分支修改内容直接合并到的develop分支,需要在gitlab 上发起
merge request
,至少三人评审通过,才可以进行merge。
总结
本文详细分享了使用Git进行代码版本管理的经验总结,包括Git的工作原理、使用流程、特殊场景处理及提交规范。强调了分支管理、代码提交、合并请求的重要性,并提出了具体的操作建议,希望提高团队协作效率和代码质量。
若我的内容对您有所帮助,还请关注我的公众号。不定期分享干活,剖析案例,也可以一起讨论分享。
我的宗旨:
踩完您工作中的所有坑并分享给您,让你的工作无bug,人生尽是坦途
版权归原作者 谢艺华 所有, 如有侵权,请联系我们删除。