KDE’s Gitlab setup has a branch naming rule that I always forget
about – branch names should start with work/ if you want
the server to allow you to rebase and push rebased commits (that is,
only work branches can be --force pushed
to).
I had to abandon and open new PRs a few times now because of this.
Something like this is easy to check on the client side with
pre-commit hooks. (a pre-push hook can also be
used, but I like the check to be as early as possible)
A simple hook script that checks your branch name starts with
work/YOUR_USER_NAME (I like to have the username in the
branch name) is rather simple to write:
#!/bin/bash
REPO_URL=$(git remote get-url origin)
KDE_REPO_HOST="invent.kde.org"
if [[ "${REPO_URL}" == *"${KDE_REPO_HOST}"* ]]; then
BRANCH=$(git rev-parse --abbrev-ref HEAD)
BRANCH_REGEX="^work/$USER/.*$"
if ! [[ $BRANCH =~ $BRANCH_REGEX ]]; then
echo "Your commit was rejected due to its name '$BRANCH', should start with 'work/$USER'"
exit 1
fi
fi
It checks that the Git repository is on invent.kde.org,
and if it is, it checks if the current branch follows the desired naming
scheme.
KDEGitCommitHooks
But the question is where to put this script?
Saving it as .git/hooks/pre-commit in the cloned source
directory would work in general, but there are two problems:
- Manually putting it into every single cloned KDE source directory on your system would be a pain;
KDEGitCommitHooks, which is used by many KDE projects, will overwrite the custompre-commithook script you define.
The second issue is not a problem since a few hours ago.
KDEGitCommitHooks (a part of the
extra-cmake-modules framework) now generates a
pre-commit hook that, additionally to what it used to do
before, executes all the custom scripts you place in the
.git/hooks/pre-commit.d/ directory.
So, if a project uses KDEGitCommitHooks you can save the
aforementioned script as
.git/hooks/pre-commit.d/kde-branches-should-start-with-work.sh
and it should be automatically executed any time you create a new commit
(after KDEGitCommitHooks updates the main
pre-commit hook in your project).
For projects that do not use KDEGitCommitHooks, you will
need to add a pre-commit hook that executes scripts in
pre-commit.d, but more on that in a moment.
Git templates
The first problem remains – putting this into a few hundred local source directories is a pain and error-prone.
Fortunately, Git allows creating a template directory structure which
will be reproduced for any repository you init or
clone.
I placed my template files into ~/.git_templates_global
and added these two lines to ~/.gitconfig:
[init]
templatedir = ~/.git_templates_global
I have two KDE-related hook scripts there.
The above one is saved as
~/.git_templates_global/hooks/pre-commit.d/kde-branches-should-start-with-work.
And the second file is the default main
pre-commit
(~/.git_templates_global/hooks/pre-commit) script:
#!/usr/bin/env bash
# If the user has custom commit hooks defined in pre-commit.d directory,
# execute them
PRE_COMMIT_D_DIR="$(dirname "$0")/pre-commit.d/"
if [ -d "$PRE_COMMIT_D_DIR" ]; then
for PRE_COMMIT_D_HOOK in "$PRE_COMMIT_D_DIR"/*; do
./"$PRE_COMMIT_D_HOOK"
RESULT=$?
if [ $RESULT != 0 ]; then
echo "$PRE_COMMIT_D_HOOK returned non-zero: $RESULT, commit aborted"
exit $RESULT
fi
done
fi
exit 0
It tries to run all the scripts in pre-commit.d and
reports if any of them fail.
This default main pre-commit script will be
used in projects that do not use KDEGitCommitHooks. In the
projects that do, KDEGitCommitHooks will replace it with a
script that executes everything in pre-commit.d same as
this one does, but with a few extra steps.

