最佳实践:Node.js集成Git方案梳理

1. 背景

在开发一款js静态分析工具时,我遇到了一些git相关的需求:

  • 通过git比较出工程中两个分支的改动文件
  • 跨分支读取

针对这个两个问题,我们先看看用 git 命令如何操作:

1.1 分支比较

通过如下的 git 命令即可进行分支比较:

css 复制代码
git diff [分支1] [分支2] --name-status

打印结果可能如下:

css 复制代码
M       a.js
D       b.vue
A       c.vue
R092    .whistle.js     .whistle111.js
...

这里每一行就是一个改动文件,空格前是改动类型,空格后是改动的具体文件。

M: 修改 D: 删除 A: 新增 R: 重命名,这里的 092 代表是改动前后两个文件的相似度。[了解更多]

1.2 跨分支读取

这里先说一下跨分支读取的意思:假如我现在处于a分支中开发,我想要实现在不切换分支的情况下读取b分支某个文件的内容和某个文件夹下面的文件列表。

通过调研,发现可以通过 git cat-file 和 git ls-tree 来实现:

  • 读取文件内容
bash 复制代码
#读取文件
git cat-file -p [分支]:[文件相对路径]
  • 列出目录下的文件及文件夹列表
bash 复制代码
git ls-tree [分支]:[目录相对路径]

所以,现在的问题是如何在nodejs中集成这功能,且支持打包到 Cli工具和 Vscode 拓展。

2. 实现方案

2.1 exec 调用 Git 命令

首先想到最简单的方案就是通过Node.js 的 child_process 模块中的 exec调用Git命令:

typescript 复制代码
import { execSync } from "child_process";

function getChangeFileList(baseBranch: string, targetBranch: string) {
  return execSync(`git diff ${baseBranch} ${targetBranch} --name-status`, {
    cwd: projectDir,
  }).toString().trim();
}

这种方法使用简单,无需依赖外部的包,且能够被打包到node cli工具和vscode插件中。

目前有许多js库都基于这个原理,例如 simple-git,可以进一步简化使用的成本。

但经过一段时间的使用,发现这种方式存在两个问题:

  1. 依赖本机安装的Git,且需要正确配置环境变量(一般开发都会安装git,不是很严重的问题)。
  2. 通过创建子进程调用外部命令,而创建子进程是有性能开销的,当调用太多次后有性能问题,具体有多差可以看后面的对比。

由于有了这些问题,所以调研实践了市面的其他几种方案。

2.2 execFile 调用 Git 可执行文件

上面我们介绍了通过 child_process模块中的 exec(execSync是exec的同步形式)方法,它是通过调用shell来执行命令的,而在这个模块中还有一个execFile 方法,可以通过git程序的路径来执行:

ini 复制代码
const res = execFileSync("/usr/bin/git", ["cat-file", "-p", `master:packages.json`]);

下面是nodejs文档的描述

child_process.exec() 和 child_process.execFile() 之间区别的重要性可能因平台而异。 在 Unix 类型的操作系统(Unix、Linux、macOS)上,child_process.execFile() 可以更高效,因为它默认不衍生 shell。 但是,在 Windows 上,.bat 和 .cmd 文件在没有终端的情况下无法自行执行,因此无法使用 child_process.execFile() 启动。

可以看到这种方法性能有所提升,但是必须指定git的位置。

2.3 dugite

github.com/desktop/dug...

github.com/desktop/dug...

dugite 是一个execFile原理实现git绑定的js库,但于上面不同的是,它在安装后会调用postinstall钩子去下载一个精简版版的git,所以不需要手动指定git路径。

postinstall 钩子

node_modules
中的可执行文件

再从dugite的github可以看成,dugite是github-desktop的一部分,而github-desktop是基于electron开发的,那么可以推测出这个库对于开发跨端的桌面程序有很好的支持。

2.3 NodeGit

官网:www.nodegit.org/

NodeGit 是一个基于 C++ 实现的Node.js 原生模块,实现了对 libgit2 的封装。

ini 复制代码
const repo = await NodeGit.Repository.open(gitBasePath);

经过使用发现这个库优点如下:

  1. 功能强大,API复杂
  2. 原生模块性能好
  3. API基于Promise来实现。

但是使用了这个库也发现了一些问题:

  1. 原生模块导致安装复杂,比如在我的mac m1 电脑安装会失败,需要指定安装^0.28.0-alpha.21 这个版本。
  2. 在一些低版本Linux 上面安装会失败,需要手动升级GCC版本。
  3. vscode插件不支持原生模块。

2.4 isomorphic-git

isomorphic-git.org/

isomorphic-git 是一个纯 JavaScript 的库,提供了跨浏览器和 Node.js 环境使用的 Git 功能。它不依赖于外部的 Git 客户端或二进制文件,而是通过 JavaScript 实现了 Git 的核心功能。

使用 isomorphic-git 实现跨分支读取:

javascript 复制代码
import * as git from "isomorphic-git";
import fs from 'fs';

const oid = await git1.resolveRef({
    fs: fs,
    dir: projectDir,
    ref: 'master',
});

let cache = {};
const res = await git1.readBlob({
    fs: fs,
    dir: projectDir,
    oid,
    cache,
    filepath: 'packages.json'
 });
 console.log(res.blob);

这个库支持通过 cache 参数缓存结果,提高批量读取文件的速度。

3. 总结

下面我会从性能、浏览器支持、vscode插件机制几个角度进行对比:

exec + git execFile + git dugite NodeGit isomorphic-git
读取 620个不同文件 11888 ms 9357 ms 4002 ms 92ms 开启cache: 810 ms 不开cache: 12828 ms
star - - 443 5.5k 7.1k
浏览器支持 不支持 不支持 不支持 不支持 支持
vscode插件 支持 支持 不支持,需要 npm install下载依赖 不支持 支持
node cli 工具 支持 支持 支持 支持,但可能需要升级系统的库 支持
API支持 需要手写git命令 需要手写git命令 需要手写git命令 API封装度高,使用复杂 API封装度高,使用较为简单

根据上述表格,可以得到如下结论:

  1. isomorphic-git综合能力最强,可以兼容大部分场景。
  2. 需要浏览器支持使用isomorphic-git
  3. 需要性能使用 nodegit
  4. electron 集成可以考虑使用 dugite,github 官方背书
  5. 不依赖外部git的方案:dugite、nodegit、isomorphic-git

但接入哪一个,还需要在项目中对比。

相关推荐
课堂随想4 分钟前
SHA-1 是一种不可逆的、固定长度的哈希函数,在 Git 等场景用于生成唯一的标识符来管理对象和数据完整性
git·哈希算法
多多米100539 分钟前
初学Vue(2)
前端·javascript·vue.js
柏箱1 小时前
PHP基本语法总结
开发语言·前端·html·php
新缸中之脑1 小时前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法
hmz8561 小时前
最新网课搜题答案查询小程序源码/题库多接口微信小程序源码+自带流量主
前端·微信小程序·小程序
看到请催我学习1 小时前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
blaizeer2 小时前
深入理解 CSS 浮动(Float):详尽指南
前端·css
编程老船长2 小时前
网页设计基础 第一讲:软件分类介绍、工具选择与课程概览
前端
编程老船长2 小时前
网页设计基础 第二讲:安装与配置 VSCode 开发工具,创建第一个 HTML 页面
前端
速盾cdn2 小时前
速盾:网页游戏部署高防服务器有什么优势?
服务器·前端·web安全