How to count commits in a specific branch – 如何计算一个git 分支里的 commit数量?

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:

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.