日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

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

來源: 責編: 時間:2024-05-30 17:19:02 280觀看
導讀一、背景Babel是一個比較龐大的項目,其子工程就有至少140個(如 babel/plugins/presets/lerna/babel-loader等),產出的子工具已經是前端開發的基礎設施,對開發效率、代碼質量等有非常高的要求。在本文中,我們將了解Babel是

一、背景

Babel是一個比較龐大的項目,其子工程就有至少140個(如 babel/plugins/presets/lerna/babel-loader等),產出的子工具已經是前端開發的基礎設施,對開發效率、代碼質量等有非常高的要求。whc28資訊網——每日最新資訊28at.com

在本文中,我們將了解Babel是怎樣進行項目管理的。whc28資訊網——每日最新資訊28at.com

圖片圖片whc28資訊網——每日最新資訊28at.com

本文從工程管理、代碼管理、文檔管理、質量管理四個方面對Babel項目管理進行拆解分析。whc28資訊網——每日最新資訊28at.com

工程管理

Babel是典型的monorepo項目,即單倉庫項目,所有的子模塊在同一個倉庫里。Babel目前有140+個子模塊,在工程管理部分,需要解決以下問題:whc28資訊網——每日最新資訊28at.com

  • 模塊間如何方便地互相關聯進行本地開發;
  • 整個項目的版本控制;
  • 操作自動化。

工程管理部分主要使用lerna、yarn等工具。whc28資訊網——每日最新資訊28at.com

代碼風格

Babel是多人協作開發的開源項目,如何保證代碼風格一致,Babel使用的是社區常見的解決方案。whc28資訊網——每日最新資訊28at.com

該模塊主要使用eslint、prettier等工具。whc28資訊網——每日最新資訊28at.com

文檔

Babel的迭代速度很快、涉及的模塊很多,該模塊解決版本發布后如何自動更新相關文檔等問題。whc28資訊網——每日最新資訊28at.com

該模塊主要使用lerna等工具。whc28資訊網——每日最新資訊28at.com

質量控制

Babel的產品是前端開發的基礎設施,該模塊主要保證Babel的產出是高質量的。whc28資訊網——每日最新資訊28at.com

該模塊主要使用jest、git blame等工具。whc28資訊網——每日最新資訊28at.com

二、monorepo

Babel使用monorepo模式進行工程管理。whc28資訊網——每日最新資訊28at.com

什么是monorepo

monorepo(monolithic repository),指的是單倉庫代碼,將多個項目代碼存儲在一個倉庫里。另外有一種模式是multirepo,指的是多倉庫代碼(one-repository-per-module),不同的項目分布在不同的倉庫里。React、Babel、Jest、Vue、Angular均采用monorepo進行項目管理。whc28資訊網——每日最新資訊28at.com

典型的monorepo結構是:whc28資訊網——每日最新資訊28at.com

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

這是Babel源碼的目錄結構:whc28資訊網——每日最新資訊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的模式:whc28資訊網——每日最新資訊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是兩種不同的理念。whc28資訊網——每日最新資訊28at.com

multirepo允許多元化發展,每個模塊獨立實現自己的構建、單元測試、依賴管理等。monorepo抹平了模塊間的很多差異,通過集中管理和高度集成化的工具,減少開發和溝通時的成本。monorepo最大的問題可能就是不能管理占用空間太大的項目了。whc28資訊網——每日最新資訊28at.com

所以,還是要根據項目的實際需求出發選擇用哪種項目管理模式。whc28資訊網——每日最新資訊28at.com

三、lerna

lerna是基于git/npm/yarn等的工作流提效工具,用于維護monorepo。它是Babel 開發過程中提升開發效率產出的工具。whc28資訊網——每日最新資訊28at.com

lerna本身也是一個monorepo的項目,并且,lerna為monorepo項目提供了如下支持:whc28資訊網——每日最新資訊28at.com

  • 項目管理

lerna提供了一系列命令用于monorepo項目初始化、添加子項目、查看項目信息等。whc28資訊網——每日最新資訊28at.com

  • 依賴管理

lerna支持為monorepo項目統一管理公共依賴、自動安裝各個子項目的依賴、自動創建子模塊符號鏈接等。whc28資訊網——每日最新資訊28at.com

  • 版本管理

lerna可以根據項目代碼的變動情況,發現影響的子項目范圍,在發布時提供語義化版本推薦等,極大提升了monorepo項目的版本管理效率。whc28資訊網——每日最新資訊28at.com

lerna命令集

命令行列表

lerna官網有對各種命令各種用法的詳細介紹,這些命令可以分為:項目管理、依賴管理、版本管理三大類。whc28資訊網——每日最新資訊28at.com

圖片圖片whc28資訊網——每日最新資訊28at.com

全局配置項

lerna有一批通用參數,所有子命令均可以使用。whc28資訊網——每日最新資訊28at.com

--concurrencywhc28資訊網——每日最新資訊28at.com

當lerna將任務并行執行時,需要使用多少線程(默認為邏輯CPU內核數)。whc28資訊網——每日最新資訊28at.com

lerna publish --concurrency 1

--loglevel<silent|error|warn|success|info|verbose|silly>whc28資訊網——每日最新資訊28at.com

要報告什么級別的日志。如果失敗,所有日志都寫到當前工作目錄中的lerna-debug.log中。whc28資訊網——每日最新資訊28at.com

任何高于該設置的日志都會顯示出來。默認值是"info"。whc28資訊網——每日最新資訊28at.com

--max-buffer<bytes>whc28資訊網——每日最新資訊28at.com

為每個底層進程調用設置的最大緩沖區長度。例如,當有人希望在運行lerna import的同時導入包含大量提交的倉庫時,就是它出場的時候了。在這種情況下,內置的緩沖區長度可能不夠。whc28資訊網——每日最新資訊28at.com

--no-progresswhc28資訊網——每日最新資訊28at.com

禁用進度條。在CLI環境中總是這樣。whc28資訊網——每日最新資訊28at.com

--no-sortwhc28資訊網——每日最新資訊28at.com

默認情況下,所有任務都按照拓撲排序的順序在包上執行,以尊重所討論的包的依賴關系。在不保證lerna調用一致的情況下,以最努力的方式打破循環。whc28資訊網——每日最新資訊28at.com

如果只有少量的包有許多依賴項,或者某些包執行的時間長得不成比例,拓撲排序可能會導致并發瓶頸。--no-sort配置項禁用排序,而是以最大并發的任意順序執行任務。whc28資訊網——每日最新資訊28at.com

如果您運行多個watch命令,該配置項也會有所幫助。因為lerna run將按照拓撲排序的順序執行命令,所以在繼續執行之前可能會等待某個命令。當您運行"watch"命令時會阻塞執行,因為他們通常不會結束。whc28資訊網——每日最新資訊28at.com

--reject-cycleswhc28資訊網——每日最新資訊28at.com

如果(在bootstrap、exec、publish或run中)發現循環,則立即失敗。whc28資訊網——每日最新資訊28at.com

lerna bootstrap --reject-cycles

過濾器參數

--scope<glob>

只包含名稱與給定通配符匹配的包。whc28資訊網——每日最新資訊28at.com

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

--ignore<glob>

排除名稱與給定通配符匹配的包。whc28資訊網——每日最新資訊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

排除私有的包。默認情況下是包含它們的。whc28資訊網——每日最新資訊28at.com

--since [ref]

只包含自指定ref以來已經改變的包。如果沒有傳遞ref,它默認為最近的標記。whc28資訊網——每日最新資訊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來說很有效。whc28資訊網——每日最新資訊28at.com

--exclude-dependents

當使用--since運行命令時,排除所有傳遞的被依賴項,覆蓋默認的“changed”算法。whc28資訊網——每日最新資訊28at.com

如果沒有--since該參數時無效的,會拋出錯誤。whc28資訊網——每日最新資訊28at.com

--include-dependents

在運行命令時包括所有傳遞的被依賴項,無視--scope、--ignore或--since。whc28資訊網——每日最新資訊28at.com

--include-dependencies

在運行命令時包括所有傳遞依賴項,無視--scope、--ignore或--since。whc28資訊網——每日最新資訊28at.com

與接受--scope(bootstrap、clean、ls、run、exec)的任何命令組合使用。確保對任何作用域的包(通過--scope或--ignore)的所有依賴項(和dev依賴項)也進行操作。whc28資訊網——每日最新資訊28at.com

注意:這將會覆蓋--scope和--ignore。whc28資訊網——每日最新資訊28at.com

例如,如果一個匹配了--ignore的包被另一個正在引導的包所以來,那么它仍會照常工作。whc28資訊網——每日最新資訊28at.com

當您想要“設置”一個依賴于其他正在設置的包其中的一個包時,這是非常有用的。whc28資訊網——每日最新資訊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分支進行大量發布時才有用,通常情況下不推薦這樣做。whc28資訊網——每日最新資訊28at.com

lerna原理解析

文件結構

以下是lerna的主要目錄結構(省略了一些文件和文件夾):whc28資訊網——每日最新資訊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/*目錄下。whc28資訊網——每日最新資訊28at.com

另外,在源碼中,經常會看到名稱為@lerna/command的子項目,如lerna/core/lerna/index.js的內容是:whc28資訊網——每日最新資訊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個子項目。whc28資訊網——每日最新資訊28at.com

以下是各子項目分布:whc28資訊網——每日最新資訊28at.com

圖片圖片whc28資訊網——每日最新資訊28at.com

命令行注冊

lerna命令注冊工作集中在lerna/core/lerna/*路徑下。whc28資訊網——每日最新資訊28at.com

lerna/core/lerna/package.jsonwhc28資訊網——每日最新資訊28at.com

該文件的bin字段定義了lerna命令:whc28資訊網——每日最新資訊28at.com

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

lerna/core/lerna/cli.jswhc28資訊網——每日最新資訊28at.com

該文件描述了命令行的執行入口:whc28資訊網——每日最新資訊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指令:whc28資訊網——每日最新資訊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命令定義為:whc28資訊網——每日最新資訊28at.com

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

Command類定義在@lerna/command,位于lerna/core/command目錄。whc28資訊網——每日最新資訊28at.com

有一些寫法值得借鑒,比如個別方法需要InitCommand的實例自行定義,否則拋錯,InitCommand類的定義如下:whc28資訊網——每日最新資訊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描述了命令行的執行入口:whc28資訊網——每日最新資訊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的內容是:whc28資訊網——每日最新資訊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。whc28資訊網——每日最新資訊28at.com

子模塊相同的依賴可以通過依賴提升(hoisting),將相同的依賴安裝在根目錄下,本地包之間用軟連接實現。whc28資訊網——每日最新資訊28at.com

lerna bootstrap

該命令執行時,會在每個子項目下面,各自安裝其中package.json聲明的依賴。whc28資訊網——每日最新資訊28at.com

這樣會有一個問題,相同的依賴會被重復安裝,除了占用更多空間外,依賴安裝速度也受影響。whc28資訊網——每日最新資訊28at.com

lerna bootstrap --hoist

--hoist標記時,lerna bootstrap會識別子項目下名稱和版本號相同的依賴,并將其安裝在根目錄的node_modules下,子項目的node_modules會生成軟連接。whc28資訊網——每日最新資訊28at.com

這樣節省了空間,也減少了依賴安裝的耗時。whc28資訊網——每日最新資訊28at.com

yarn install

當在項目中聲明yarn作為依賴安裝的底層依賴,如:whc28資訊網——每日最新資訊28at.com

lerna.json

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

package.jsonwhc28資訊網——每日最新資訊28at.com

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

相對于lerna,yarn提供了更強大的依賴分析能力、hoisting算法。而且,默認情況下,yarn會開啟hoist功能,也可以設置nohoist關閉該功能:whc28資訊網——每日最新資訊28at.com

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

lerna中涉及的git命令

lerna中廣泛使用了git命令用于內部工作,這里列舉了lerna中使用的git命令。whc28資訊網——每日最新資訊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哪些命令用到了它們。whc28資訊網——每日最新資訊28at.com

git rev-parse

  • 主要用于解析git引用(如分支名稱、標簽名稱等)或表達式,并輸出對應的SHA-1值。它的作用包括但不限于:

解析提交、分支、標簽等引用,獲取對應的SHA-1值。whc28資訊網——每日最新資訊28at.com

校驗是否為有效的引用或表達式。whc28資訊網——每日最新資訊28at.com

生成git對象的唯一標識符。whc28資訊網——每日最新資訊28at.com

下面是一個git rev-parse命令的執行結果案例:whc28資訊網——每日最新資訊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

  • 主要用于根據最接近的標簽來描述當前提交的位置。它的作用包括但不限于:

找到最接近當前提交的標簽。whc28資訊網——每日最新資訊28at.com

根據最接近的標簽以及提交的SHA-1值生成一個描述字符串。whc28資訊網——每日最新資訊28at.com

可以幫助識別當前提交相對于標簽的距離,以及提交是否是基于標簽進行的修改。whc28資訊網——每日最新資訊28at.com

下面是一個git describe命令的執行結果案例:whc28資訊網——每日最新資訊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-listwhc28資訊網——每日最新資訊28at.com

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

列出提交對象的哈希值,可以按時間、作者、提交者等順序進行排序。whc28資訊網——每日最新資訊28at.com

支持使用范圍、分支、標簽等參數來限制輸出的提交范圍。whc28資訊網——每日最新資訊28at.com

下面是一個git rev-list命令的執行結果案例:whc28資訊網——每日最新資訊28at.com

$ git rev-list HEADf7f6d6f2b6b47eb8c4cf4b8bf5f83e0b8028c031a3d8b4e1c2e1d0a9b8c6e5f7d6a4b3e8a1b2c3d4

這里git rev-list HEAD將列出當前HEAD指向的提交及其之前的所有提交的 SHA-1 哈希值。whc28資訊網——每日最新資訊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-indexwhc28資訊網——每日最新資訊28at.com

  • 主要用于比較索引和工作樹之間的差異,并將其輸出為標準輸出。它的作用包括但不限于:

檢查暫存區(index)和當前工作目錄之間的差異。whc28資訊網——每日最新資訊28at.com

可以與不同的選項一起使用,以便輸出不同格式的差異信息。whc28資訊網——每日最新資訊28at.com

下面是一個git diff-index命令的執行結果案例:whc28資訊網——每日最新資訊28at.com

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

這里git diff-index HEAD將顯示當前提交(HEAD)和工作目錄之間的差異。whc28資訊網——每日最新資訊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-treewhc28資訊網——每日最新資訊28at.com

  • 主要用于比較兩棵樹之間的差異,并以特定的格式輸出。它的作用包括但不限于:

比較兩個樹對象之間的差異,例如提交對象和樹對象之間的差異。whc28資訊網——每日最新資訊28at.com

可以用于查看提交之間的差異,文件的更改等信息。whc28資訊網——每日最新資訊28at.com

下面是一個git diff-tree命令的執行結果案例:whc28資訊網——每日最新資訊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-refwhc28資訊網——每日最新資訊28at.com

  • 主要用于顯示引用(如分支和標簽)的名稱和其對應的提交哈希值。它的作用包括但不限于:

列出git倉庫中的所有引用及其對應的提交哈希值。whc28資訊網——每日最新資訊28at.com

可以用于查看分支、標簽等引用的信息。whc28資訊網——每日最新資訊28at.com

下面是一個git show-ref命令的執行結果案例:whc28資訊網——每日最新資訊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;  }}


whc28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-91828-0.html深入理解Babel - 項目管理工具Lerna解析

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 淺談CSS權重計算規則,你學會了嗎?

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

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
国产精品久99| 女女同性女同一区二区三区91| 日韩视频免费观看| 一本色道久久综合狠狠躁篇的优点 | 国产精品草草| 国产日韩在线亚洲字幕中文| 精品1区2区3区4区| 日韩亚洲欧美中文三级| 亚洲欧美日本伦理| 久久视频这里只有精品| 欧美喷潮久久久xxxxx| 国产免费成人在线视频| 亚洲国产日韩欧美在线99| 一区二区三区精品视频在线观看| 性做久久久久久免费观看欧美| 老司机精品视频网站| 欧美特黄一级| 在线欧美电影| 亚洲欧美日韩精品在线| 欧美国产欧美亚州国产日韩mv天天看完整| 国产精品久久7| 亚洲高清一区二| 香港成人在线视频| 欧美国产精品专区| 国产日韩av高清| 99在线热播精品免费99热| 久久久国产成人精品| 欧美日韩国产欧| 精品成人一区| 亚洲欧美激情一区二区| 欧美国产欧美综合| 黑人巨大精品欧美黑白配亚洲| 99亚洲一区二区| 美女国产精品| 国产欧美一区二区三区久久人妖| 亚洲精品美女在线| 久久精品一区四区| 国产精品久久久久免费a∨| 91久久精品国产| 久久精品在线视频| 国产精品美女久久久浪潮软件| 亚洲韩国日本中文字幕| 欧美在线亚洲在线| 国产精品久久久久久久浪潮网站| 亚洲激情一区| 久久另类ts人妖一区二区| 国产精品你懂得| 99国产精品久久久久久久成人热 | 老司机aⅴ在线精品导航| 国产精品日韩| 99视频日韩| 欧美成人免费小视频| 国产一区二区剧情av在线| 亚洲在线一区二区三区| 欧美日韩91| 亚洲日本成人网| 蜜乳av另类精品一区二区| 国产一二精品视频| 午夜影院日韩| 国产伦精品一区二区三| 亚洲一区不卡| 国产精品h在线观看| 亚洲毛片在线| 欧美激情女人20p| 在线观看不卡| 久久这里有精品视频| 国产综合欧美在线看| 亚洲欧美一区二区精品久久久| 欧美午夜精品理论片a级按摩 | 久久综合九色综合欧美就去吻| 国产日韩欧美三级| 欧美亚洲一区| 国产日韩欧美| 欧美一区二区大片| 国产日韩欧美二区| 欧美一区免费视频| 国产一级揄自揄精品视频| 欧美在线视频播放| 国产一区二区高清| 久久精品青青大伊人av| 国内精品视频666| 久久久久久伊人| 精品51国产黑色丝袜高跟鞋| 久久久天天操| 亚洲二区在线视频| 欧美福利视频在线观看| 亚洲精品久久嫩草网站秘色| 欧美精品 日韩| 一本色道久久99精品综合| 欧美区国产区| 亚洲午夜免费视频| 国产精品综合色区在线观看| 久久疯狂做爰流白浆xx| 激情一区二区三区| 你懂的国产精品永久在线| 亚洲三级观看| 欧美三区在线观看| 亚洲欧美日韩区| 国产一区视频观看| 美女免费视频一区| 亚洲免费黄色| 国产精品看片资源| 久久国产精品久久国产精品 | 亚洲精品九九| 欧美三级视频在线| 香港成人在线视频| 一区免费视频| 欧美精品在线观看| 亚洲影院免费| 国内成人自拍视频| 欧美黄色片免费观看| 中文高清一区| 国产一区二区三区丝袜| 欧美福利小视频| 亚洲一区www| 国产字幕视频一区二区| 欧美大片一区二区| 亚洲午夜av| 韩国av一区二区| 欧美黄色网络| 欧美一级视频| 最新成人在线| 国产精品午夜国产小视频| 久久人人九九| 99视频热这里只有精品免费| 国产农村妇女精品一区二区| 麻豆乱码国产一区二区三区| 亚洲美女av在线播放| 国产欧美精品日韩| 欧美成年人网站| 亚洲一区自拍| 亚洲第一免费播放区| 欧美亚州在线观看| 久久青草久久| 亚洲一级影院| 最新中文字幕一区二区三区| 国产精品系列在线| 欧美福利视频在线观看| 午夜激情一区| 亚洲肉体裸体xxxx137| 国产欧美视频一区二区三区| 欧美精品一区二区久久婷婷| 欧美专区在线播放| 99视频一区二区三区| 伊人精品在线| 国产精品三级视频| 欧美精品日韩综合在线| 久久精品亚洲精品| 亚洲天堂网在线观看| 亚洲福利视频一区二区| 国产精品网站在线播放| 欧美黄污视频| 久久精品久久99精品久久| 在线一区二区三区做爰视频网站| 激情久久五月| 国产精品性做久久久久久| 欧美精品 国产精品| 久久久久久久一区| 亚洲欧美国产制服动漫| 亚洲免费高清| 亚洲电影欧美电影有声小说| 国产女人精品视频| 欧美天堂亚洲电影院在线观看 | 欧美日韩国产亚洲一区| 久久久久久电影| 午夜视频久久久| 一区二区三区日韩欧美| 亚洲国产精品日韩| 韩国av一区二区三区在线观看| 国产精品高精视频免费| 欧美激情女人20p| 久久一综合视频| 久久国产精品99久久久久久老狼| 亚洲无线观看| 亚洲美女中文字幕| 亚洲国产精品一区二区第四页av | 亚洲欧美日产图| 宅男噜噜噜66一区二区66| 亚洲欧洲三级| 亚洲第一偷拍| 在线观看亚洲| 激情综合色综合久久| 国产婷婷97碰碰久久人人蜜臀| 国产精品久久久久av| 欧美视频一区二区三区四区| 欧美另类一区二区三区| 欧美成年人视频网站| 美日韩精品视频免费看| 猫咪成人在线观看| 久久夜色撩人精品| 久久精品国产清自在天天线| 欧美中文字幕在线播放| 久久激五月天综合精品| 欧美中文在线免费| 欧美在线免费播放| 欧美在线亚洲综合一区| 欧美在线不卡| 久久精品30| 久久久av网站| 久久一区二区视频| 免费日韩精品中文字幕视频在线| 美日韩精品视频| 欧美电影免费观看| 欧美精品久久一区|