前言

之前也学习过Git的基本操作,基本可以应付日常工作学习中的大部分场景,其实还有很多高深的Git操作没有去学习,当掌握了这些“骚操作”之后,也能提升我们的工作效率

开始之前我推荐一下Git的学习资料:

尤其Git沙盒,用闯关的形式教授Git分支的操作,非常有意思,不太喜欢枯燥的文章可以去试一下那个

正文

废话不多说我们直奔主题

基础篇

你应该知道每次提交(commit)之后都会产生一个节点,这个节点有唯一的Hash命名,可以通过git log来查看提交的日志

image-20210523182748117

基于分支的提交操作,我们需要处理以下步骤:

  • 新建分支
  • 切换至新分支
  • 提交修改
 git branch newBranch
 git checkout newBranch
 # 可以合并为一步,git checkout -b newBranch
 # 做一些代码修改
 git add .
 git commit -m "newBranchCommit"

通过分支图我们可以看到当前的分支结构如图所示

image-20210523183430019

可能不太明显,此时我们在master分支上再进行一次提交

image-20210523183717594

假设此时本期需求已经开发完成,需要将所有的分支合并,我们一共有两种方式来进行合并commit和rebase

此时大部分情况下会有冲突产生,即合并的两条分支的代码不一致(两人同时新增不同的代码),git会帮我们做出如下改动

image-20210523184146757

我们根据需要可以保留任意版本或者全部保留,然后添加暂存—>提交暂存

image-20210523184359258

再来看第二种方式rebase,我们先回滚到上一版本,使用命令git reset HEAD~1可以进行版本回滚,最后的数字代表要回滚的步数,不加数字默认为1步

rebase的原理就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

git rebase master

此时同样需要解决冲突,解决完成之后一样的添加暂存—>提交暂存,来看一下它与merge的区别

image-20210523190606337

在选定rebase目标之后,可以看见我们的分支多了一个REBASE-i,此时出现了冲突,我们需要在解决冲突之后提交一下,然后使用--continue命令来完成rebase,可以看见最后的REBASE-i已经没有了

它与merge的区别在于可以将分支线性化,不会产生纠缠不清的分支

image-20210523191057094

高级篇

你可能在之前的图片中看到 了HEAD这个指示,HEAD 总是指向当前分支上最近一次提交记录。如果想查看HEAD的指向,可以使用命令cat .git.HEAD来查看,其实就是读取.git隐藏文件夹中的文件

image-20210523202245858

如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD 查看它的指向

HEAD的意义就在于可以找到分支名无法指向的节点,使用分支名只能找到分支末端的节点

image-20210523202753820

再来看分支图,蓝色的小圆圈就是指代的当前HEAD,后面的hash值就是刚才我们切换的节点

image-20210523202843202

在使用hash值切换时不需要记住全部的hash,一般人也不会去记,只需要提供不会重复的前几位,Git就会帮我们自动完成。除此之外,还可以使用相对引用之前我们在版本回退的时候已经接触到了~,现在再来加一个^,比如我们当前在main分支上,我们可以使用git checkout master^来切换到master分支当前节点的父级结点,^可以叠加,如master^^代表master分支的父节点的父节点

image-20210523204526754

虽然^很方便,但是如果需要操作很多步,那也是很烦人的,所以~就用来简化操作,比如^^^等价于~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"

image-20210523215732739

移动提交记录

移动提交记录有两种方式,一种是cherry-pick另一种是我们前面的老同学rebase,我们先来看cherry-pick。cherry-pick可以指定版本号抓取提交记录到当前分支,比如下面的例子,我们将newBranch的提交记录抓取到master中

image-20210523233345459

使用命令git cherry-pick <提交版本号>,这里版本号就填红框后面的版本号(可以填多个,依次抓取到master上),效果如下

image-20210523233604342

再来看一下rebase的效果,添加-i(–interactive)命令,参数有两个起始版本号(不包括)和结束版本号(包括),或者也可以使用引用HEAD~4

git rebase -i startVer overVer
# 或者 git rebase -i HEAD~4

在键入命令后悔启动类似Vim的编辑器,如下

image-20210523234816316

上方会展示要合并的记录,每一行的第一个单词是一个指令,含义如下:

  • pick:保留该commit(缩写:p)

  • reword:保留该commit,但我需要修改该commit的注释(缩写:r)

  • edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)

  • squash:将该commit和前一个commit合并(缩写:s)

  • fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)

  • exec:执行shell命令(缩写:x)

  • drop:我要丢弃该commit(缩写:d)

注意现在的顺序

image-20210523235708305

我们将编辑器中的顺序调换为

image-20210524000026079

可以看到已经调换了两个提交记录的位置

image-20210524000059584

标记

在日常的发布中,我们现在大多使用的是CI/CD的流程,配置好打包脚本之后,只需要从git仓库拉取代码之后就可以自动打包发布了

使用tag命令来进行标识

git tag version1
git tag versino2 hashCode

可以直接打标识,也可以指定某一hash码来打标识

如果要查看已有的标识可以使用git tag -l命令来查看所有的分支,使用git describe --tags可以查看距离当前提交记录最近的一个tag

掌握了这些git技能已经可以满足日常的开发了,还需要了解一下远程的操作,这里就不多做说明了


前端小白