当前位置:首页 > 科技  > 软件

深入理解Babel - 项目管理工具Lerna解析

来源: 责编: 时间:2024-05-30 17:19:02 120观看
导读一、背景Babel是一个比较庞大的项目,其子工程就有至少140个(如 babel/plugins/presets/lerna/babel-loader等),产出的子工具已经是前端开发的基础设施,对开发效率、代码质量等有非常高的要求。在本文中,我们将了解Babel是

一、背景

Babel是一个比较庞大的项目,其子工程就有至少140个(如 babel/plugins/presets/lerna/babel-loader等),产出的子工具已经是前端开发的基础设施,对开发效率、代码质量等有非常高的要求。0Ft28资讯网——每日最新资讯28at.com

在本文中,我们将了解Babel是怎样进行项目管理的。0Ft28资讯网——每日最新资讯28at.com

图片图片0Ft28资讯网——每日最新资讯28at.com

本文从工程管理、代码管理、文档管理、质量管理四个方面对Babel项目管理进行拆解分析。0Ft28资讯网——每日最新资讯28at.com

工程管理

Babel是典型的monorepo项目,即单仓库项目,所有的子模块在同一个仓库里。Babel目前有140+个子模块,在工程管理部分,需要解决以下问题:0Ft28资讯网——每日最新资讯28at.com

  • 模块间如何方便地互相关联进行本地开发;
  • 整个项目的版本控制;
  • 操作自动化。

工程管理部分主要使用lerna、yarn等工具。0Ft28资讯网——每日最新资讯28at.com

代码风格

Babel是多人协作开发的开源项目,如何保证代码风格一致,Babel使用的是社区常见的解决方案。0Ft28资讯网——每日最新资讯28at.com

该模块主要使用eslint、prettier等工具。0Ft28资讯网——每日最新资讯28at.com

文档

Babel的迭代速度很快、涉及的模块很多,该模块解决版本发布后如何自动更新相关文档等问题。0Ft28资讯网——每日最新资讯28at.com

该模块主要使用lerna等工具。0Ft28资讯网——每日最新资讯28at.com

质量控制

Babel的产品是前端开发的基础设施,该模块主要保证Babel的产出是高质量的。0Ft28资讯网——每日最新资讯28at.com

该模块主要使用jest、git blame等工具。0Ft28资讯网——每日最新资讯28at.com

二、monorepo

Babel使用monorepo模式进行工程管理。0Ft28资讯网——每日最新资讯28at.com

什么是monorepo

monorepo(monolithic repository),指的是单仓库代码,将多个项目代码存储在一个仓库里。另外有一种模式是multirepo,指的是多仓库代码(one-repository-per-module),不同的项目分布在不同的仓库里。React、Babel、Jest、Vue、Angular均采用monorepo进行项目管理。0Ft28资讯网——每日最新资讯28at.com

典型的monorepo结构是:0Ft28资讯网——每日最新资讯28at.com

├── packages|   ├── pkg1|   |   ├── package.json|   ├── pkg2|   |   ├── package.json├── package.json

这是Babel源码的目录结构:0Ft28资讯网——每日最新资讯28at.com

├─ lerna.json├─ package.json└─ packages/ # 这里将存放所有子项目目录    ├─ README.md    ├─ babel-cli    ├─ babel-code-frame    ├─ babel-compat-data    ├─ babel-core    ├─ babel-generator    ├─ babel-helper-annotate-as-pure    ├─ babel-helper-builder-binary-assignment-operator-visitor    ├─ babel-helper-builder-react-jsx    ├─ ...

而rollup则采取了multirepo的模式:0Ft28资讯网——每日最新资讯28at.com

├─ rollup    ├─ package.json    ├─ ...├─ plugins    ├─ package.json    ├─ ...├─ awesome    ├─ package.json    ├─ ...├─ rollup-starter-lib    ├─ package.json    ├─ ...├─ rollup-plugin-babel    ├─ package.json    ├─ ...├─ rollup-plugin-commonjs    ├─ package.json    ├─ ...

monorepo的优缺点

优点

  • 便捷的代码复用与依赖管理当所有项目代码都在一个工程里,抽离可复用的代码就十分容易了。并且抽离后,如果复用的代码有改动,可以通过一些工具,快速定位受影响的子工程,进而做到子工程的版本控制。
  • 便捷的代码重构通过一些工具,monorepo项目中的代码改动可以快速地定位出代码变更的影响范围,对整个工程进行快速的整体测试。而如果子工程分散在不同的工程分支里的话,通用代码的重构将难以触达各个子工程。
  • 倡导开放、共享monorepo项目中,开发者可以方便地看到所有子工程,这样响应了"开放、共享"的组织文化。可以激发开发者对工程质量等维护的热情(毕竟别人看不到自己的代码,乱不乱就看自己心情了),有助于团队建立良好的技术氛围。

缺点

  • 复杂的权限管理因为所有子工程集中在一个工程里,某些子工程如果不希望对外展示的话,monorepo的权限管理就比较难以实现了,难以锁定目标工程做独立的代码权限管理。
  • 较高的熟悉成本相对于multirepo,monorepo涉及各种子工程、通用依赖等,新的开发者在理解整个项目时,可能需要了解较多的信息才能入手,如通用依赖代码、各子工程功能。
  • 较大的工程体积很明显,所有子工程集成在一个工程里,代码体积会非常大,对文件存储系统等提出了较高的要求。
  • 较高的质量风险成也萧何败萧何,monorepo提供了便捷的代码复用能力,同时,一个公用模块的某个版本有bug的话,很容易影响所有用到它的子工程。此时,做好高覆盖率的单元测试就比较重要了。

选择

multirepo和monorepo是两种不同的理念。0Ft28资讯网——每日最新资讯28at.com

multirepo允许多元化发展,每个模块独立实现自己的构建、单元测试、依赖管理等。monorepo抹平了模块间的很多差异,通过集中管理和高度集成化的工具,减少开发和沟通时的成本。monorepo最大的问题可能就是不能管理占用空间太大的项目了。0Ft28资讯网——每日最新资讯28at.com

所以,还是要根据项目的实际需求出发选择用哪种项目管理模式。0Ft28资讯网——每日最新资讯28at.com

三、lerna

lerna是基于git/npm/yarn等的工作流提效工具,用于维护monorepo。它是Babel 开发过程中提升开发效率产出的工具。0Ft28资讯网——每日最新资讯28at.com

lerna本身也是一个monorepo的项目,并且,lerna为monorepo项目提供了如下支持:0Ft28资讯网——每日最新资讯28at.com

  • 项目管理

lerna提供了一系列命令用于monorepo项目初始化、添加子项目、查看项目信息等。0Ft28资讯网——每日最新资讯28at.com

  • 依赖管理

lerna支持为monorepo项目统一管理公共依赖、自动安装各个子项目的依赖、自动创建子模块符号链接等。0Ft28资讯网——每日最新资讯28at.com

  • 版本管理

lerna可以根据项目代码的变动情况,发现影响的子项目范围,在发布时提供语义化版本推荐等,极大提升了monorepo项目的版本管理效率。0Ft28资讯网——每日最新资讯28at.com

lerna命令集

命令行列表

lerna官网有对各种命令各种用法的详细介绍,这些命令可以分为:项目管理、依赖管理、版本管理三大类。0Ft28资讯网——每日最新资讯28at.com

图片图片0Ft28资讯网——每日最新资讯28at.com

全局配置项

lerna有一批通用参数,所有子命令均可以使用。0Ft28资讯网——每日最新资讯28at.com

--concurrency0Ft28资讯网——每日最新资讯28at.com

当lerna将任务并行执行时,需要使用多少线程(默认为逻辑CPU内核数)。0Ft28资讯网——每日最新资讯28at.com

lerna publish --concurrency 1

--loglevel<silent|error|warn|success|info|verbose|silly>0Ft28资讯网——每日最新资讯28at.com

要报告什么级别的日志。如果失败,所有日志都写到当前工作目录中的lerna-debug.log中。0Ft28资讯网——每日最新资讯28at.com

任何高于该设置的日志都会显示出来。默认值是"info"。0Ft28资讯网——每日最新资讯28at.com

--max-buffer<bytes>0Ft28资讯网——每日最新资讯28at.com

为每个底层进程调用设置的最大缓冲区长度。例如,当有人希望在运行lerna import的同时导入包含大量提交的仓库时,就是它出场的时候了。在这种情况下,内置的缓冲区长度可能不够。0Ft28资讯网——每日最新资讯28at.com

--no-progress0Ft28资讯网——每日最新资讯28at.com

禁用进度条。在CLI环境中总是这样。0Ft28资讯网——每日最新资讯28at.com

--no-sort0Ft28资讯网——每日最新资讯28at.com

默认情况下,所有任务都按照拓扑排序的顺序在包上执行,以尊重所讨论的包的依赖关系。在不保证lerna调用一致的情况下,以最努力的方式打破循环。0Ft28资讯网——每日最新资讯28at.com

如果只有少量的包有许多依赖项,或者某些包执行的时间长得不成比例,拓扑排序可能会导致并发瓶颈。--no-sort配置项禁用排序,而是以最大并发的任意顺序执行任务。0Ft28资讯网——每日最新资讯28at.com

如果您运行多个watch命令,该配置项也会有所帮助。因为lerna run将按照拓扑排序的顺序执行命令,所以在继续执行之前可能会等待某个命令。当您运行"watch"命令时会阻塞执行,因为他们通常不会结束。0Ft28资讯网——每日最新资讯28at.com

--reject-cycles0Ft28资讯网——每日最新资讯28at.com

如果(在bootstrap、exec、publish或run中)发现循环,则立即失败。0Ft28资讯网——每日最新资讯28at.com

lerna bootstrap --reject-cycles

过滤器参数

--scope<glob>

只包含名称与给定通配符匹配的包。0Ft28资讯网——每日最新资讯28at.com

lerna exec --scope my-component -- ls -la     lerna run --scope toolbar-* test     lerna run --scope package-1 --scope *-2 lint

--ignore<glob>

排除名称与给定通配符匹配的包。0Ft28资讯网——每日最新资讯28at.com

lerna exec --ignore package-{1,2,5}  -- ls -la     lerna run --ignore package-1  test     lerna run --ignore package-@(1|2) --ignore package-3 lint

--no-private

排除私有的包。默认情况下是包含它们的。0Ft28资讯网——每日最新资讯28at.com

--since [ref]

只包含自指定ref以来已经改变的包。如果没有传递ref,它默认为最近的标记。0Ft28资讯网——每日最新资讯28at.com

# 列出自最新标记以来发生变化的包的内容    $ lerna exec --since -- ls -la    # 为自“master”以来所有发生更改的包运行测试    $ lerna run test --since master    # 列出自“某个分支”以来发生变化的所有包    $ lerna ls --since some-branch

在CI中使用时,如果您可以获得PR将要进入的目标分支,那么它将特别有用,因为您可以将其作为--since配置项的ref。这对于进入master和feature分支的PR来说很有效。0Ft28资讯网——每日最新资讯28at.com

--exclude-dependents

当使用--since运行命令时,排除所有传递的被依赖项,覆盖默认的“changed”算法。0Ft28资讯网——每日最新资讯28at.com

如果没有--since该参数时无效的,会抛出错误。0Ft28资讯网——每日最新资讯28at.com

--include-dependents

在运行命令时包括所有传递的被依赖项,无视--scope、--ignore或--since。0Ft28资讯网——每日最新资讯28at.com

--include-dependencies

在运行命令时包括所有传递依赖项,无视--scope、--ignore或--since。0Ft28资讯网——每日最新资讯28at.com

与接受--scope(bootstrap、clean、ls、run、exec)的任何命令组合使用。确保对任何作用域的包(通过--scope或--ignore)的所有依赖项(和dev依赖项)也进行操作。0Ft28资讯网——每日最新资讯28at.com

注意:这将会覆盖--scope和--ignore。0Ft28资讯网——每日最新资讯28at.com

例如,如果一个匹配了--ignore的包被另一个正在引导的包所以来,那么它仍会照常工作。0Ft28资讯网——每日最新资讯28at.com

当您想要“设置”一个依赖于其他正在设置的包其中的一个包时,这是非常有用的。0Ft28资讯网——每日最新资讯28at.com

lerna bootstrap --scope my-component --include-dependencies     # my-component 及其所有依赖项将被引导
lerna bootstrap --scope "package-*" --ignore "package-util-*" --include-dependencies     # 所有匹配 "package-util-*" 的包将被忽略,除非它们依赖于名称匹配 "package-*" 的包

--include-merged-tags

lerna exec --since --include-merged-tags -- ls -la

在使用--since命令时,它包含来自合并分支的标记。这只有在从feature分支进行大量发布时才有用,通常情况下不推荐这样做。0Ft28资讯网——每日最新资讯28at.com

lerna原理解析

文件结构

以下是lerna的主要目录结构(省略了一些文件和文件夹):0Ft28资讯网——每日最新资讯28at.com

lerna├─ CHANGELOG.md -- 更新日志├─ README.md -- 文档├─ commands -- 核心子模块├─ core -- 核心子模块├─ utils -- 核心子模块├─ lerna.json -- lerna 配置文件├─ package-lock.json -- 依赖声明├─ package.json -- 依赖声明├─ scripts -- 内置脚本└─ yarn.lock -- 依赖声明

有趣的是,lerna本身也是用lerna进行开发管理的。它是一个monorepo项目,其各个子项目分布在lerna/commands/*、core/*、utils/*目录下。0Ft28资讯网——每日最新资讯28at.com

另外,在源码中,经常会看到名称为@lerna/command的子项目,如lerna/core/lerna/index.js的内容是:0Ft28资讯网——每日最新资讯28at.com

const cli = require("@lerna/cli");const addCmd = require("@lerna/add/command");const bootstrapCmd = require("@lerna/bootstrap/command");const changedCmd = require("@lerna/changed/command");const cleanCmd = require("@lerna/clean/command");const createCmd = require("@lerna/create/command");const diffCmd = require("@lerna/diff/command");const execCmd = require("@lerna/exec/command");const importCmd = require("@lerna/import/command");const infoCmd = require("@lerna/info/command");const initCmd = require("@lerna/init/command");const linkCmd = require("@lerna/link/command");const listCmd = require("@lerna/list/command");const publishCmd = require("@lerna/publish/command");const runCmd = require("@lerna/run/command");const versionCmd = require("@lerna/version/command");

这些子项目分布在lerna/commands/*、core/*、utils/*下,截至本文截稿时,lerna有61个子项目。0Ft28资讯网——每日最新资讯28at.com

以下是各子项目分布:0Ft28资讯网——每日最新资讯28at.com

图片图片0Ft28资讯网——每日最新资讯28at.com

命令行注册

lerna命令注册工作集中在lerna/core/lerna/*路径下。0Ft28资讯网——每日最新资讯28at.com

lerna/core/lerna/package.json0Ft28资讯网——每日最新资讯28at.com

该文件的bin字段定义了lerna命令:0Ft28资讯网——每日最新资讯28at.com

"bin": {             "lerna": "cli.js"     }

lerna/core/lerna/cli.js0Ft28资讯网——每日最新资讯28at.com

该文件描述了命令行的执行入口:0Ft28资讯网——每日最新资讯28at.com

#!/usr/bin/env node    "use strict";    /* eslint-disable import/no-dynamic-require, global-require */    const importLocal = require("import-local");    if (importLocal(__filename)) {        require("npmlog").info("cli", "using local version of lerna");    } else {        require(".")(process.argv.slice(2));    }

lerna/core/lerna/index.js

该文件为命令行引入了所有lerna指令:0Ft28资讯网——每日最新资讯28at.com

"use strict";const cli = require("@lerna/cli");const addCmd = require("@lerna/add/command");const bootstrapCmd = require("@lerna/bootstrap/command");const changedCmd = require("@lerna/changed/command");const cleanCmd = require("@lerna/clean/command");const createCmd = require("@lerna/create/command");const diffCmd = require("@lerna/diff/command");const execCmd = require("@lerna/exec/command");const importCmd = require("@lerna/import/command");const infoCmd = require("@lerna/info/command");const initCmd = require("@lerna/init/command");const linkCmd = require("@lerna/link/command");const listCmd = require("@lerna/list/command");const publishCmd = require("@lerna/publish/command");const runCmd = require("@lerna/run/command");const versionCmd = require("@lerna/version/command");const pkg = require("./package.json");module.exports = main;function main(argv) {const context = {    lernaVersion: pkg.version,};return cli()    .command(addCmd)    .command(bootstrapCmd)    .command(changedCmd)    .command(cleanCmd)    .command(createCmd)    .command(diffCmd)    .command(execCmd)    .command(importCmd)    .command(infoCmd)    .command(initCmd)    .command(linkCmd)    .command(listCmd)    .command(publishCmd)    .command(runCmd)    .command(versionCmd)    .parse(argv, context);}

Commander类

lerna的子命令均继承自Command类,比如lerna init命令定义为:0Ft28资讯网——每日最新资讯28at.com

const { Command } = require("@lerna/command");class InitCommand extends Command {    ...}

Command类定义在@lerna/command,位于lerna/core/command目录。0Ft28资讯网——每日最新资讯28at.com

有一些写法值得借鉴,比如个别方法需要InitCommand的实例自行定义,否则抛错,InitCommand类的定义如下:0Ft28资讯网——每日最新资讯28at.com

class InitCommand extends Command {    ...    initialize() {        throw new ValidationError(this.name, "initialize() needs to be implemented.");    }    execute() {        throw new ValidationError(this.name, "execute() needs to be implemented.");    }}

import-local

上文提到,lerna/core/lerna/cli.js描述了命令行的执行入口:0Ft28资讯网——每日最新资讯28at.com

#!/usr/bin/env node"use strict";/* eslint-disable import/no-dynamic-require, global-require */const importLocal = require("import-local");if (importLocal(__filename)) {    require("npmlog").info("cli", "using local version of lerna");} else {    require(".")(process.argv.slice(2));}

其中,import-local的作用是,实现本地开发版本和生产版本的切换。import-local/index.js的内容是:0Ft28资讯网——每日最新资讯28at.com

'use strict';const path = require('path');const resolveCwd = require('resolve-cwd');const pkgDir = require('pkg-dir');module.exports = filename => {    const globalDir = pkgDir.sync(path.dirname(filename));    const relativePath = path.relative(globalDir, filename);    const pkg = require(path.join(globalDir, 'package.json'));    const localFile = resolveCwd.silent(path.join(pkg.name, relativePath));    const localNodeModules = path.join(process.cwd(), 'node_modules');    const filenameInLocalNodeModules = !path.relative(localNodeModules, filename).startsWith('..');    // Use path.relative() to detect local package installation,    // because __filename's case is inconsistent on Windows    // Can use === when targeting Node.js 8    // See https://github.com/nodejs/node/issues/6624    return !filenameInLocalNodeModules && localFile && path.relative(localFile, filename) !== '' && require(localFile);};

依赖管理

Babel使用lerna进行依赖管理。其中,lerna自己实现了一套依赖管理机制,也支持基于yarn的依赖管理。这里主要介绍lerna的hoisting。0Ft28资讯网——每日最新资讯28at.com

子模块相同的依赖可以通过依赖提升(hoisting),将相同的依赖安装在根目录下,本地包之间用软连接实现。0Ft28资讯网——每日最新资讯28at.com

lerna bootstrap

该命令执行时,会在每个子项目下面,各自安装其中package.json声明的依赖。0Ft28资讯网——每日最新资讯28at.com

这样会有一个问题,相同的依赖会被重复安装,除了占用更多空间外,依赖安装速度也受影响。0Ft28资讯网——每日最新资讯28at.com

lerna bootstrap --hoist

--hoist标记时,lerna bootstrap会识别子项目下名称和版本号相同的依赖,并将其安装在根目录的node_modules下,子项目的node_modules会生成软连接。0Ft28资讯网——每日最新资讯28at.com

这样节省了空间,也减少了依赖安装的耗时。0Ft28资讯网——每日最新资讯28at.com

yarn install

当在项目中声明yarn作为依赖安装的底层依赖,如:0Ft28资讯网——每日最新资讯28at.com

lerna.json

{                 "npmClient": "yarn",                 "useWorkspaces": true,         }

package.json0Ft28资讯网——每日最新资讯28at.com

{                 "workspaces": [                         "packages/*"                 ]         }

相对于lerna,yarn提供了更强大的依赖分析能力、hoisting算法。而且,默认情况下,yarn会开启hoist功能,也可以设置nohoist关闭该功能:0Ft28资讯网——每日最新资讯28at.com

{                 "workspaces": {                         "packages": [                                 "Packages/*",                         ],                         "nohoist": [                                 "**"                         ]                  }         }

lerna中涉及的git命令

lerna中广泛使用了git命令用于内部工作,这里列举了lerna中使用的git命令。0Ft28资讯网——每日最新资讯28at.com

git initgit rev-parsegit describegit rev-listgit taggit loggit configgit diff-indexgit --versiongit showgit amgit resetgit ls-filesgit diff-treegit commitgit ls-remotegit checkoutgit pushgit addgit remotegit show-ref

没有必要逐个介绍git命令,我们选取几个不是很常见的git命令介绍,了解其作用、lerna哪些命令用到了它们。0Ft28资讯网——每日最新资讯28at.com

git rev-parse

  • 主要用于解析git引用(如分支名称、标签名称等)或表达式,并输出对应的SHA-1值。它的作用包括但不限于:

解析提交、分支、标签等引用,获取对应的SHA-1值。0Ft28资讯网——每日最新资讯28at.com

校验是否为有效的引用或表达式。0Ft28资讯网——每日最新资讯28at.com

生成git对象的唯一标识符。0Ft28资讯网——每日最新资讯28at.com

下面是一个git rev-parse命令的执行结果案例:0Ft28资讯网——每日最新资讯28at.com

$ git rev-parse HEADf7f6d6f2b6b47eb8c4cf4b8bf5f83e0b8028c031
  • 关联的lerna命令
  • lerna version:在执行版本升级操作时,lerna会使用git rev-parse来获取先前提交的哈希值作为上一个版本的参考。
  • lerna changed:用于列出自上次标记以来发生变更的包,可能会用到git rev-parse来比较不同提交之间的差异。
  • lerna diff:显示自上次标记以来的所有包的diff,也可能会使用git rev-parse来比较不同提交之间的差异。
  • lerna源码案例libs/commands/import/src/index.ts
getCurrentSHA() {    return this.execSync("git", ["rev-parse", "HEAD"]);}getWorkspaceRoot() {    return this.execSync("git", ["rev-parse", "--show-toplevel"]);}

git describe

  • 主要用于根据最接近的标签来描述当前提交的位置。它的作用包括但不限于:

找到最接近当前提交的标签。0Ft28资讯网——每日最新资讯28at.com

根据最接近的标签以及提交的SHA-1值生成一个描述字符串。0Ft28资讯网——每日最新资讯28at.com

可以帮助识别当前提交相对于标签的距离,以及提交是否是基于标签进行的修改。0Ft28资讯网——每日最新资讯28at.com

下面是一个git describe命令的执行结果案例:0Ft28资讯网——每日最新资讯28at.com

$ git describepolaris-release-1.0.0-c12345
  • 关联的lerna命令
  • lerna version:在执行版本升级操作时,lerna可能会使用git describe 来确定当前提交的位置,以便生成新的版本号。
  • lerna源码案例libs/commands/diff/src/lib/get-last-commit.ts
export function getLastCommit(execOpts?: ExecOptions) {  if (hasTags(execOpts)) {    log.silly("getLastTagInBranch", "");    return childProcess.execSync("git", ["describe", "--tags", "--abbrev=0"], execOpts);  }  log.silly("getFirstCommit", "");  return childProcess.execSync("git", ["rev-list", "--max-parents=0", "HEAD"], execOpts);}

git rev-list0Ft28资讯网——每日最新资讯28at.com

  • 主要用于列出提交对象的SHA-1哈希值。它的作用包括但不限于:

列出提交对象的哈希值,可以按时间、作者、提交者等顺序进行排序。0Ft28资讯网——每日最新资讯28at.com

支持使用范围、分支、标签等参数来限制输出的提交范围。0Ft28资讯网——每日最新资讯28at.com

下面是一个git rev-list命令的执行结果案例:0Ft28资讯网——每日最新资讯28at.com

$ git rev-list HEADf7f6d6f2b6b47eb8c4cf4b8bf5f83e0b8028c031a3d8b4e1c2e1d0a9b8c6e5f7d6a4b3e8a1b2c3d4

这里git rev-list HEAD将列出当前HEAD指向的提交及其之前的所有提交的 SHA-1 哈希值。0Ft28资讯网——每日最新资讯28at.com

  • 关联的lerna命令
  • lerna changed:列出自上次标记以来发生变更的包,可能会使用git rev-list 来获取两个标记之间的提交列表。
  • lerna diff:显示自上次标记以来的所有包的diff,也可能会使用git rev-list 来获取两个标记之间的提交列表。
  • lerna 源码案例libs/commands/diff/src/lib/get-last-commit.ts
export function getLastCommit(execOpts?: ExecOptions) {  if (hasTags(execOpts)) {    log.silly("getLastTagInBranch", "");    return childProcess.execSync("git", ["describe", "--tags", "--abbrev=0"], execOpts);  }  log.silly("getFirstCommit", "");  return childProcess.execSync("git", ["rev-list", "--max-parents=0", "HEAD"], execOpts);}

git diff-index0Ft28资讯网——每日最新资讯28at.com

  • 主要用于比较索引和工作树之间的差异,并将其输出为标准输出。它的作用包括但不限于:

检查暂存区(index)和当前工作目录之间的差异。0Ft28资讯网——每日最新资讯28at.com

可以与不同的选项一起使用,以便输出不同格式的差异信息。0Ft28资讯网——每日最新资讯28at.com

下面是一个git diff-index命令的执行结果案例:0Ft28资讯网——每日最新资讯28at.com

$ git diff-index HEAD:100644 100644 bcd1234... 0123456... M        file.txt

这里git diff-index HEAD将显示当前提交(HEAD)和工作目录之间的差异。0Ft28资讯网——每日最新资讯28at.com

  • 关联的lerna命令
  • lerna changed:列出自上次标记以来发生变更的包时,可能会用到git diff-index来比较索引和工作树之间的差异。
  • lerna源码案例libs/commands/import/src/index.ts
export class ImportCommand extends Command<ImportCommandOptions> {    ...    if (this.execSync("git", ["diff-index", "HEAD"])) {      throw new ValidationError("ECHANGES", "Local repository has un-committed changes");    }    ...}

git diff-tree0Ft28资讯网——每日最新资讯28at.com

  • 主要用于比较两棵树之间的差异,并以特定的格式输出。它的作用包括但不限于:

比较两个树对象之间的差异,例如提交对象和树对象之间的差异。0Ft28资讯网——每日最新资讯28at.com

可以用于查看提交之间的差异,文件的更改等信息。0Ft28资讯网——每日最新资讯28at.com

下面是一个git diff-tree命令的执行结果案例:0Ft28资讯网——每日最新资讯28at.com

$ git diff-tree HEAD~2 HEAD100644 blob a3d8b4e1c2e1d0a9b8c6e5f7d6a4b3e8a1b2c3d4        file.txt
  • 关联的lerna命令
  • lerna diff:显示自上次标记以来的所有包的diff时,可能会使用git diff-tree 来比较不同提交之间的差异。
  • lerna源码案例libs/commands/publish/src/lib/get-projects-with-tagged-packages.ts
export async function getProjectsWithTaggedPackages(  projectNodes: ProjectGraphProjectNodeWithPackage[],  projectFileMap: ProjectFileMap,  execOpts: ExecOptions): Promise<ProjectGraphProjectNodeWithPackage[]> {  log.silly("getTaggedPackages", "");  // @see https://stackoverflow.com/a/424142/5707  // FIXME: --root is only necessary for tests :P  const result = await childProcess.exec(    "git",    ["diff-tree", "--name-only", "--no-commit-id", "--root", "-r", "-c", "HEAD"],    execOpts  );  const stdout: string = result.stdout;  const files = new Set(stdout.split("/n"));  return projectNodes.filter((node) => projectFileMap[node.name]?.some((file) => files.has(file.file)));}

git show-ref0Ft28资讯网——每日最新资讯28at.com

  • 主要用于显示引用(如分支和标签)的名称和其对应的提交哈希值。它的作用包括但不限于:

列出git仓库中的所有引用及其对应的提交哈希值。0Ft28资讯网——每日最新资讯28at.com

可以用于查看分支、标签等引用的信息。0Ft28资讯网——每日最新资讯28at.com

下面是一个git show-ref命令的执行结果案例:0Ft28资讯网——每日最新资讯28at.com

$ git show-refa3d8b4e1c2e1d0a9b8c6e5f7d6a4b3e8a1b2c3d4 HEADa3d8b4e1c2e1d0a9b8c6e5f7d6a4b3e8a1b2c3d4 refs/heads/mainf7f6d6f2b6b47eb8c4cf4b8bf5f83e0b8028c031 refs/tags/v1.0.0
  • 关联的lerna命令
  • lerna version:在执行版本升级操作时,lerna可能会使用git show-ref 来获取引用的信息,以确定当前提交的位置。
  • lerna源码案例libs/commands/version/src/lib/remote-branch-exists.ts
export function remoteBranchExists(gitRemote: string, branch: string, opts: ExecOptions) {  log.silly("remoteBranchExists", "");  const remoteBranch = `${gitRemote}/${branch}`;  try {    childProcess.execSync("git", ["show-ref", "--verify", `refs/remotes/${remoteBranch}`], opts);    return true;  } catch (e) {    return false;  }}


0Ft28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-91828-0.html深入理解Babel - 项目管理工具Lerna解析

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 浅谈CSS权重计算规则,你学会了吗?

下一篇: C#队列(Queue)的基本使用,一文全掌握

标签:
  • 热门焦点
  • K8S | Service服务发现

    K8S | Service服务发现

    一、背景在微服务架构中,这里以开发环境「Dev」为基础来描述,在K8S集群中通常会开放:路由网关、注册中心、配置中心等相关服务,可以被集群外部访问;图片对于测试「Tes」环境或者
  • 一年经验在二线城市面试后端的经验分享

    一年经验在二线城市面试后端的经验分享

    忠告这篇文章只适合2年内工作经验、甚至没有工作经验的朋友阅读。如果你是2年以上工作经验,请果断划走,对你没啥帮助~主人公这篇文章内容来自 「升职加薪」星球星友 的投稿,坐
  • 微信语音大揭秘:为什么禁止转发?

    微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • 慕岩炮轰抖音,百合网今何在?

    慕岩炮轰抖音,百合网今何在?

    来源:价值研究所 作者:Hernanderz&ldquo;难道就因为自己的一个产品牛逼了,从客服到总裁,都不愿意正视自己产品和运营上的问题,选择逃避了吗?&rdquo;这一番话,出自百合网联合创
  • 腾讯盖楼,字节拆墙

    腾讯盖楼,字节拆墙

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之&ldquo;想重温暴刷深渊、30+技能搭配暴搓到爽的游戏体验吗?一起上晶核,即刻暴打!&rdquo;曾凭借直播腾讯旗下代理格斗游戏《DNF》一
  • 重估百度丨大模型,能撑起百度的“今天”吗?

    重估百度丨大模型,能撑起百度的“今天”吗?

    自象限原创 作者|程心 罗辑2023年之前,对于自己的&ldquo;今天&rdquo;,百度也很迷茫。&ldquo;新业务到 2022 年底还是 0,希望 2023 年出来一个 1。&rdquo;这是2022年底,李彦宏
  • 携众多高端产品亮相ChinaJoy,小米带来一场科技与人文的视听盛宴

    携众多高端产品亮相ChinaJoy,小米带来一场科技与人文的视听盛宴

    7月28日,全球数字娱乐领域最具知名度与影响力的年度盛会中国国际数码互动娱乐展览会(简称ChinaJoy)在上海新国际博览中心盛大开幕。作为全球领先的科
  • Android 14发布:首批适配机型公布

    Android 14发布:首批适配机型公布

    5月11日消息,谷歌在今天凌晨举行了I/O大会,本次发布会谷歌带来了自家的AI语言模型PaLM 2、谷歌Pixel Fold折叠屏、谷歌Pixel 7a手机,同时发布了Androi
  • Counterpoint :OPPO双旗舰战略全面落地 高端产品销量增长22%

    Counterpoint :OPPO双旗舰战略全面落地 高端产品销量增长22%

    2023年6月30日,全球行业分析机构Counterpoint Research发布的《中国智能手机高端市场白皮书》显示,中国智能手机品牌正在寻求高质量发展,中国高端智能
Top