0

These days I have a problem of pushing package-lock.json unintentionally.

Ex)

I run npm install in my feature branch and my package-lock.json is updated.

I made a commit and my feature branch is merged into develop branch. Package-lock.json in develop branch is overwritten by package-lock.json in my feature branch.

Due to updated packages in package-lock.json, it broke the application.


I know that I have to be careful not to push package-lock.json unless package.json has changed, however, sometime I forget.

So I'm thinking if I can add some rule in pre-commit to show some warning if I commit package-lock.json only. Is there any way to accomplish it?

thank you

aaayumi
  • 1,224
  • 8
  • 27
  • 47
  • 2
    The best approach is to be conscious of what you're committing. Before running `git commit`, run `git diff --cached` and make sure you know what will be included. Better yet, also be careful about what you stage. I know a lot of users blindly use `git add .` or similar, but I believe this is an anti-pattern. I strongly prefer to manually stage changes so I know what I'm committing. You should be the "first reviewer" of your own code. – ChrisGPT was on strike Mar 01 '19 at 15:29
  • Also, how did your feature branch get merged into your develop branch if it breaks develop? This is no different than if you add a database migration, for example. What review process are you using? – ChrisGPT was on strike Mar 01 '19 at 15:38
  • What I want to achieve here is run git commit and automatically check the discrepancy between package-lock.json and package.json. – aaayumi Mar 01 '19 at 16:11
  • Well there shouldn't _be_ a discrepancy between those files. One is generated from the other. And `npm install`, which you mention in your question, shouldn't update versions for already installed packages. Even `npm update` doesn't result in a "discrepancy", though it may update libraries and generate conflicts when you merge. – ChrisGPT was on strike Mar 01 '19 at 16:13

1 Answers1

2

If you are already using Git Hooks like "pre-commit", you can basically add one more script to the "pre-commit" list and write a script that does what you need (code below).

Using a combination of git/grep commands you can check that in the list of staged files, "package.json" and "package-lock.json" are both there (or none of them is).

The script can be:

#!/bin/sh
if [ `git diff --name-only --cached | egrep -c 'package.json|package.lock.json'` == "0" -o `git diff --name-only --cached | egrep -c 'package.json|package.lock.json'` == "2" ]; then
  echo "Checked successfully."
elif [ `git diff --name-only --cached | egrep -c 'package.json'` == "1" -a `git diff --name-only --cached | egrep -c 'package.lock.json'` == "0" ]; then
  echo "Warning: you are committing package.json without package.lock.json"
else
  echo "Error: make sure you commit BOTH package.json and package.lock.json"
  exit 1
fi
exit 0

git diff --name-only --cached gets the list of staged files (file names only)

| use the result of previous command as argument for the next

egrep to perform a search (in this case search for strings 'package.json' and 'package.lock.json')

-c counts the number of matches

Wrapping the whole command in backticks will execute it and provide the result to the main script.

The result of the git+egrep command returns the number of occurrences found. You then check what this result is, to tell the script to continue (exit 0) or quit (exit 1).

Make the script file executable, and add the reference to it in your package.json:

"scripts": {
  "check-package": "./bin/check-package.sh",
}
...
"pre-commit": [
  "check-package"
]

That should be it!

When you are done, just make sure you first commit the script only, and then package.json (otherwise it would already look for the script, without finding it).

Final note: This approach is valid to check any 2 or more files that need to be there at the same time in the list of files staged for commit.