Operations 7 min read

Implementing Server-Side Git Hooks for Changelog Validation

This article explains how to enforce changelog standards in GitLab by configuring server‑side Git hooks that validate commit messages, providing step‑by‑step instructions, environment setup, and both shell and Python script examples to automatically reject non‑conforming pushes.

360 Quality & Efficiency
360 Quality & Efficiency
360 Quality & Efficiency
Implementing Server-Side Git Hooks for Changelog Validation

When receiving new code, checking the git log and maintaining a proper CHANGELOG is essential; this article explains how to enforce changelog standards using Git server‑side hooks in GitLab.

Server‑side Git hooks (pre‑receive, update, post‑receive) run on the GitLab server after a push; the pre‑receive hook can reject commits that do not meet the required format.

Configuration steps include locating the repository’s physical path via the GitLab PostgreSQL database, creating a custom_hooks directory, adding a pre-receive script, and setting executable permissions (chmod +777).

The provided shell script reads commit information, checks that the commit message starts with “modify”, and aborts the push with a non‑zero exit code if the check fails.

#!/bin/bash

echo "开始提交信息检查..."

# 从标准输入获取本次提交的commit id及分支的信息
read normalInput
ARR=($normalInput)
parentCommitId=${ARR[0]}
currentCommitId=${ARR[1]}
branch=${ARR[2]}

echo "您提交的分支为:$branch"

# 获取commit的信息,用户,邮箱,msg等
user=$(git log --pretty=format:"%an" $currentCommitId -1)
echo "提交者为:$user"

commitDate=$(git log --pretty=format:"%cd" $currentCommitId -1)
echo "提交日期为:$commitDate"

msg=$(git log --pretty=format:"%s" $currentCommitId -1)
echo "提交的备注为:$msg"

flag=$(echo $msg | grep "modify.*")
if [ -z "$flag" ]; then
    echo "[ERROR]提交信息校验未通过,需以modify开头"
    exit 1
fi

A Python version of the hook performs similar validation, converting timestamps to a common timezone, ignoring merge‑request commits, and ensuring commit messages start with a JIRA ticket pattern; it exits with an error when the pattern is missing.

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import sys, re, datetime
import fileinput
import shlex, subprocess
import dateutil.parser
import pytz

def datestring2timezone(datestring, timezone='Asia/Shanghai', dateformat='%Y-%m-%d %H:%M:%S'):
    """将带有时区的时间统一化规定的时区时间
    :param datestring: svn/git时间, eg:2011-01-19T05:13:13.421543Z,2018-11-09 17:38:37 +0800
    :param timezone: 统一时区,默认是中国时区
    :param dateformat: 转换成时间格式
    :return:
    """
    local_time = dateutil.parser.parse(datestring).astimezone(pytz.timezone(timezone))
    da = datetime.datetime.strftime(local_time, dateformat)
    return da

print("Begin check your commit info")
origin_commit, curr_commit, branch = None, None, None
for line in fileinput.input():
    line_list = line.strip().split()
    if len(line_list) >= 3:
        origin_commit, curr_commit, branch = line_list[:3]
        break

commit_user = subprocess.check_output(shlex.split('git log --pretty=format:"%an" {} -1'.format(curr_commit)), shell=False)
commit_date = subprocess.check_output(shlex.split('git log --pretty=format:"%cd" {} -1'.format(curr_commit)), shell=False)
commit_msg = subprocess.check_output(shlex.split('git log --pretty=format:"%s" {} -1'.format(curr_commit)), shell=False)

RULE_MERGE_REQUEST = r'^Merge branch .*(into|.*)'
if re.search(RULE_MERGE_REQUEST, str(commit_msg), flags=0):
    commit_user = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%an" -1'), shell=False)
    commit_date = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%cd" -1'), shell=False)
    commit_msg = subprocess.check_output(shlex.split('git log --no-merges --date-order --pretty=format:"%s" -1'), shell=False)

start_date = "2021-07-07 19:00:00"
if start_date >= datestring2timezone(commit_date):
    sys.exit(0)

if not re.search(r'^JIRA-[0-9]{4,6}', str(commit_msg), flags=0):
    print("ERROR:Comment must start with DPT-
. E.g.: DPT-1234")
    sys.exit(1)
sys.exit(0)

After configuring the hook, a local push that violates the rules is rejected, demonstrating the enforcement mechanism; further extensions can integrate with tools like JIRA for richer workflows.

GitLabvalidationgitChangelogserver-side hook
360 Quality & Efficiency
Written by

360 Quality & Efficiency

360 Quality & Efficiency focuses on seamlessly integrating quality and efficiency in R&D, sharing 360’s internal best practices with industry peers to foster collaboration among Chinese enterprises and drive greater efficiency value.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.