前言
大家好,我是加权,在37手游负责安卓SDK业务。
本文旨在介绍在工作中使用git的一些经验,让初学者能够快速理解和使用git,不会涉及高深的指令和冷门操作。希望对大家有帮助。
使用Git的目的
大家网上随便一搜就能查到git的各种优势,我就不复制粘贴了。
实际工作中,对我最有帮助的几点是
- 允许我犯错,能够撤销操作,恢复代码
- 完整的代码记录,能够了解项目代码的发展过程
- 分支的管理协作,避免代码混乱
而我使用git的根本目的在于,让我的项目时刻保持在一个清晰,便于维护的状态。所以我每做一个操作,都会思考下,这样做是否可以合理。
接下来,我们有必要先介绍下git的几个必须知道的概念。
基本概念
工作区域概念
- 工作区
- 工程下git管理的所有文件默认都在工作区
- 工作区的文件你可以随便玩,非常安全
- 工作区的改动通过add命令添加到暂存区
- 暂存区
- 暂存区是存放提交前的内容的地方,需要仔细留意进入暂存区的内容是否是你想要的
- 暂存区的内容可以提交(commit)到本地仓库
- 本地仓库
- 提交到本地仓库后,改动就会记录在案,可以针对提交记录做二次操作
- 提交后,二次处理提交记录时需要小心,因为操作错误后需要更复杂的方法才可以恢复,甚至不能恢复
- 本地仓库可以推送(push)到远程仓库,可以拉取(pul)远程仓库的内容
- 远程仓库:
- 公司代码的大本营,除了拉取代码(pull)是绝对安全,其他指令都要三思
- 一般情况下都会对远程仓库做权限管理,避免错误操作做成无法挽回的问题
操作对象概念
- 分支(branch)
- 创建分支等同于创建副本,在分支内做任何操作都非常安全,不会影响主版本
- 通常,一个需求会对应一个分支
- 大部分分支都是"消耗品",合并后会删除
- 头(HEAD)
- 是一个特殊的指针,指向你当前所在的提交上,一般来说都是指向某个分支的最新提交上,但是也可以单独指向某个提交
- 一般是不需要特别注意,但是做任何提交前,应该都要留意当前的头在哪里,确保操作正确
- 提交(commit)
- 当把暂存区的内容提交(动词)到仓库时,就会产生一个提交(commit,名词)
- 一个commit会有一个唯一的sha值,通过这个sha值就可以找回内容
- commit是单个操作的最小单元,大部分的二次操作都是针对commit的
- 在主分支上的commit可以说是永存的
- 不在主分支上的commit,大部分时候,只要知道sha值也可以恢复
- 标签(tags)
- 用来标记commit
- 常见用来标记发版节点
操作概念
- 检出(checkout)
- 切换、创建分支
- 提交(commit)
- 把暂存区的内容提交到仓库
- 推送(push)
- 把本地仓库的内容推送到远程仓库
- 一般都是推送单个分支
- 拉取(pul)
- 把远程仓库的内容拉取到本地仓库
- 需要注意,一些git工具(如source tree),可以跨分支拉取,有可能产生其他附带操作(如合并、变基)
- 获取(fetch)
- 拉取远程仓库的信息,不会对分支产生影响
- 合并(merge)
- 合并是针对分支操作的
- 合并有几种模式,需要注意的是快速合并不会产生commit,类似于直接复制分支,实际工作中,合并需求分支时禁用快速合并,强制产生commit会比较好
- 合并是有方向的,A merge B是把B分之合并到A分支,产生的commit会在A分支上
- 变基(rebase)
- 变基是针对分支操作的
- 简单地说,变基就是调整分支上的第一个commit的起始位置
- 变基的高阶操作,可以调整分支上任意一个commit,这一个功能对整理代码非常有用
- 遴选(cherry pick)
- cherry pick是针对commit的
- 可以理解为复制代码,一般是用来复制其他分支的commit到当前分支
- cherry pick对commit的细化程度有要求,如果commit内有多余的代码,通常就比较难直接cherry pick
- 回滚(revert)
- 提交一个commit的反操作,来消除commit
- 最合适的场景是,通过revert来移除一个已经合并的功能,对付反复修改需求的产品经理的神器
- 重置(reset)
- 把分支重置到某个commit,相当于撤销操作
- 注意,重置后,分支上的记录,甚至暂存区的内容,都会消失,因此需要小心操作
常用的概念基本就是这些,百看不如一练,接下来看看在实际场景中会用到哪些操作吧。
场景0:张三入职第一次拉工程
#0x00:拉工程
powershell
git clone xxxxx.git
相信聪明的大家都会了,不在赘述
#0x01:设置用户
有时候会漏了这一步,这样我们有可能看不出这代码是张三写的,那么想让他背锅的时候就比较麻烦~所以得让张三设置下用户属性。
powershell
git config user.name zhangsan
git config user.email zhangsan@gmail.com
如果是张三自己的电脑,他也可以是设置全局属性,那么就不用每次都设置了。
#0x02:拉取最新分支
通常clone仓库后,默认拉取的是master分支,张三需要确认下工程的分支规范,然后拉取最新的分支
powershell
git checkout dev
git pull
至此,张三就在本地有了最新的代码了他可以开始搬砖了
场景1:新任务
现在需求来了,我们给张三分配个需求,验下货,就给他做个登录界面吧。
那么张三就要先拉取最新的dev分支,如上一步,那么此时张三是在dev分支上了。
#0x00:创建分支
要新开任务,所以张三需要新建分支,分支名称如果能体现需求的话,在后续的处理上会有帮助,所以我们以fea前缀表示功能,login表示登录需求,创建一个fea-login分支。
powershell
git checkout -b fea-login
关于分支的规范各个团队可能不同,但是应该至少可以通过分支名区分出普通需求(feature)、更新功能(update)、移除功能(remove)、bug修复(bugfix)等类型,以便在分支合并或者回顾时快速知道分支的内容。
#0x01:提交代码
张三一顿操作之后,创建了几个新文件,此时他想先提交一次。
那么首先通过add命令,添加想提交的内容到暂存区
powershell
git add --all
这一步通过GUI工具会更加容易,比如sourceTree
通过GUI可以清晰看到暂存区的情况,可以按行或者按区块添加改动到暂存区,比敲命令更不容易出错。
添加代码到暂存区后,张三可以提交代码了。
为了提交记录的可读性,我们要求张三每次提交时需要写上能体现提交内容的信息
powershell
git commit -m 'a-添加登录文件'
关于提交信息,相信各个团队有自己的规范和要求。我自己习惯在提交信息前添加前缀来表示这个提交的主要作用,是新增代码(a),修改代码(m),修复问题(f),移除代码(rm),测试代码(ta/tm),还是无关重要的文本优化(o)。这个习惯对我回顾提交记录时有很大帮助,大家可以参考下。
又经过一顿操作,张三终于搞定了,他准备推送分支到远程仓库,好让我们合并分支了。
powershell
// 首次提交
git push --set-upstream origin fea-login
// 普通提交
git push
到目前为止张三表现不错,看看接下来怎样~
场景2:李四更新了远端分支
就在张三准备确认推送之前,李四告诉张三,因为他开发的功能有部分也涉及登录模块,已经提交合并到dev了,有可能会影响张三的功能,所以让张三注意下,避免产生冲突。
其实这里不一定要张三处理,不过张三第一天来,还是多干一点好好表现吧。
所以张三切换回dev分支,重新拉取了dev的代码
powershell
git checkout dev
git pull
因为改动的内容比较多,张三也不确认自己改动的代码会不会和现在的dev冲突,这时张三可以选择通过变基来确认是否有冲突
powershell
// 先切换回工作分支
git checkout fea-login
// rebase到最新的dev上
git rebase dev
运气不错,顺利完成了变基,张三确认自己的代码不会和dev产生冲突,可以推送到远程仓库了。这样在合并分支时,必定不会有冲突产生。
通过变基操作,我们的分支可以好像在最新的代码的基础上开发一样,如果代码有冲突,也能够得到明确提示,在这个场景下相当有用。
但是需要注意,rebase实际会产生新的commit,和原本的分支的提交记录会有较大差异,所以如果已经推送过到远端,则需要小心操作!
场景3:合并功能提测
张三和李四都开发完毕,现在可以合并提测了,首先介绍下合并的fast-forward概念
当前分支合并到另一分支时,如果没有分歧解决,会直接移动文件指针,这个过程就是fast-forward
这样合并后的效果相当于一直在主分支上开发,被合并分支不存在。
这样虽然看起来整个分支树会很简洁,但是在多人合作的场景下并不好,因为以后回顾的时候就好像张三直接在主分支开发了登录功能,如果都使用这种模式合并的话,很容易就无法区分功能分支了。
所以,在合并分支时,我更加倾向通过no-ff参数禁用fast-forward,强制产生一个新的merge commit,这样分支合并就很清晰了。
所以张三需要做的是
powershell
// 先切换回dev上
git checkout dev
// 确保代码最新
git pull
// 合并工作分支
git merge --no-ff fea-login
// 推送到远端
git push
这样就完成了可以提测了
一般提测可能还需要新增版本号,这时张三也可以直接在dev分支上新增版本号后再提交构建。
总结
至此,张三已经可以正常处理日常的开发需求了,回顾下几个重要点
- 一个功能应该一个分支,并且分支名称应该符合规范
- 提交代码应该把控好"颗粒度",并且应该填写符合规范的提交信息,方便review
- 推送分支代码前,应该先检查是否和远端有冲突,可通过rebase来处理,如果已经推送过远端需要小心操作
- 合并分支应该使用no-ff禁用fast-forward,产生合并commit
以上就是本文分享的全部内容了,下一篇文章我们再来分享下更多git操作。
欢迎大家在评论区说出git操作的一些问题,一起探讨~