Stackoverflow anwser link by Paul Lan
I posted my answer here.
The problem
If you try to google Stackoverflow of how to count commits of a giving branch, you could be disappointed that the best answer you may get, is some like
git rev-list --no-merges --count HEAD ^master
Developers assume you always fork your branch from master
or develop
. That is not always the case, is it?
You may fork your branch out of any parent branch beside master
/ develop
.
So their solution won’t work universally.
The solution
Here I perceive the problem in another way.
Try run the shell script in your git root
:
git log --graph --abbrev-commit --decorate --first-parent HEAD
Here is my screenshot of a testing branch:
Observe the image, you could see, we have the first 3 commits belongs testing branch feature-2
The 4th commit is not.
It’s not very tough to generalize it the pattern:
In Git commit graph, you could see if a commit belongs to a branch, it has the rules:
- If a commit log line containing a commit hash, it brings the tracking BRANCH_NAME if it’s in HEAD or remote (origin/BRANCH_NAME)
- If a commit log line bringing commit hash doesn’t have any of tracking BRANCH_NAME, it belongs to it’s later sibling branch.
So the solution here is trying to apply this pattern and finding the commit count we want. Here is my final code:
#!/bin/bash
# Run production build before push
echo "[INFO] run .git/hooks/pre-push"
echo "[INFO] Check if only one commit"
# file .git/hooks/pre-push
currentBranch=(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
gitLog=(git log --graph --abbrev-commit --decorate --first-parent HEAD)
commitCountOfCurrentBranch=0
startCountCommit=""
baseBranch=""
while read -r line; do
# if git log line started with something like "* commit aaface7 (origin/BRANCH_NAME)" or "commit ae4f131 (HEAD -> BRANCH_NAME)"
# that means it's on our branch BRANCH_NAME
matchedCommitSubstring="( [[line =~ \*[[:space:]]commit[[:space:]].*\((.*)\) ]] && echo {BASH_REMATCH[1]} )"
if [[ ! -z{matchedCommitSubstring} ]];then
if [[ line =~currentBranch ]];then
startCountCommit="true"
else
startCountCommit=""
if [[ -z {baseBranch} ]];then
baseBranch=( [[ {matchedCommitSubstring} =~ (.*)\, ]] && echo{BASH_REMATCH[1]} || echo {matchedCommitSubstring} )
fi
fi
fi
if [[ ! -z{startCountCommit} && line =~ ^\*[[:space:]]commit[[:space:]] ]];then
((commitCountOfCurrentBranch++))
fi
done <<< "gitLog"
if [[ -z {baseBranch} ]];then
baseBranch="origin/master"
else
baseBranch=( [[ {baseBranch} =~ ^(.*)\, ]] && echo{BASH_REMATCH[1]} || echo {baseBranch} )
fi
echo "[INFO] Current commit count of the branch{currentBranch}: {commitCountOfCurrentBranch}"
if [[{commitCountOfCurrentBranch} -gt 1 ]];then
echo "[ERROR] Only a commit per branch is allowed."
echo "[INFO] Try run 'git rebase -i {baseBranch}'"
echo "[INFO] Then run 'git push --force' to update remote branch"
exit 1
fi
npm run build
exit?
The variable commitCountOfCurrentBranch
is the number we want.