Get hash of most recent git commit in Node

node.jsGit

node.js Problem Overview


I'd like to get the id/hash of the most recent commit on the current branch in NodeJS.

In NodeJS, I'd like to get the most recent id/hash, with respect to git and commits thereof.

node.js Solutions


Solution 1 - node.js

Short solution, no external module needed (synchronous alternative to Edin's answer):

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

and if you want to manually specify the root directory of the git project, use the second argument of execSync to pass the cwd option, like execSync('git rev-parse HEAD', {cwd: __dirname})

Solution 2 - node.js

Solution #1 (git required, with callback):

require('child_process').exec('git rev-parse HEAD', function(err, stdout) {
    console.log('Last commit hash on this branch is:', stdout);
});

Optionally, you can use execSync() to avoid the callback.

Solution #2 (no git required):

  • get contents of the file .git/HEAD
  • if the git repo is in the detached head state, the content will be the hash
  • if the git repo is on some branch, the content will be something like: "refs: refs/heads/current-branch-name"
  • get contents of .git/refs/heads/current-branch-name
  • handle all possible errors in this process
  • to get the latest hash from the master branch directly, you can get the contents of the file: .git/refs/heads/master

This can be coded with something like:

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

Solution 3 - node.js

Using nodegit, with path_to_repo defined as a string containing the path to the repo you want to get the commit sha for. If you want to use the directory your process is running from, then replace path_to_repo with 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
} );

Solution 4 - node.js

I was inspired by edin-m's "Solution #2 (no git required)", but I didn't like the substring(5) part which felt like a dangerous assumption. I feel my RegEx is much more tolerant to the variations allowed in git's loose requirements for that file.

The following demo shows that it works for both a checked out branch and a "detached 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

Solution 5 - node.js

If you are always on specific branch, you can read .git/refs/heads/<branch_name> to easily get commit hash.

const fs = require('fs');
const util = require('util');

util.promisify(fs.readFile)('.git/refs/heads/master').then((hash) => {
    console.log(hash.toString().trim());
});

Solution 6 - node.js

Here's a version I worked up that uses fs.promises and 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();

Solution 7 - node.js

You can also use git-fs (it's name on npm is git-fs, on Github it's node-git.)

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

The same module can read directories and files from the repo.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNoahView Question on Stackoverflow
Solution 1 - node.jsantoine129View Answer on Stackoverflow
Solution 2 - node.jsedin-mView Answer on Stackoverflow
Solution 3 - node.jsPaulView Answer on Stackoverflow
Solution 4 - node.jsBruno BronoskyView Answer on Stackoverflow
Solution 5 - node.jshakatashiView Answer on Stackoverflow
Solution 6 - node.jsergView Answer on Stackoverflow
Solution 7 - node.jsNoahView Answer on Stackoverflow