How to configure a local commit hook?
Since the version 5.3.x it is possible to install a local commit hook, which will evaluate the commit message in addition at commit time. Therefore we provide a Rest-API, which you can use to evaluate a commit message at any time in your process.
How to create a commit message hook?
Please create a file “.git/hooks/commit-msg“ in your repository. This file is a Git hook and will be called during a commit. In this file we can now create a Rest-API call, to evaluate the commit message, based on the rules you have configured in the Push Check (see Rest-API Version 1.0.0 ). So you will have always the same configuration, for a local commit message check (at commit time) and remote check (at push time).
Example hook
In general the .git/hooks/commit-msg can be created like in the following example. The example is working and needs only some configuration. But please feel free to change this hook according to your needs or company guidelines.
#!/usr/bin/python3
import sys, re, json, requests
#Load commit message
commitMessageFile = open(sys.argv[1])
commitMessage = commitMessageFile.read().strip()
# Hook configuration
url = "<your Bitbucket URL (e.g. https://bitbucket-server)>"
project = "<your project slug (e.g. project_1)>"
repository = "<your repsitory slug (e.g. rep_1)>"
accessToken = "<your personal accesstoken>"
endpoint = url + "/rest/jhfb/1.0.0/check/commit"
print("Check commit message")
print("End-point: %s" % (endpoint))
headers = {"Authorization": "Bearer %s" % (accessToken)}
payload = {"message": commitMessage, "project-slug": project, "repository-slug" : repository }
# Ask the rest api
resp = requests.post(endpoint, json=payload, headers=headers)
# Everyting fine
if resp.status_code == 200:
print("Commit message is valid")
sys.exit(0)
# The evaluation of the commit message fails
if(resp.status_code == 400):
json_data = json.loads(resp.text)
print("JHFB Commit Message Check")
print("-------------------------------------------")
for answer in json_data['answers']:
print(answer['title'])
print(answer['message'])
sys.exit(1)
# Any other http errors
if(resp.status_code == 404):
print("[%s] Check if Bitbucket is up, the jhfb hook is enabled and configured" % (resp.status_code))
sys.exit(1)
if(resp.status_code == 401):
print("[%s] Unauthorized - Please add your accessToken to the script" % (resp.status_code))
sys.exit(1)
print("[%s] Any other HTTP error" % (resp.status_code))
sys.exit(1)
As you see there is some configuration needed:
url = "<your Bitbucket URL (e.g. https://bitbucket-server)>"
project = "<your project slug (e.g. project_1)>"
repository = "<your repsitory slug (e.g. rep_1)>"
accessToken = "<your personal accesstoken>"
KEY | Description |
---|---|
url | The base url of Bitbucket instance e.g. |
project | The project key of your Bitbucket project. It is needed to access the hook configuration. e.g. PROJECT_1 You can access this key in the URL of your repository:
|
repository | The repository key of your Bitbucket repository. It is needed to access the hook configuration. e.g. rep_1 You can access this key in the URL of your repository:
|
accessToken | A authentication is needed. In our example we use personal access tokens to authenticate the hook agains Bitbucket. Feel free to change this according to your needs or your company guidelines. e.g. NTgsajU0ODE3dsDgzdsOR9dF3SqA8DCYVKzAg4cXAdhz7 The following Atlassian article demonstrate, how you can create a personal access token. https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html |
Of course you can get this information in a dynamic way also. This example shows, how the needed configuration will be created based on the configured origin of the repository. This is just a example and needs to be adjusted to your origin:
# Example: access all data based on repository information
# SSH Example origin = ssh://git@bitbucket-server/project_1/rep_1.git
#get the origin of the repository
stream = os.popen('git config --get remote.origin.url')
originOutput = stream.read()
# extract url, project and repo information based on origin
url = "https://%s" % originOutput.rsplit('/', 3)[-3].rsplit('@', 1)[-1]
project = originOutput.rsplit('/', 2)[-2].strip()
repository = originOutput.rsplit('/', 1)[-1].replace(".git","").strip()
Hook Execution
Remind, that Git hooks needs to be executed. So the executable flag is needed. So please run the following command in your repository.
sudo chmod +x .git/hooks/commit-msg
Python dependencies
The hook needs some has some dependencies. This dependencies needs to be installed
sudo python3 -m pip install requests
How to create a commit message hook in Windows environments?
Windows environment
If you will work with windows it could be more complicated. On Windows, we saw a lot of problems regarding the SHEBANG (e.g. #!/usr/bin/python3
). So you maybe need to use a little trick to make the script executable
Create a wrapper script , which will trigger a python script
#!/bin/sh
#FILE: ./git/hooks/commit-msg
PYTHON = <PATH to your python executable>
$PYTHON .git/hooks/pre-commit.py
Create a python script
Create a python script .git/hooks/pre-commit.py
with the main functionality, like described in our example. See sections above.
Hook Execution
Remind, that Git hooks needs to be executed. So the executable flag is needed. So please run the following command in your repository.
sudo chmod +x .git/hooks/commit-msg .git/hooks/pre-commit.py
How to use the hook?
The usage is transparent. You do not need to do anything. Just commit!
Push hook
Of course the hook will evaluate in addition the behaviour of pushes is as before. No changes