获取 Node 中最近一次 git 提交的哈希值
Posted
技术标签:
【中文标题】获取 Node 中最近一次 git 提交的哈希值【英文标题】:Get hash of most recent git commit in Node 【发布时间】:2016-04-03 18:29:52 【问题描述】:我想获取 NodeJS 中当前分支上最近提交的 id/hash。
在 NodeJS 中,我想获取关于 git 及其提交的最新 id/hash。
【问题讨论】:
您似乎已经找到了正确的节点模块。 Afaik 有例子可以做你想做的事。 @Sirko 希望提供链接。我今天早上搜索了文档,但没有找到。 您可以使用node-git lib 执行此操作。要获取 id,请查看 here,这是获取提交统计信息和哈希提交的示例。 入门:github.com/nodegit/nodegit/blob/master/examples/walk-history.js 另请参阅 nodegit.org/api/reference/#list 和 nodegit.org/api/repository/#getBranchCommit 【参考方案1】:短解决方案,不需要外部模块(同步替代 Edin 的答案):
revision = require('child_process')
.execSync('git rev-parse HEAD')
.toString().trim()
如果要手动指定git项目的根目录,使用execSync
的第二个参数传递cwd
option,如execSync('git rev-parse HEAD', cwd: __dirname)
【讨论】:
使用.slice(0, 7);
获取短sha。
@DanielSteigerwald 或git rev-parse --short HEAD
我不得不承认,我有点困惑为什么这个答案比four months before this answer发布的更详尽的答案(其中已经有这个解决方案)有更多的赞成票...跨度>
因为同步选项是两年后在 Edin 的回答中添加的。【参考方案2】:
解决方案 #1(需要 git,带有回调):
require('child_process').exec('git rev-parse HEAD', function(err, stdout)
console.log('Last commit hash on this branch is:', stdout);
);
或者,您可以使用execSync()
来避免回调。
解决方案 #2(不需要 git):
获取文件.git/HEAD
的内容
如果 git repo 处于 detached head 状态,内容将是哈希
如果 git repo 在某个分支上,内容将类似于:“refs: refs/heads/current-branch-name”
获取.git/refs/heads/current-branch-name
的内容
处理此过程中所有可能的错误
直接从master分支获取最新的hash,可以获取文件内容:.git/refs/heads/master
可以这样编码:
const rev = fs.readFileSync('.git/HEAD').toString().trim();
if (rev.indexOf(':') === -1)
return rev;
else
return fs.readFileSync('.git/' + rev.substring(5)).toString().trim();
【讨论】:
选择这个是因为我喜欢你不必像 Paulpro 的回答那样指定path_to_repo
。
虽然这可行,但@Paulpro 的答案更便携(不依赖于安装 git)、更快(child_process.exec 需要一段时间才能生成),并且保持“在节点中”(如OP想要)。
@CameronTacklind 并非如此,它依赖于编译与 libgit2 的绑定,这需要安装比仅安装 git 本身更多的软件。我已经包含了 w/ 和 w/o git 解决方案,因为这是公认的答案。
@edin-m 哪一部分“不是真的”?我相信我所说的一切都是正确的。当然,有些人会发现安装 NodeGit 比较麻烦,但这并不重要。依赖安装的git
可能不太便携,但不可否认,在实践中,git
相当普遍。正如@hakatashi 指出的那样,保持“节点”的另一种方法是(您已在此处提供)。任何产生/执行另一个二进制文件的东西都不会留在“节点”恕我直言。
鉴于我们正在寻找一个 git 提交,它是仅在 git 管理的目录中才有意义的数据,隐藏的 .git
目录由 git 本身创建(你没有如果你刚刚从 github、gitlab 或任何其他 git 托管服务下载了一个版本),那么 git 将不可用的想法是......令人困惑,充其量是?如果没有安装 git 并管理目录,则 没有 git 提交可供查看。【参考方案3】:
使用nodegit,将path_to_repo
定义为一个字符串,其中包含您要为其获取提交sha 的repo 的路径。如果您想使用运行进程的目录,请将path_to_repo
替换为process.cwd()
:
var Git = require( 'nodegit' );
Git.Repository.open( path_to_repo ).then( function( repository )
return repository.getHeadCommit( );
).then( function ( commit )
return commit.sha();
).then( function ( hash )
// use `hash` here
);
【讨论】:
只是在我的机器上 FIY,这大约比来自@antoine129 的更被接受的答案快 3.2 倍。 execSync 大约需要 6.4 毫秒,而 nodegit 只需要大约 1.8 毫秒nodegit
在大多数情况下是最佳选择
这应该是公认的答案。它是唯一保持“在节点中”并且对变化的分支具有鲁棒性的答案。
在低于 10 毫秒的范围内需要多长时间真的很重要吗?特别是如果您在 main 开始时执行此操作并将其存储以供以后使用(而不是每次需要时都执行此操作)。添加另一个依赖于477 more dependencies的依赖似乎也有点矫枉过正(如果你只是为此使用它)。但我猜一个空的 Next.js 项目使用的数量大致相同......【参考方案4】:
我受到edin-m's "Solution #2 (no git required)" 的启发,但我不喜欢substring(5)
部分,这感觉像是一个危险的假设。我觉得我的 RegEx 对 git 对该文件的宽松要求所允许的变化更加宽容。
以下演示显示它适用于签出分支和“分离的 HEAD”。
$ cd /tmp
$ git init githash
Initialized empty Git repository in /private/tmp/githash/.git/
$ cd githash
$ cat > githash.js <<'EOF'
const fs = require('fs');
const git_hash = () =>
const rev = fs.readFileSync('.git/HEAD').toString().trim().split(/.*[: ]/).slice(-1)[0];
if (rev.indexOf('/') === -1)
return rev;
else
return fs.readFileSync('.git/' + rev).toString().trim();
console.log(git_hash());
EOF
$ git add githash.js
$ git commit -m 'https://***.com/a/56975550/117471'
[master (root-commit) 164b559] https://***.com/a/56975550/117471
1 file changed, 14 insertions(+)
create mode 100644 githash.js
$ node githash.js
164b559e3b93eb4c42ff21b1e9cd9774d031bb38
$ cat .git/HEAD
ref: refs/heads/master
$ git checkout 164b559e3b93eb4c42ff21b1e9cd9774d031bb38
Note: checking out '164b559e3b93eb4c42ff21b1e9cd9774d031bb38'.
You are in 'detached HEAD' state.
$ cat .git/HEAD
164b559e3b93eb4c42ff21b1e9cd9774d031bb38
$ node githash.js
164b559e3b93eb4c42ff21b1e9cd9774d031bb38
【讨论】:
【参考方案5】:如果你总是在特定的分支上,你可以阅读.git/refs/heads/<branch_name>
以轻松获取提交哈希。
const fs = require('fs');
const util = require('util');
util.promisify(fs.readFile)('.git/refs/heads/master').then((hash) =>
console.log(hash.toString().trim());
);
【讨论】:
【参考方案6】:这是我设计的一个使用fs.promises
和async/await
的版本。
import default as fsWithCallbacks from 'fs';
const fs = fsWithCallbacks.promises;
const getGitId = async () =>
const gitId = await fs.readFile('.git/HEAD', 'utf8');
if (gitId.indexOf(':') === -1)
return gitId;
const refPath = '.git/' + gitId.substring(5).trim();
return await fs.readFile(refPath, 'utf8');
;
const gitId = await getGitId();
【讨论】:
【参考方案7】:你也可以使用git-fs(它在npm上叫git-fs,在Github上叫node-git。)
Git('path/to/repo')
Git.getHead((err, sha) =>
console.log('The hash is: ' + sha)
)
同一模块可以从 repo 中读取目录和文件。
【讨论】:
以上是关于获取 Node 中最近一次 git 提交的哈希值的主要内容,如果未能解决你的问题,请参考以下文章