3

I want to the hook to do something like run NPM install after merge branch but only if package.json file is being modified

I'm not sure if I'm doing it correctly, please find my post-merge below

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

differenceCode=$git diff HEAD^ HEAD --exit-code -- ./package.json

echo "test - $?"

if [ "$?" != 0 ]; then 
npm install
fi

I can run git diff HEAD^ HEAD --exit-code -- ./package.json from bash and also echo $? show me 1 when there are changes in package.json else it return me 0.

However when I included that command in the post-merge file, and trigger the post-merge event it show me:

diff: unknown option -- exit-code
diff: Try 'diff --help' for more information.
husky - post-merge hook exited with code 2 (error)

Anyone can help me with this please.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Here's a great article I found while researching this: https://jshakespeare.com/use-git-hooks-and-husky-to-tell-your-teammates-when-to-run-npm-install/ – CTS_AE Feb 08 '23 at 19:15

1 Answers1

3

You wrote:

differenceCode=$git diff HEAD^ HEAD --exit-code -- ./package.json

in your script. (Why did you put a dollar sign $ in front of git?)

This is the immediate source of your problem. $git is an unset variable; in sh, unset variables expand to nothing; so you are running the command:

diff HEAD^ HEAD --exit-code -- ./package.json

and not the command:

git diff HEAD^ HEAD --exit-code -- ./package.json

If you remove the stray $ sign, that problem will go away.

Your subsequent:

echo "test - $?"

will show the exit code from the command you ran, if it gets executed. The fact that it doesn't get executed indicates that the line:

. "$(dirname "$0")/_/husky.sh"

must have set the -e option ("exit on error"). If it did that, you don't need a subsequent test. But there is another error here:

echo "test - $?"

if [ "$?" != 0 ]; then 
npm install
fi

You would need to remove the echo command, because echo itself is a command, and as such, it sets the $? last-command exit status variable. So if echo succeeds—it almost always does—it will set $? to zero.

If -e is set, as it appears to be, we won't get this far if $? is not zero. Since -e is set, it's important not to allow the git diff command to cause the script to exit early. To fix that, replace the whole sequence with:

if git diff HEAD^ HEAD --exit-code -- ./package.json; then
    # ... code to handle a zero exit code here
else
    # ... code to handle a nonzero exit here
fi

The test will now work even with -e set.

You can simplify this a bit since you have nothing to do in the then section by writing:

if ! git diff HEAD^ HEAD --exit-code -- ./package.json; then
    npm install
fi

and once you do that, you can simplify this one more step by writing:

git diff HEAD^ HEAD --exit-code -- ./package.json || npm install

but the main things to do are:

  1. remove the $;
  2. move the git diff command into the if test.

These are what's required; everything else is optional.

torek
  • 448,244
  • 59
  • 642
  • 775
  • thanks for the reply, I have changed the code to `c #!/bin/sh . "$(dirname "$0")/_/husky.sh" if git diff HEAD^ HEAD --exit-code -- ./package.json; then npm install fi` if I'm correct it will only run npm install if there is changes for package.json. However I found it always run npm install even package.json doesn't have any changes. Is there something I'm wrong or I have to add to make it work? – user7755725 Nov 19 '21 at 06:34
  • `if git diff ...; then list; of; commands; fi` runs the commands if the `git diff` program exits *zero*. That's why I said you need to put them in the `else` section, or use one of the fancier alternatives. – torek Nov 19 '21 at 06:36