0

I'm using nodegit and I can't figure out how to detect whether the there has been changes to commit.

Currently, I'm committing when an external event happens, but I don't know if this will cause a real difference in the files. I don't check whether the commit is empty before pushing, which led me to end up with lots of empty commits, I'd like to avoid that.

When doing it manually, I usually run a git status to check whether there were changes to commit, I was thinking about doing something similar here, but can't figure out how. (here is the documentation)

  console.log('committing...');
  const commitResult = await commitFile(`schema.json`, schemaAsString, `${appName} (${appId})`);
  const statuses = await repo.getStatus();
  console.log('getStatus status', statuses);
  console.log('getStatus status', statuses[0].status());
  console.log('getStatus isModified', statuses[0].isModified());
  console.log('getStatus path', statuses[0].path());
  console.log('getStatus statusBit', statuses[0].statusBit());

  console.log('pushing...');
  const pushResult = await push(repo);
  console.log('pushResult', pushResult);
Vadorequest
  • 16,593
  • 24
  • 118
  • 215
  • 1
    Wow, that documentation does not seem very helpful... I would look for a tutorial, but first naïve search didn't yield much that's useful. To be honest, if you can, I would automate your workflow with a bash script if you can, rather than in JS. In any case, I won't be able to help with this question because I'm just learning JS and TS and have never used nodegit. My Docusaurus example came all pre-built, I just had to trigger it, not program it... – joanis Jun 12 '22 at 20:03
  • Yeah, the documentation is lacking lots of details, the most useful things are the examples: https://github.com/nodegit/nodegit/blob/master/examples/general.js – Vadorequest Jun 12 '22 at 20:08

3 Answers3

1

In general : from the command line, another way to see if there are differences at all is to run git diff HEAD. The diff is empty iff there are no differences.

You seem to care only about schema.json in your script : from the command line that would be git diff HEAD -- schema.json.

If you manage to generate a similar command in nodegit (get the diff for schema.json between HEAD and the worktree ), you can use it as a condition at the very beginning of your script.

LeGEC
  • 46,477
  • 5
  • 57
  • 104
1

I am detecting changes by doing a diff between the head commit and the index like this:

import { Diff, Repository, Tree } from 'nodegit';

const EmptyTree = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';

async function getStagedChanges(repository: Repository) {
  const head = await repository.getHeadCommit();
  const tree = await (head ? head.getTree() : Tree.lookup(repository, EmptyTree));
  const diff = await Diff.treeToIndex(repository, tree);

  return diff;
}

If there is no head commit (i.e. the repository has no commits yet) then I use the empty tree instead to show everything in the index.

Mike Jerred
  • 9,551
  • 5
  • 22
  • 42
0

I figured it out by trying things a bit at random.

I use the Index checksum, and compare it before and after committing.

If the commit is empty, the checksum doesn't change. If the commit isn't empty, the checksum changes.

Based on that, it's easy to write a simple condition to perform the push or not.

  const repo = await clone(repositoryLocalPath);
  console.log('repo', repo);
  const indexBeforeCommit: Index = await repo.refreshIndex();
  const indexBeforeCommitChecksum = indexBeforeCommit.checksum().tostrS();
  console.log('indexBeforeCommit checksum', indexBeforeCommitChecksum);

  console.log('committing...');
  const commitId = await commitFile(`schema.json`, schemaAsString, `Airtable - ${appName} (${appId})`);
  const indexAfterCommit: Index = await repo.refreshIndex();
  const indexAfterCommitChecksum = indexAfterCommit.checksum().tostrS();
  console.log('indexAfterCommit checksum', indexAfterCommitChecksum);

  if (indexBeforeCommitChecksum !== indexAfterCommitChecksum) {
    console.log('pushing...');
    const pushResult = await push(repo);
    console.log('pushResult', pushResult);
  } else {
    console.log('no changes to push');
  }
Vadorequest
  • 16,593
  • 24
  • 118
  • 215
  • 1
    That will always be *safe* (as in, never say "no changes" when there are changes) but it might not be *sufficient* (because a Git index may contain stuff other than the set of files to be committed). In general what you want here is to diff the index contents—the *proposed next commit* as stored *in* the index—against the current or `HEAD` commit. How to do that in nodegit, I have no idea; in command-line Git you'd use `git update-index --refresh` followed by `git diff-index`. These are wrapped into some convenience functions in the shell library `git-sh-setup`. – torek Jun 12 '22 at 21:20
  • Good to know, I think I might need to revisit this implementation in the future. Regarding how to do what you explained with nodegit, I guess `refreshIndex ` followed by https://www.nodegit.org/api/diff/#indexToIndex would achieve what you describe. Considering my code only ever update/commit a single file, doesn't use tags or anything else, the above "simple" way should be sufficient, for now. – Vadorequest Jun 13 '22 at 06:11