Получить хэш из последнего git-фиксации в узле

Я хотел бы получить id/hash из последней фиксации текущей ветки в NodeJS.

В NodeJS я хотел бы получить самый последний id/хэш в отношении git и совершить его.

Ответы

Ответ 1

Решение № 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 находится в состоянии отсоединенной головы, содержимое будет хешем
  • если репозиторий git находится в какой-либо ветке, содержимое будет выглядеть примерно так: "refs: refs/heads/current-branch-name"
  • получить содержимое .git/refs/heads/current-branch-name
  • обработать все возможные ошибки в этом процессе
  • Чтобы получить последний хеш из основной ветки напрямую, вы можете получить содержимое файла: .git/refs/heads/master

Это может быть закодировано с чем-то вроде:

const rev = fs.readFileSync('.git/HEAD').toString();
if (rev.indexOf(':') === -1) {
    return rev;
} else {
    return fs.readFileSync('.git/' + rev.substring(5)).toString();
}

Ответ 2

Короткое решение, не требуется внешний модуль (синхронная альтернатива Edin):

revision = require('child_process')
  .execSync('git rev-parse HEAD')
  .toString().trim()

и если вы хотите вручную указать корневую директорию проекта git, используйте второй аргумент execSync для передачи опции cwd, например execSync('git rev-parse HEAD', {cwd: __dirname})

Ответ 3

Используя nodegit, с path_to_repo определяемым как строка, содержащая путь к репо, вы хотите получить команду commit sha. Если вы хотите использовать каталог, из которого выполняется ваш процесс, а затем замените 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
} );

Ответ 4

Если вы всегда находитесь в определенной ветки, вы можете прочитать .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());
});

Ответ 5

Вот версия, которую я разработал, которая использует 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();

Ответ 6

Я был вдохновлен edin-m "Solution # 2 (git не требуется)", но мне не понравилась часть substring(5) которая выглядела как опасное предположение. Я чувствую, что мой RegEx гораздо более терпим к изменениям, разрешенным в требованиях Git Loose для этого файла.

Следующая демонстрация показывает, что она работает как для извлеченной ветки, так и для "отсоединенного 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://stackoverflow.com/a/56975550/117471'
[master (root-commit) 164b559] https://stackoverflow.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

Ответ 7

Вы также можете использовать git-fs (это имя на npm является git-fs, на Github it node-git.)

Git('path/to/repo')
Git.getHead((err, sha) => {
    console.log('The hash is: ' + sha)
})

Тот же модуль может читать каталоги и файлы из репо.