likes
comments
collection
share

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

作者站长头像
站长
· 阅读数 79

Git的常用操作及原理浅析

基础概念

三个分区

git中有三个分区,工作区版本库暂存区。我们可以把一个git托管的项目成两部分:

  • .git目录中保存了工程所有的commit节点和分支信息,我们把这部分叫做版本库
  • 其余部分是项目中的文件,我们将其叫做工作区,我们日常开发都是修改这些文件

版本库中有一个暂存区,它会保存当前被修改的文件,我们平时调用 git add .就是将工作区中修改的文件同步到暂存区,紧接着我们会调用 git commit暂存区的文件记录到当前分支中,他们之间的关系如下:

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

commit

git是通过commit来记录工程的每一个历史的版本,我们可以通过切换commit来回退到任意一个版本,看上去很神奇,那commit的本质是什么呢? 实际上,git会为每个文件创建一个blob对象(本质上也是一个文件),blob中保存着这个文件的二进制数据,通过SHA1算法计算出二进制数据的hash值作为该blob对象的索引(blob对象的文件名就是这个hash值) Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当我们运行git commit -m "xxx"时,如果有文件发生改变,就会创建新的blob对象,老版本的blob对象也会保留

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

接着,git还会创建一个commit对象,记录工作区中所有文件对应的blob对象。commit实际保存的是一串blob对象的索引,以此间接持有blob对象,而blob对象中保存着原始文件的数据,因此,我们就可以通过commit对象还原出工程中所有的文件。commit也会将其记录的内容用SHA1计算出hash值,作为索引

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

commit除了保存blob对象的索引,还保存了上一个commit的索引,这样就形成了一个类似链表的结构,我们可以追溯到当前commit之上的任意一个版本。除此之外,commit对象还保存了提交信息,作者信息等数据 Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

这里只是大致阐述了下原理,实际情况要稍微复杂些,具体可以参考:GIT对象模型

branch

branchgit的主要功能之一,方便团队管理项目,并行开发不同的需求。 git允许我们随意的创建分支,并能够快速的在分支间切换,仿佛没有任何性能开销。实际上,我们可以将branch看做是一个指针,指向某一个commit

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当我们创建新的commit时,branch会自动指向新建的commit Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

本文的git操作演示是基于学习 Git 分支

通过上文我们了解到,commit是一个类似链表的结构,因此我们可以把branch回退到任意一个历史版本

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

多个commit可能会有同一个父节点(例如基于develop分支创建多个feature分支协同开发),一个commit也可能会有多个父节点(通常是因为用merge合并分支),所以当多个分支交织在一起时,commit构成了一个网状结构,而不是一条链。这里需要注意,网状结构是自下而上的,一个commit只知道他的父节点而不知道它有哪些子节点

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

HEAD

一个工程中会同时存在多个分支,那么我们是如何知道当前处于哪个分支下呢?在git中,有一个特殊的指针HEAD,它往往指向某一个branch,不同于branch指针,HEAD指针全局只有一个,他最终会指向一个commit,我们当前工作区的文件都来源于这个commit

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当我们切换分支时,HEAD指针指向了另一个branch指针,从而间接引用到另一个commit,使工作区的文件发生了变化

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

HEAD也可以直接指向一个commit,此时的分支处于detach状态,如果创建新的commit则不属于任何一个分支

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

TAG

当项目要发布时,我们通常会基于当前commit创建一个TAG,用于标记要发布的版本。其实TAG本质上也是一个指针,指向一个commitTAG内包含TAG名和commit索引

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

不同于branch指针创建后可以重新指向任何commitTAG创建后始终指向一个commit,相当于锚定了commit网络中的一个节点

git命令

通常情况下,git命令有一个固定的模式:

git subcommand [options] hash|ref
  • 这里的subcommand表示子命令,如checkoutreset, merge, rebase等(我们接下来会提到这些命令)
  • options是一些可选参数,不同的子命令会有一些独有的参数,提供了一些额外的控制能力。例如git checkout -b dev-b选项意味着先创建dev分支,再把HEAD指向dev,不指定此选项则不会有创建分支的行为
  • 在命令的末尾,指定要针对哪一个commit进行操作。定位一个commit可以用它的hash值索引(完整的hash值有41位,我们只用前几位就可以),也可以通过branchHEADTAG等指向commit的指针来定位commit,我们可称之为引用

引用有两个特殊的操作符,可以用相对位置的方式来定位历史节点。这里我们以main分支为例,main指向commit c2

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

  • main^表示c2的父节点,即commit c1
  • main~n表示c2之上的第n个父节点,例如main~2commit c0

常用操作

checkout

通过上文我们了解到,当前工作区中的文件来源于HEAD指向的commit。我们可以通过checkout命令来改变HEAD指向的commit,从而将工作区中的文件回溯到对应的历史版本 当运行git checkout c0HEAD会指向hash值为c0commit(为了简化我们只取两位hash值作为commit的标识)

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当运行git checkout mainHEAD会指向main分支(图中当HEAD指向某个分支时,会在分支名右侧出现*),这就是git切换分支时执行的操作

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当运行git checkout dev^HEAD会指向commit c1

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当运行git checkout dev~2HEAD会指向commit c0

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

撤销

reset

有时候出于某些原因,我们需要撤销最近的commit修改,从而将工程回退到之前的版本,这时可以用reset命令 reset本质上是让当前分支(HEAD指向的分支)指向其他的commit,当运行git reset c0dev分支会指向commit c0,从而让工程回退到c0的版本

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

这里我们需要注意,虽然项目回退到了c0,但这并不意味这c1c2节点被删除,reset仅仅只是改变了branch指向的commit,原来的commit依然存在

revert

reset虽然很好用,但是存在两个问题:

  • 我们无法感知到项目发生过回退
  • 无法只还原历史中某个commit的改动

针对上述两种情况,我们可以使用revert。当我们想还原commit c0的改动,运行git revert c0

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

通过动画演示我们可以看出,revert本质上做了两件事:

  • 自动生成commit c0’,用于还原commit c0中的改动
  • 将当前分支指向commig c0‘

执行完revert命令后,我们能够从提交历史中看出项目曾经发生过回退,这便于我们日后追踪工程文件的变动

合并

merge

在团队协同开发的过程中,我们常常基于一个分支(通常基于develop分支或main分支)来创建新分支,用来开发新功能,不同的人开发不同的模块,最终把所有的分支合并到一起 我们最常见的合并分支命令是merge。举个例子,假设有两个分支mainfeat1,他们有一个公共commit节点c1,且当前分支是main

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当执行git merge feat1

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

merge会创建一个新的commit节点c4并将main分支指向它。mainfeat1有一个公共祖先节点c1merge命令会自动比较自c1之后两个分支的修改,来决定c4采用哪个commit中的改动

举例来说,假设c1中有三个文件a.txtb.txtc.txtcommit c2修改了a.txtcommit c3修改了a.txtb.txtmerge命令会比较c2c3与其公共祖先节点c1的差异,发现c.txtc2c3中都没有发生过改动,所以在生成的commit c4内直接复用c1中的c.txtb.txt在只在c3中发生了改动,因此c4会使用c3中修改的b.txtc2c3都修改了a.txt,因此无法自动决定使用哪个版本,git会让我们手动解决冲突,之后生成新的blob对象来保存合并冲突后的a.txtc4会引用这个新版本的a.txt

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

这里只列举了merge中最常见的情况,还存在一些较为复杂的场景,merge也提供了一些参数让我们控制合并的策略,具体内容可以参考:git合并原理

rebase

除了merge外,我们还可以用rebase来合并分支。我们继续使用上面的例子,执行git rebase feat1

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

rebase执行的操作可以拆分三步:

  • 查找公共祖先节点(在本例中为c1
  • 复制当前分支自公共祖先节点之后的所有commit(本例中创建commit c3'来复制c3),把它们移动到要合并的分支的后面(本例中把c3'的父节点改为c2
  • main分支指向最后一个复制的commit(本例中将main分支指向c3'

类似merge,如果两个分支都修改了同一个文件,则需要手动合并冲突,解决冲突后的文件会包含在被复制的那些commit中。执行rebase后,main分支当前commit的父节点由c1变成了c2,相当于重新改变了基底,这也是re-base这一名称的含义。同时整个分枝树是一条没有分叉的链,相比较与merge更加简洁,缺点是无法从提交记录中看出分支发生了合并

整理提交记录

cherry pick

有时候出于某些原因,我们需要把其他分支的某几个commit合并到当前分支中,这时可以使用cherry pick指令,当执行git cherry-pick c2 c3

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

顾名思义,cherry pick让我们像“挑选樱桃”那样选出几个我们想要合并的commit(本例中我们挑选了c2c3),git会复制这些选中的commit(创建c2'来复制c2,创建c3'来复制c3)并将它们依次移动到当前分支之后(合并前main分支指向c4,先将c2'的父节点改为c4,再将c3'的父节点改为c2'),同时将当前分支指向最后一个复制的commitmain分支最终指向c3'

交互式rebase

某些情况下,我们想要把多个连续的commit压缩成一个,或者想要调整前几个commit的顺序,像这种修改提交历史的操作,我们可以用交互式rebase来实现。前面我们提到如何用rebase合并分支,交互式rebase就是添加-i参数,我们通常用它来修改当前分支的提交记录。假设我们想移除倒数第二个commit,运行git rebase -i HEAD~2

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

注:这里只是用动画的方式来演示交互式rebase,真实的情况需要用VIM编辑器来操作

从演示动画可以看出,rebase复制了我们选择留下的commit(本例中我们选择只留下c2, git创建c2'来复制c2),然后将第一个复制的commit指向公共祖先节点(将c2'指向c0),最后将当前分支指向最后一个复制的commitmain分支最终指向c2') 交互式rebase还有很多处理commit的操作:

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

上面的例子中我们使用了pickdrop命令,常用的还有squash命令,用来把多个commit压缩成一个,这里我们就不一一细说了

查看Tag

我们常常用TAG来标记要发布版本的commit,有时候需要查看最近一个TAG的信息来确认当前的版本号(ci脚本中经常会有这个需求),可以用describe命令来查看距离指定的引用commit最近的tag信息,返回结构:tag_num_hash,tag是TAG名,num为当前commit节点距离此tag的提交数,hash为当前引用指向的commit节点索引,举例来说:

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

当运行git describe会得到v1.0.0_2_gC3,代表离HEAD最近的TAGv1.0.0HEAD与之相差两个提交且HEAD指向c3。当运行git describe main时得到结果v1.0.0_1_gC2,这里就留给大家思考其含义

远程仓库

在工作中,我们会有一个远程仓库来存放我们的代码,所有开发人员都会clone这个仓库到本地,并在本地修改好代码后再推送到远程仓库。那远程仓库跟本地仓库的关系是怎样的呢?

远端

git中有一个概念叫做远端,它代表与本地仓库关联的远程仓库,我们可以用remote命令添加多个远端,每个远端都有自己的名称,代表一个远程仓库。假设我们的远程仓库有三个分支:mainfeat1feat2,当执行clone命令后,我们会在本地创建一个git仓库(假设左侧为本地仓库,右侧为远程仓库):

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

在本地仓库中,git会默认创建一个名叫origin的远端,代表我们复制的远程仓库(这里我们简写为o

远程分支和上游分支

clone完成时,我们的本地仓库实际上有两种分支,远程分支(remote branch,也被叫做remote tracking branch)和本地分支(local branch)。远程分支会关联到远程仓库中的某一个分支,我们把它叫做上游分支(upstream branch),他们之间的关系如下:

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

远程分支的结构为<remote_name>/<feature_name>,例如o/main,意味着它会追踪远端omain分支(即上游分支main),上游分支main发生的改动会同步到远程分支main(下一节会详细讲到)

本地分支可能会关联一个远程分支,例如本地仓库中的main,它是clone后自动创建,关联远程分支o/main,如果此时我们checkout本地分支main,我们可以感知到它关联了远端o中的main分支(即上游分支main

这里需要注意,我们可以基于远程分支来创建新的本地分支,但不可以直接在远程分支上创建commit。实际上,如果你运行checkout命令切换到远程分支,会自动进入detach模式(HEAD直接指向commit而不是branch

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

这里我们执行了git checkout o/feat1HEAD指针直接指向commit c3,如果此时我们修改代码并执行git commit,会创建一个新的commit并指向c3HEAD会指向这个新的commit,而o/feat1依然指向c3

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

这意味着我们无法修改o/feat1,它对我们来说是“只读”的,因为远程分支上游分支关联,只有上游分支的改动才会影响到远程分支,维护了本地仓库远程仓库的一致性

拉取

fetch

远程分支保存在本地仓库,当远程仓库更新时,远程分支并不会自动更新,我们需要使用fetch命令来同步远端的修改,执行git fetch

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

从演示中可以看出,fetch会先将远程仓库中新增的commit复制到本地仓库,然后将远程分支指向最新的commit,这里将o/main指向了c3,使得o/main远程仓库中的main看起来一模一样。这里需要注意,fetch并不会修改本地分支,比如本地仓库中的main依然指向c1,如果我们想要更新本地分支需要手动合并远程分支,这看起来很麻烦,我们可以用pull来代替fetch

pull

pull命令可以拆分成两步:

  • fetch同步远程仓库
  • 远程分支合并到本地分支

上文我们提到了两种合并分支的方式,mergerebasepull允许我们指定用哪一种方式来合并远程分支。假如我们在本地分支创建了commit c2远程仓库此时也新增了commit c3,执行git pull,效果等同于fetch + merge

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

执行git pull -r,效果等同于fetch + rebase

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

实际上,完整的pull命令如下: git pull [<options>] [<repository> [<refspec>...]] options通常用来指定合并分支的行为,例如之前我们使用的-r,指定用rebase合并

repository指定从哪个远端拉取代码,我们之前的例子从未设置过此参数,因为当前分支是main关联了远程分支o/main,所以此时的repository远端o

refspec的结构是src:destsrc告诉我们拉取远端的哪个分支dest表示同步到本地仓库的哪个分支。在之前的例子中,当前分支main关联了远程分支o/maino/main追踪了上游分支main,因此这里可以省略refspec参数,git会将上游分支main同步到o/main。如果当前分支不存在关联的远程分支,我们需要指定refspec参数。举个例子,假设当前分支dev没有任何关联的远程分支,我们想要将上游分支main同步到本地分支main,可以运行git pull origin main:main

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

从演示中我们看出,git上游分支main新增的commit c2同步到了本地分支main,并将它合并到当前分支dev,而远端分支o/main并没有发生改变。这里要注意,refspect中的dest分支必须是src分支的某一个历史版本(就像远程分支上游分支的关系),否则无法执行同步操作(同步操作类似更新而不是合并)。dest也不能是当前分支,我们之前提到,pull命令是fetch+合并分支,如果dest就是当前分支,那么在fetch完成后无法将自己合并到自己,这从逻辑上就说不通

推送

当我们修改了本地分支后,使用push指令将本地的改动推送给远端。假设远程仓库有一个main分支,本地仓库main分支基于远程分支 o/main,并创建了c2c3两个commit,执行git push

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

本地仓库中,通过对比本地分支和与之关联的远程分支,计算出都新增了哪些commit,将这些commit同步到远程仓库上游分支,最后将远程分支指向最新的commit。在本例中,发现本地分支main新增了c2c3,于是将它们推送到上游分支main,最后将o/main指向了c3

这里有一个问题需要注意,如果本地仓库落后于远程仓库(即远程仓库有了新的改动,但本地仓库中的远程分支并没有同步),这时候执行push会操作失败,git警告我们要先同步远程仓库的改动,这个时候我们要先使用pull来拉取远程仓库的改动,然后才能执行push

举个例子,假设在本地仓库中,远程分支o/main指向c1main基于o/main创造了commit c2,这时远程仓库中的main新增了commit c3,我们要先执行git pull --rebaserebase会让你的分支树看起来更整洁),这时本地分支main看起来像是在远程分支main之上添加了commit c2,现在我们可以执行git pushc2同步到远程仓库main分支中

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

push命令的结构类似pull,假如当前分支有关联的远程分支,可以省略repositoryrefspec(之前例子里,main分支关联了o/main),否则需要指定这两个参数。举个例子,假设当前分支是feat1,它并没有关联任何远程分支,我们要将它推送到远端dev,可以执行git push origin feat1:dev

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

从演示动画可以看出,git本地分支feat1指向的commit c3同步到了上游分支dev,然后更新远程分支o/dev,让其指向c3 如果我们要推送的本地分支并没有关联的上游分支git会自动创建相应的上游分支远程分支,并关联被推送的本地分支。举例来说,假如当前分支feat没有关联任何远程分支远程仓库中也不存在名叫feat分支,执行git push

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

git自动创建了上游分支feat远程分支o/feat,并将本地分支关联了o/feat

关联远程分支

从前两个小节中我们可以发现,本地分支如果有关联的远程分支,在执行pullpush的时候会很方便。我们可以创建新的本地分支来关联远程分支,假设本地仓库有一个远程分支o/main,执行git checkout -b feat o/main

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

我们新建了一个名叫feat本地分支并关联了远程分支o/main,然后在feat分支上创建commit c2,最后直接执行git push,可以看出,我们新建的commit c2直接被推送到了上游分支main,远程分支o/main也更新到commit c2的位置 我们也可以为已有的本地分支设置关联的远程分支,通过执行git branch -u o/main feat1,给本地分支feat1关联了远程分支o/main,接下来就可以像上面的例子一样,使用默认的参数来执行push命令,这里就不详细赘述了

git工作流

在团队的日常工作中,我们遇到多种开发场景,包括:协同开发新特性,发布版本,修复线上bug等,大家都往一个git仓库中提交代码,如果没有协作规范(也就是git工作流),那将是一场灾难。下面我简单介绍一下业界常用的三种git工作流

git flow

git flow采用严格的分支管理策略,适用于周期性发布的项目,我们在项目开发中就是采用git flow工作模式,它是最早提出的一种git工作流程,覆盖了开发新特性,bug追踪,版本发布等场景,结构如下:

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

  • master:保持在发布状态,打tag记录版本
  • develop:日常开发,所有的提交最终都要合并到这里
  • feature:开发新特性,基于develop,开发完成最终要合并到develop
  • hotfix:修复bug,基于main,修复完后合并到main并打tag升级版本号,也要合并到develop
  • release:用于发布版本,当新特性开发完成并合并到develop后,基于develop创建release分支,后续跟此版本相关的commit全部提交到此分支,当版本稳定后,合并到main分支发版,打tag记录版本号,也要合并到develop

详情参考Gitflow Workflow

github flow

main始终保持在发布状态,轻量,适用于频繁部署的项目

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

  • 基于main创建新分支(新特性,bug修复,重构等,全部基于main),分支名要具有描述性
  • 修改,提交
  • 同步代码,提交pull request
  • code review
  • 合并到main
  • deploy

详情参考Understanding the GitHub flow

gitlab flow

频繁部署的项目

适用于前端或后台项目,认为feature分支合并到main分支后即可发布,分支合并后可自动部署

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

开发新特性:

  • 基于master创建feature分支,开发新特性
  • 新特性开发完毕,提交merge request,合并到main
  • code review后合并到main
  • 将main分支合并到production分支,自动发布
  • 删除feature分支

修改bug:

  • 基于master创建bugfix分支,修改bug
  • bug修复完毕后提交merge request,合并到main
  • code review后合并到main,如果先合并到production,很可能忘记合并到main,导致后续发布还是会存在此bug
  • 将bugfix的修改cherry-pick到production分支
  • 删除bugfix分支

还有一个变种,适用于多个环境的发布: Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

  • pre-production是用来同步main分支修改的环境,可以叫其他名字
  • 部署pre-production需要创建merge request将main合并到pre-production
  • 上线时将pre-production合并到production
  • 合并顺序是从上游到下游

周期性发布的项目

适用于移动端,桌面软件项目,很多开源项目都采用这种协作模式

Git的常用操作及原理浅析Git的常用操作及原理浅析 基础概念 三个分区 git中有三个分区,工作区,版本库,暂存区。我

  • 根据master开发新特性
  • 新特性开发完后,创建release分支,分支名包含小版本号
  • bugfix分支修复了release分支的bug,先合并到main,再cherry pick到release分支,这样确保之后开发的新特性的分支一定修复了此bug
  • 每个发布的版本都维护有一个分支,不用在main上打tag,更快定位历史发布版本

详情参考Introduction to GitLab Flow

总结

本文从原理层面介绍了git中一些核心概念,并介绍了一些常用操作,以及底层的含义(这里强烈建议大家在 学习git分支 上动手操作一下),最后简略的介绍了几种常见的git工作流,如果有不足之处还请大家指正,希望本文能对大家有所帮助

转载自:https://juejin.cn/post/7126528295046381581
评论
请登录