前言
之前也学习过Git的基本操作,基本可以应付日常工作学习中的大部分场景,其实还有很多高深的Git操作没有去学习,当掌握了这些“骚操作”之后,也能提升我们的工作效率
开始之前我推荐一下Git的学习资料:
尤其Git沙盒,用闯关的形式教授Git分支的操作,非常有意思,不太喜欢枯燥的文章可以去试一下那个
正文
废话不多说我们直奔主题
基础篇
你应该知道每次提交(commit)之后都会产生一个节点,这个节点有唯一的Hash命名,可以通过git log
来查看提交的日志
基于分支的提交操作,我们需要处理以下步骤:
- 新建分支
- 切换至新分支
- 提交修改
git branch newBranch
git checkout newBranch
# 可以合并为一步,git checkout -b newBranch
# 做一些代码修改
git add .
git commit -m "newBranchCommit"
通过分支图我们可以看到当前的分支结构如图所示
可能不太明显,此时我们在master分支上再进行一次提交
假设此时本期需求已经开发完成,需要将所有的分支合并,我们一共有两种方式来进行合并commit和rebase
此时大部分情况下会有冲突产生,即合并的两条分支的代码不一致(两人同时新增不同的代码),git会帮我们做出如下改动
我们根据需要可以保留任意版本或者全部保留,然后添加暂存—>提交暂存
再来看第二种方式rebase,我们先回滚到上一版本,使用命令git reset HEAD~1
可以进行版本回滚,最后的数字代表要回滚的步数,不加数字默认为1步
rebase的原理就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。
git rebase master
此时同样需要解决冲突,解决完成之后一样的添加暂存—>提交暂存,来看一下它与merge的区别
在选定rebase目标之后,可以看见我们的分支多了一个REBASE-i
,此时出现了冲突,我们需要在解决冲突之后提交一下,然后使用--continue
命令来完成rebase,可以看见最后的REBASE-i
已经没有了
它与merge的区别在于可以将分支线性化,不会产生纠缠不清的分支
高级篇
你可能在之前的图片中看到 了HEAD这个指示,HEAD 总是指向当前分支上最近一次提交记录。如果想查看HEAD的指向,可以使用命令cat .git.HEAD
来查看,其实就是读取.git隐藏文件夹中的文件
如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD
查看它的指向
HEAD的意义就在于可以找到分支名无法指向的节点,使用分支名只能找到分支末端的节点
再来看分支图,蓝色的小圆圈就是指代的当前HEAD,后面的hash值就是刚才我们切换的节点
在使用hash值切换时不需要记住全部的hash,一般人也不会去记,只需要提供不会重复的前几位,Git就会帮我们自动完成。除此之外,还可以使用相对引用之前我们在版本回退的时候已经接触到了~
,现在再来加一个^
,比如我们当前在main分支上,我们可以使用git checkout master^
来切换到master分支当前节点的父级结点,^
可以叠加,如master^^
代表master分支的父节点的父节点
虽然^很方便,但是如果需要操作很多步,那也是很烦人的,所以~
就用来简化操作,比如^^^
等价于~3
可以使用git branch -f newBranch master~2
,将newBranch强制指向master的前两个节点
常用的分支操作:
git branch -d branchName,删除分支
git branch -d -r branchName,删除远程分支(需要提交才能生效)
git branch -D branchName,强制删除分支
git branch,查看本地分支
git branch -a,查看所有的远程分支
git branch -m oldName newName
此外,撤销变更我们之前说过了reset,还有一个revert可以用来撤销变更,区别在于reset是在本地的节点上回滚,只能在本地生效,;如果需要对远程分支产生影响就需要使用revert,revert会将内容回滚之后添加一个新的节点,需要commit提交一下
git revert -n 70ed3584
git commit -m "description"
移动提交记录
移动提交记录有两种方式,一种是cherry-pick
另一种是我们前面的老同学rebase
,我们先来看cherry-pick。cherry-pick可以指定版本号抓取提交记录到当前分支,比如下面的例子,我们将newBranch的提交记录抓取到master中
使用命令git cherry-pick <提交版本号>
,这里版本号就填红框后面的版本号(可以填多个,依次抓取到master上),效果如下
再来看一下rebase的效果,添加-i
(–interactive)命令,参数有两个起始版本号(不包括)和结束版本号(包括),或者也可以使用引用HEAD~4
等
git rebase -i startVer overVer
# 或者 git rebase -i HEAD~4
在键入命令后悔启动类似Vim的编辑器,如下
上方会展示要合并的记录,每一行的第一个单词是一个指令,含义如下:
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)
注意现在的顺序
我们将编辑器中的顺序调换为
可以看到已经调换了两个提交记录的位置
标记
在日常的发布中,我们现在大多使用的是CI/CD的流程,配置好打包脚本之后,只需要从git仓库拉取代码之后就可以自动打包发布了
使用tag
命令来进行标识
git tag version1
git tag versino2 hashCode
可以直接打标识,也可以指定某一hash码来打标识
如果要查看已有的标识可以使用git tag -l
命令来查看所有的分支,使用git describe --tags
可以查看距离当前提交记录最近的一个tag
掌握了这些git技能已经可以满足日常的开发了,还需要了解一下远程的操作,这里就不多做说明了