-
-
Save schacon/e9e743dee2e92db9a464619b99e94eff to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# Colors | |
RED='\033[0;31m' | |
GREEN='\033[0;32m' | |
NO_COLOR='\033[0m' | |
BLUE='\033[0;34m' | |
YELLOW='\033[0;33m' | |
NO_COLOR='\033[0m' | |
width1=5 | |
width2=6 | |
width3=30 | |
width4=20 | |
width5=40 | |
# Function to count commits | |
count_commits() { | |
local branch="$1" | |
local base_branch="$2" | |
local ahead_behind | |
ahead_behind=$(git rev-list --left-right --count "$base_branch"..."$branch") | |
echo "$ahead_behind" | |
} | |
# Main script | |
main_branch=$(git rev-parse HEAD) | |
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" "Ahead" "Behind" "Branch" "Last Commit" " " | |
# Separator line for clarity | |
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" "-----" "------" "------------------------------" "-------------------" " " | |
format_string="%(objectname:short)@%(refname:short)@%(committerdate:relative)" | |
IFS=$'\n' | |
for branchdata in $(git for-each-ref --sort=-authordate --format="$format_string" refs/heads/ --no-merged); do | |
sha=$(echo "$branchdata" | cut -d '@' -f1) | |
branch=$(echo "$branchdata" | cut -d '@' -f2) | |
time=$(echo "$branchdata" | cut -d '@' -f3) | |
if [ "$branch" != "$main_branch" ]; then | |
# Get branch description | |
description=$(git config branch."$branch".description) | |
# Count commits ahead and behind | |
ahead_behind=$(count_commits "$sha" "$main_branch") | |
ahead=$(echo "$ahead_behind" | cut -f2) | |
behind=$(echo "$ahead_behind" | cut -f1) | |
# Display branch info | |
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" $ahead $behind $branch "$time" "$description" | |
fi | |
done | |
Neat! A while ago I wrote https://github.com/jlebon/git-bstatus in the same vein. Some may find it overkill depending on their needs.
One-liner with similar functionality:
git for-each-ref --color --sort=-committerdate --format=$'%(color:red)%(ahead-behind:HEAD)\t%(color:blue)%(refname:short)\t%(color:yellow)%(committerdate:relative)\t%(color:default)%(describe)' refs/heads/ --no-merged | \ sed 's/ /\t/' | \ column --separator=$'\t' --table --table-columns='Ahead,Behind,Branch Name,Last Commit,Description'
for macos:
bb = !git for-each-ref --color --sort=-committerdate --format=$'%(color:red)%(ahead-behind:HEAD)\t%(color:blue)%(refname:short)\t%(color:yellow)%(committerdate:relative)\t%(color:default)%(describe)' refs/heads/ --no-merged | sed 's/ /\t/' | column -s=$'\t' -t -c 'Ahead,Behind,Branch Name,Last Commit,Description'
column
in macos is BSD (not GNU) and has different argument names.
Thanks for the amazing script !
One change for anyone not wanting two fatal errors and some more output, when you run it by mistake from a directory which is not git repo:
diff --git a/git-better-branch.sh b/git-better-branch.sh
index 6281256f32d3..47d04496658f 100755
--- a/git-better-branch.sh
+++ b/git-better-branch.sh
@@ -27,6 +27,11 @@ count_commits() {
# Main script
main_branch=$(git rev-parse HEAD)
+if [ $? -ne 0 ]; then
+ # If 'git rev-parse' failed, probably we are not in a git repo, fail now
+ exit 1
+fi
+
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" "Ahead" "Behind" "Branch" "Last Commit" " "
# Separator line for clarity
I might be a bit too late, but none of the above is working out for me. Is it depecrated? or am I dumb
I'm using macos, the solution proposed by @evilr00t for macos doesn't show any output.
the .sh file gives an empty table with no branches. I did git branch -a to make sure I'm in the correct path.
Is there any suggestions?
@Azzam-Alotaibi Hey, i found out that cloning a repository only checkouts the default branch. This script only shows the branches you have checked out. And this script does not show the default branch.
It uses git for-each-ref
command to get all the branches and selects the branches that starts with refs/heads
To checkout all the remote branches at once, run this in bash:
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master `; do
git branch --track ${branch#remotes/origin/} $branch
done
I realized this script only uses local branches so if your branches change remotely this may not show accurate information. I need to test if this is the case.
I think
ahead-behind
field was added ingit 2.41
..?