经过本文你能够了解到:

  • git 的起源
  • git 的根底知识
  • gitflow 流程的根本方法
  • 依据 git 的多种作业流

在讲 Git Flow 之前,咱们先讲讲其他东西

  • 什么是版别?
    版是指印刷时的版,本便是印刷出来的书本;版别是一种称谓,用于描绘同一事物的相互之间有差异的各种形式、状况或内容。
    换言之,任何事物只要有差异化都会触及到版别这个概念,可是,咱们这儿说的版别,包含后边聊到的东西,都应该是一些有意义的版别,举个例子,小明 1 月 1 日 至 1 月 31 日 每天都在改一份策划书,2 月 1 号小明的甲方说仍是上一个版别好,此刻对于小明来说,上一个版别是什么?也许是最近一次小明发给甲方的一个计划,也许是上一个甲方说还能够的计划,但小明可能现已不记得具体是几号改完给甲方的计划了。

  • 常见的版别操控有哪些?
    copy 文件以命名区分的方法、本编辑器的撤回/行进功用、运用专业工具如 svn、git 等等都归于版别操控的领域,不同的版别操控有不同的用途,比方文本编辑器的撤回,能够轻松撤销本次修改,比方 copy 文件,能够让新旧文件一起存在,便利对比,但这些方法过分简略了,而且中心进程都是一些暂时性的东西,不足以作为一个修改前史参考或许完好版别来看待,为此,还需求一些专业工具,如 集中式版别办理体系 SVN、CVS,分布式版别办理体系 BitKeeper、Git 等。

  • Git 开发背景

    同生活中的许多伟大事物相同,Git 诞生于一个极富纷争大举创新的时代。 Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护作业都花在了提交补丁和保存归档的繁琐业务上(1991-2002年间)。 到 2002 年,整个项目组开端启用一个专有的分布式版别操控体系 BitKeeper 来办理和维护代码。
    到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的协作联系结束,他们收回了 Linux 内核社区免费运用 BitKeeper 的权利。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)依据运用 BitKeeper 时的经验教训,开发出自己的版别体系。 他们对新的体系制订了若干方针:

    • 速度
    • 简略的规划
    • 对非线性开发形式的强力支持(答应不计其数个并行开发的分支)
    • 完全分布式
    • 有能力高效办理相似 Linux 内核相同的超大规模项目(速度和数据量) 自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的一起,依然保留着初期设定的方针。 它的速度飞快,极端合适办理大项目,有着令人难以置信的非线性分支办理体系(拜见 Git 分支)。
  • 1991 年 Linux 开发了 linux 体系这个开源项目,采用邮件发送源文件顺便patch的方法进行写作开发,由 Linux 自己进行手工兼并;

  • 2002 年 BitKeeper 与 Linux 社区达成协议,答应 Linux 社区免费试用 BitKeeper,因为免费试用,协议内容更多地是维护 BitKeeper 本身。

  • 2005 年 BitKeeper 不满 Linux 社区损坏协议内容(说白了便是反编译 BitKeeper,试图做破解版或其他),停止协作;

  • 同 2005 年,Linux 花费了 2 周时刻,开发了 Git 第一版,一个月内运用 Git 来办理 Linux 代码;

Git 根底知识

作业区(Workspace)、暂存区(Index)、版别库(Repository)

# 创立并进入 testGitFlow 目录
# 此刻 testGitFlow 便是咱们的作业区(Workspace),也便是作业目录

$ mkdir testGitFlow && cd testGitFlow

# 初始化 git 库房
# 此刻目录中添加了 .git 目录,.git 目录便是 git 库房,不归于作业区

$ git init

# 新增两个文件
$ echo 111 > a.txt
$ echo 222 > b.txt

# 添加两个文件到暂存区/索引(Index)
$ git add .

# 把索引中的两个文件添加到版别库(Repository)
$ git commit -m 'init'

以上触及的几个概念:
Workspace: 简略理解便是咱们的项目目录
Index: 简略理解便是存储即将提交的内容的区域
Repository: 版别库房

Commit、Tree、Blob 目标

# 经过 git log 检查版别
$ git log

>
commit 2b304a56998989dbcfd77f370f4b43fcad9e5872 (HEAD -> master)
Author: huihuipan <huihuipan163@163.com>
Date:   Mon Feb 27 17:56:53 2023 +0800
    init

# 经过 git cat-file 检查 commit 信息

# 检查 commit 类型
$ git cat-file -t 2b304a
> commit

# 检查 commit 内容
$ git cat-file -p 10d717

>
tree 4caaa1a9ae0b274fba9e3675f9ef071616e5b209
author huihuipan <huihuipan163@163.com> 1677491813 +0800
committer huihuipan <huihuipan163@163.com> 1677491813 +0800
init

# 能够发现有 tree, author, committer 等信息
# 继续检查 tree 内容
$ git cat-file -t 4caaa1
> tree

$ git cat-file -p 4caaa1
>
100644 blob 58c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c	a.txt
100644 blob c200906efd24ec5e783bee7f23b5d7c941b0c12c	b.txt

# 能够发现有 blob 信息
# 继续检查 blob 内容
$ git cat-file -t 58c9bd 
> blob

$ git cat-file -p 58c9bd 
> 111

# 能够看到里面存储的是 a.txt 的内容

以上触及的几个概念:
commit: commit 记载提交的版别
tree: tree 记载不同版别下的目录结构和文件名
blob: blob 记载文件内容

此刻咱们的 git 项目结构如下

Git的多种工作流

修改文件及提交 commit 的时产生了什么?

Git的多种工作流

  1. 首先,a.txt 内容 从 111 修改为 333,此刻 git 库房没有变化,仅仅作业区和索引的内容对不上了;
  2. 履行 git add 指令
    1. git 库房依据新的 a.txt 内容(333)创立出一个新的 blob 结点,记载 a.txt 内容
    2. 索引从旧 blob 的指向新的 blob
  3. 履行 git commit 指令
    1. 依据索引的状况,生成 tree 目标
    2. 依据新生成的 tree 目标和 上一个 commit 目标,生成新的 commit 目标
    3. 把分支指针从旧的 commit 目标移动到新的 commit 目标

HEAD、Branch、Tag

Branch: 是指向 Commit 的指针,每一次提交新的commit,当前的 Branch 都会指向最新的 commit;

HEAD: 指向 Branch 的指针,当checkout 到非 branch 时,会提示处于分离头指针状况,能够做一些试验性的动作;

Tag: 指向 Commit 的指针,用作标签,一般用作记载固定版别,也能够理解为是指定 commit 的别名;

以上咱们能够得知,git 的版别办理粒度去到了文件等级,blob 之间的对比即可得到 diff,这儿也引申出了一个开发上的一个思考,当咱们的程序规划的根底是一个比较小粒度的时候,后续开发和扩展就会愈加灵敏,事实上git 对commit 的操作也是十分灵敏,灵敏到稍不留意就有可能变成事端。

Checkout、Merge、Rebase、Fetch、Pull

checkout 检出: 把 HEAD 检出到指定 branch 或 commit,或许检出指定版别指定文件的内容,因为在 git 里面checkout 承载了太多的功用,一切切换分支有专属指令 switch

merge 兼并:

Git的多种工作流

rebase 变基:

Git的多种工作流

rebase 会修改版别前史,即使 rebase 前与 rebase 后的内容共同,但版别不再是同一个版别

fetch: 从另一个存储库下载目标和引用,如远程库

pull: git pull = fetch + merge

依据 Git 的几种作业流

Git Flow

Git的多种工作流

简介

出自 Vincent Driessen2010年写的一篇文章
《A successful Git branching model》

首要分支

Git的多种工作流

有两个分支会贯穿整个版别的生命周期,也便是长时间分支:

  • master 分支:用于发布
  • develop 分支:用于开发 master 分支和 develop 分支的联系如上,虚线部分指着两个分支并不是直接产生相关,而是经过 release/hotfix 分支产生相关

支撑分支

  • feature branches: 用于需求开发

Git的多种工作流

开发需求时从 develop 分支拉出 feature 分支,feature 分支开发结束后(开发自测无问题)则兼并回 develop 分支,兼并后删去分支,后续呈现 bug 则在 develop 分支修改。

  • release branches: 用于发布

Git的多种工作流

当 develop 分支处于一个相对安稳的状况时即可从 develop 分支拉出 release 分支准备发布,release 分支不进行功用开发,仅进行 bug 修正,直至无问题时兼并到 master 分支进行发布,一起兼并回 develop 分支后删去 release 分支。

  • hotfix branches: 用于修正生产问题

Git的多种工作流

hotfix 分支用于修正生产环境上急需修正的 bug, 当生产环境呈现 bug 时,从 master 分支拉出 hotfix 分支,修正后兼并回 master 分支进行发布,一起兼并到 develop 分支后删去。

最终回忆一下完好的 gitflow

Git的多种工作流

补充

2020年 Vincent Driessen 补充了一条反思笔记,大概说 Git Flow这种形式在继续交给的软件下显得杂乱,能够考虑运用 Github Flow 而不是将 Git Flow 硬塞到项目中。

Git Flow 之后 Adam Ruka 针对 Git Flow 的技术细节做了优化,提出了 One Flow

Github Flow

Git的多种工作流

相对于 Git FlowGithub Flow 只有一条主干分支,经过 github 平台加持添加 PR 流程: 进行某功用开发时,从 master 分支拉出 feature 分支,完成功用后提交 pr, 让相关人员进行 review, review 期间仍能够对 feature 进行提交,直至承认无问题后经过 pr, 能够把 feature 分支兼并到 master 分支进行发布

GitLab Flow

GitLab Flow 运用 master 分支作为开发分支,依据 master 分支另起发布分支 production
GitLab Flow 添加以下分支定义:
环境分支:当你需求在不同环境发布不同的版别时运用
发布分支:当项目需求发布不同的版别时运用,声明晰一个发布分支后,这个分支只会兼并严峻的缝隙修正更新。

继续发布

Git的多种工作流

gitlab-flow 引荐运用 master 分支进行开发,依据 master 分支另建 production 分支进行发布,另外提出了 环境分支的概念,依据不同环境,逐层兼并,最终汇总到 production 发布分支后进行发布

版别发布

Git的多种工作流

假如你的项目需求发布不同的版别, gitlab-flow 版别发布形式可能更合适,在继续发布形式下,不同的版别会有不同的发布分支进行发布。

Aone Flow

Git的多种工作流

Aone-flow 是以 master 分支为根底,除 master 分支外其他都是暂时分支。依据 master 分支拉出环境分支,环境分支之间不进行任何相关,独立发展,环境分支也不答应直接修改,而是经过兼并不同的 feature 分支进行组合。 feature 分支直至兼并到 发布分支后才会删去。有点是操作粒度更高更可控,缺点是环境分支的内容即使是相同的,但版别前史却有可能不共同。

怎样挑选版别操控

上面介绍了好几种 flow, 从 gitflow 开端,gitflow 让自由度超高的 git 得到了指导性的运用方法;
而 github-flow 又针对了 gitflow 的杂乱性提出了极简版的 flow;
gitlab-flow 又针对 gitflow 和 github-flow 过于杂乱或过于简略的方法,提出了自己折中的计划,一起还给出了两种交给方法(继续交给、版别交给)的计划;
最终也介绍了 AoneFlow,一种操作粒度更自由的计划。

其实没有一种万能计划,不同的团队/项目有着其特殊的状况,针对不同状况,flow 也在变化,合适的便是最好的。

最终

To conclude, always remember that panaceas don’t exist. Consider your own context. Don’t be hating. Decide for yourself.

引用 Vincent Driessen 的一句话:“最终,永久记住万能药不存在。考虑你自己的背景。不要厌烦。自己决定”

参考

  • Git 简史
  • git 的诞生 — 廖雪峰
  • git的宿世,和BitKeeper
  • A successful Git branching model
  • OneFlow – a Git branching model and workflow
  • GitHub Flow
  • GitLab Flow
  • Aone Flow
  • Git 作业流程 – 阮一峰
  • 分支的实质 – 智客工坊
  • 深化理解 git 兼并操作
  • git merge 的原理(递归三路兼并算法)
  • 关于Git rebase你必须要知道的几件事 – DevUI团队
  • Commit message 和 Change log 编写攻略 – 阮一峰
  • Git 兼并战略选项及示例
  • Git 工具 – 高级兼并
  • Git 可视化在线操练
  • Git内部原理揭秘 – 李泽帆