入职后,公司使用的是gitlab去做协同开发,相比以前只会在一条master主分支上玩耍,要复杂一些,我觉得吧,git本身的命令不难,难的是要理解协同开发的流程,不能再像以前那像随性的提交,提交也可能变得没那么容易了,毕竟协同开发会涉及到冲突的问题,使用gitlab或者协同开发一般都遵循git flow 流程
git使用规范可参考:Git 使用规范流程
git flow流程,我的理解 :
一般只有一个master主分支和一个dev分支,每个组员基于dev分支checkout出很多特性分支,各自开发自己的功能,开发结束后 ,向dev分支提出MR(merge request),老大(组长)收到MR请求后,会review(检查)下你的代码,没有问题后同意合并,dev分支上的功能基本合并完后,就会向master主分支发起MR合并请求,master一般是一个稳定的版本,而dev一般是开发版本,基于dev分支克隆出release分支,其中测试工程师会克隆你的release分支,测试功能,测出bug,会在gitlab中提issue,开发看到了就要根据issue去查bug且修复它,测试完成后,合并到dev分支,且删除该release分支,大致流程就是这样
这里重点说下issue吧!因为我司就是采用以issue为中心的git workflow流程推进项目的,基于issue提需求,提bug,做测试,做讨论,做反馈等等。。
, issue即是一个任务,也可以表示一个新功能,也可以是一个bug的反馈,提了一个issue,老大一般会指派人去解决这个issue,指派人把dev分支更新到最后后,会checkout一个分支去解决这个issue,分支名也一般以这个issue名字和编号命名,比如:git checkout -b issue#121_xxx问题,最重要的是,当你解决了这个issue,你commit的信息要关联到这个issue上,所有commit的信息一般是以编号开头,描述置后,比如,git commit -m “#121_修复了xxx问题”,这样你push到远程仓库的时候就自动关联到对应的issue页面去了,刚开始接触的小伙伴,肯定也像我一样踩了不少坑吧,哈哈
一个master主分支和一个dev分支,不是硬性规定,git也没有这样规定过,但一般来说开发项目都是基于这样的流程,git flow流程
,这大概是前人总结出来的经验吧,这样做,多人开发的时候会好管理,总比打家都往master上push要强得多
git flow 流程各分支的解释:
master分支
主分支,产品的功能全部实现后,最终在master分支对外发布。
develop分支
开发分支,基于master分支克隆,产品的编码工作在此分支进行。
release分支
测试分支,基于delevop分支克隆,产品编码工作完成后,发布到本分支测试,测试过程中发现的小bug直接在本分支进行修复,修复完成后合并到develop分支。本分支属于临时分支,目的实现后可删除分支。
bugfix分支
Bug修复分支,基于master分支或发布的里程碑Tag克隆,主要用于修复对外发布的分支,收到客户的Bug反馈后,在此分支进行修复,修复完毕后分别合并到develop分支和master分支。本分支属于临时分支,目的实现后可删除分支。
feature分支
功能特征分支,基于develop分支克隆,主要用于多人协助开发场景或探索性功能验证场景,功能开发完毕后合并到develop分支。feature分支可创建多个,属于临时分支,目的实现后可删除分支。
注意:
这是大多数正规的项目该有的分支,但不是硬性规定,视自己公司的git 流程而定会稍微有些区别
其实细分的话,git的工作流程可以分为三类:git flow,github flow,gitlab flow
,而我说的git flow流程和gitlab flow工作流程基本一样,但又具有公司内部的一些小改动
这三者流程得区别,可看一下阮一峰老师的文章git flow,github flow,gitlab flow
Git 命令行操作
本地库初始化:
git init
注意:
此时会生成一个隐藏目录.git,.git 目录中存放的是本地库相关的子目录和文件,不要删除,也不要胡 乱修改。
设置签名:
作用:
区分不同开发人员的身份
辨析:
这里设置的签名和登录远程库(代码托管中心)的账号、密码没有任何关系。
签名大致可以分两种级别的:
项目级别/仓库级别:
仅在当前本地库范围内有效
git config user.name tom_pro
git config user.email [email protected]
信息保存位置:./.git/config 文件
系统用户级别:
登录当前操作系统的用户范围git config --global user.name tom_glb git config --global [email protected]
信息保存位置: ~/.gitconfig 文件
两种级别的优先级:
就近原则:项目级别优先于系统用户级别,二者都有时采用项目级别的签名 ,如果只有系统用户级别的签名,就以系统用户级别的签名为准,二者都没有不允许
基本操作:
状态查看
git status 查看工作区、暂存区状态
添加
git add [file name] 将工作区的“新建/修改”添加到暂存区
git add . 添加全部到暂存区
提交
git commit -m "commit message" [file name] 将暂存区的内容提交到本地库
git commit -m "commit message" 提交暂存区全部内容到本地库
git commit --amend -m "xxx" :这条命令太重要了,可以覆盖上一次的commit 信息和log(常用于修改commit信息和不想再多生成出一条log)
查看历史记录(有重要区别)
git log 查看详细的历史记录,只显示过去的commit记录
git log --pretty=oneline 查看简化后的历史记录,只显示过去的commit记录
git log --oneline 查看更加简化的历史记录,只显示过去的commit记录
git reflog 显示全部commit记录,包括过去和未来的
注:
HEAD@{移动到当前版本需要多少步}
git log --graph 以图形的方式展示提交合并记录
git log --graph --all 以图形的方式展示所有分支的提交合并记录
git log --graph --pretty=format:"%h %s" 以图形方式,但简化过的展示提交合并
版本回退:
本质上就是让head指针指回提交过的不同commit节点
基于索引值操作[推荐]
git reset --hard [局部索引值]
git reset --hard a6ace91
使用^符号:只能后退
git reset --hard HEAD^ 一个^表示后退一步,n 个表示后退 n 步
使用~符号:只能后退
git reset --hard HEAD~n 表示后退 n 步
reset 命令的三个参数对比
–soft 参数
- 仅仅在本地库移动 HEAD 指针
–mixed 参数
- 在本地库移动 HEAD 指针
- 重置暂存区
–hard 参数
-
在本地库移动 HEAD 指针
-
重置暂存区
-
重置工作区
总结:
版本回退使用–hard 就行了
分支操作
创建和删除分支
git branch [分支名] 本地创建分支
git branch -d [分支名] 删除本地的分支
git push origin --delete [branch-name] 删除远程仓库的分支
查看分支
git branch -a 列出所有本地分支和远程分支
git branch -r 列出所有远程分支
切换分支
git checkout [分支名]
git checkout . 这个很特别,撤回上一次git add.的意思,可不是切换分支哦
合并分支
第一步:切换到接受修改的分支(被合并,增加新内容)上
git checkout [被合并分支名]
第二步:执行 merge 命令
git merge [有新内容分支名]
合并分支时出现冲突:
合并分支的时候可能会出现冲突,冲突的原因是合并的两个分支中都修改了同一个文件的一个地方
冲突的表现:
冲突的解决 :
- 第一步:编辑文件,删除特殊符号
- 第二步:把文件修改到满意的程度,保存退出
- 第三步:git add .
- 第四步:git commit -m “日志信息”
注意:
此时 commit 一定不能带具体文件名
远程操作:
创建远程库地址别名:
git remote add [别名] [远程地址] 添加需要推送的远程仓库地址
git remote -v 查看当前所有远程地址别名
推送:
git push [别名] [分支名]
克隆:
git clone[远程地址]
克隆的效果
-
完整的把远程库下载到本地
(所有分支)
-
创建 origin 远程地址别名
-
初始化本地库
注意: 克隆的远程仓库有很多分支,但克隆后通过git branch 查看分支发现只有一个master分支,其实你直接checkout切换到其他分支就行了,只不过它没有显示而已(我觉得真的很坑)
拉取 及 push推送失败时解决冲突:
如果不是基于 GitHub 远程库的最新版所做的修改,不能推送,必须先拉取
。拉取下来后如果进入冲突状态,则按照“分支冲突解决”操作解决即可。
pull=fetch+merge
git fetch [远程库地址别名] [远程分支名]
git merge [远程库地址别名/远程分支名]
=
git pull [远程库地址别名] [远程分支名]
tag(里程碑)的操作:
git tag -a v1.0 -m ‘版本介绍’ 本地创建tag信息
git tag -d v1.0 删除tag
git push origin --tags 将本地tag信息推送到远程仓库
git pull origin --tags 更新本地tag版本信息
git checkout v.10 切换tag
git clone -b v0.1 指定tag下载代码
更加详细的git命令清单,可参考阮一峰老师的总结:常用git命令清单