Creating a Git Pre-Commit Hook to Check Package Version Changes
Tags: webdev, git, react, terminal
Published: 2023-07-25 05:40:31

**Introduction**:
When working on projects with multiple contributors, it's essential to maintain consistency and track version changes accurately. In this blog, we'll explore how to create a pre-commit hook using Python that checks if the version in the `package.json` file has been modified before allowing a commit. This simple step can prevent accidental version changes and ensure a smooth development process.

**Prerequisites**:

- A Git repository with a `package.json` file containing a `"version"` field.

Step 1: Creating the Python Script
First, let's create a Python script that will perform the version check. Save the following code as `pre-commit.py`:

```python
import json
import os
import sys

def read_package_version():
    with open("package.json") as f:
        data = json.load(f)
    return data.get("version")

def check_version_change():
    old_version = read_package_version()
    new_version = os.popen("git show HEAD:package.json").read()
    new_version = json.loads(new_version).get("version")

    if old_version != new_version:
        return True
    else:
        print("No changes to package version. Commit aborted.")
        return False

if __name__ == "__main__":
    if not check_version_change():
        sys.exit(1)
```

Step 2: Making the Script Executable
Before we use the script as a Git hook, we need to make it executable. Open your terminal and run:

```bash
chmod +x pre-commit.py
```

Setting the execution permission for the script using `chmod +x pre-commit.py` is specific to Linux/macOS. However, on Windows, this step is not necessary as Windows doesn't use execute permissions like Unix-based systems.

Step 3: Setting Up the Hook
Now, let's create a symbolic link from the script to the Git's `pre-commit` hook:

```bash
ln -s ../../pre-commit.py .git/hooks/pre-commit
```

Creating Symbolic Link:
The command to create a symbolic link to the pre-commit script using `ln -s ../../pre-commit.py .git/hooks/pre-commit` is specific to Linux/macOS. On Windows, you can use the mklink command to achieve the same result.

For Windows, you can create a symbolic link using the following command:

```cmd
mklink .git\hooks\pre-commit ..\..\pre-commit.py
```

Step 4: Explanation of the Script
Now that we have the script set up as a pre-commit hook, let's understand how it works:

- The `read_package_version()` function reads the `"version"` field from the `package.json` file.

- The `check_version_change()` function performs the version comparison. It first fetches the current version from the staged version of `package.json` using `git show HEAD:package.json`. It then compares it with the previous version from the latest commit. If the versions differ, it returns `True`, allowing the commit. Otherwise, it prints a message and returns `False`, aborting the commit.

Step 5: Testing the Pre-Commit Hook
Now, whenever you attempt to commit changes, the pre-commit hook will automatically execute. It will check if the version in `package.json` has been changed. If the version has been updated, the commit will proceed as usual. If there are no changes to the version, the commit will be aborted with the message "No changes to package version. Commit aborted."

Conclusion:
By implementing this simple pre-commit hook, you can ensure that version changes in your `package.json` file are tracked accurately. This prevents unintentional version changes and helps maintain a more organized development process within your team.

Whenever you commit your code, if `package.json` is not staged for commit or even it is staged but the `"version"` is not changed. With this hook in place, you can confidently manage version changes in your project and improve collaboration among team members. Happy coding!