A short story of naming git-branch from a lazy coder
Well, I’m a developer. Using git is somehow my daily job. I’m not very keen on typing command on the console, especially with long commands. In my previous company, we didn’t create a branch for each feature, just dev
or master
branch for all (of course, release-xxx
branch for releasing). After joining the current company and feature branches are mandatory, I start seeing my bad on this. First, I use UI for switching between branches. My tools go from Android Studio (which I mainly use for Android dev) to SourceTree (which I have known for a long time) and to Fork (a new UI git tool). I’m happy with Fork.
With the support from UI tools, I usually created very long branch name like
git checkout -b ABC0123-fix-for-wrong-stuffs-someone-did-wrongly
(which ABC0123
is feature ID). However, whenever I use the console to switch between branches, it doesn’t work well although it has quite descriptive information. I decided to change, not that long branch name anymore. No more -fix-for-wrong-stuffs-that-someone-did-wrongly
, the new branch naming will go with just
git checkout -b ABC0123
or
git checkout -b ABC0123-fix
Well, with the new naming, I can switch branches easier but I don’t know what is a branch for. I have to do one more check: copy the branch name, look up in the feature dictionary (JIRA). I’m a super lazy dev, and also lack of short-term memory ability. After a day or two, I forget.
Hmm, I’m lazy and I’m in a dilemma of branch naming. Long names contain enough information but require typing very much. Short names are easy to type but lack of information.
I need to change once more. My requirement is: a short name with information.
First approach: create my own script for saving and reading the description with just branch name. Here is my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# git-branch-info.py
import sys, json, os.path
def read_file(filepath):
if not os.path.exists(filepath):
return {}
with open(filepath) as file:
return json.loads(file.read())
def get_branch_info(filepath, git_path, branch):
tree = read_file(filepath)
git_tree = tree.setdefault(git_path, {})
return git_tree.setdefault(branch, 'Not found')
def set_branch_info(filepath, git_path, branch, info):
tree = read_file(filepath)
git_tree = tree.setdefault(git_path, {})
git_tree[branch] = info
with open(filepath, 'w') as file:
file.write(json.dumps(tree))
def main(args):
filepath = args[1]
git_path = args[2]
branch = args[3]
if args[0] == 'get':
branch_info = get_branch_info(filepath, git_path, branch)
print(branch_info)
else:
info = args[4]
set_branch_info(filepath, git_path, branch, info)
if __name__ == '__main__':
main(sys.argv[1:])
With this python script, I created bash files for automatically getting such required information
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# git-branch-info.sh
infoFile="$HOME/.git-branch-info.json"
gitPath=`git rev-parse --show-toplevel`
workingBranch=`git symbolic-ref --short HEAD`
command=${1:-'get'}
python3 $(dirname "$0")/git-branch-info.py "$command" $infoFile
$gitPath $workingBranch "$2"
# git-checkout-with-info.sh
git checkout $1
sh $(dirname "$0")/git-branch-info.sh
# git-new-branch-with-info.sh
git checkout $1
sh $(dirname "$0")/git-branch-info.sh new "$2
Yes, I was happy with this script. Very smart! Hahaha.
Soon, I realized that how stupid I was (just 5 minutes after pushing those files). I remembered that we could set a description to a branch:
git config branch.<branchName>.description <description>
and also get the description:
git config branch.<branchName>.description
I came up with a new solution: using branch description for saving and reading branch information. Luckily, I just knew how to use git alias
a couple days ago. So, I could embed the new commands into aliases. Here is my final solution:
to = !git checkout $1 && git config branch.$1.description && :
new = !git checkout -b $1 &&
git config branch.$1.description \""${2:-'Not set'}"\" && :
desc = !git config branch.`git symbolic-ref --short
HEAD`.description && :
setdesc = !git config branch.`git symbolic-ref --short
HEAD`.description \""$1"\" && :
Usage:
git to branchname # switch branch and print description
git new branchname "a description" # create a new branch with
description
git desc
git setdesc "a description"
For listing all having description branches:
branches=`git branch --list`
for branch in $branches; do
cleanBranchName=${branch//\*\ /}
description=`git config branch.$cleanBranchName.description`
[ -z "$description" ] || printf "%-15s %s\n" "$branch" "$description"
done
Phew!
Update
2019/05/03
I add a new bash code for no branch name required as below.
1
2
3
4
5
6
7
8
9
10
11
12
13
allBranches=`git branch`
word=0123456789abcdefghijklmnopqrstuvwxyz
for i in $(seq 1 ${#word})
do
newBranch=$1${word:i-1:1}
if [[ $allBranches != *$newBranch* ]]; then
echo "-> $newBranch"
git checkout -b $newBranch
git config branch.$newBranch.description \""${2:-'Not set'}"\"
exit 0
fi
done
echo "Fail. Please clean up or choose another prefix"
and set the alias for git in ~/.gitconfig
new = !sh ~/path/to/script.sh \""$@"\" && :
With the new script, we just need to type:
git new <prefix> [description]
The branch name will be a combination of prefix and one of the characters in [0–9a-z]
.
2019/05/13
New script for naming in sequence (similar to above but in reverse order)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
allBranches=`git branch`
word=0123456789abcdefghijklmnopqrstuvwxyz
wlen=${#word}
for i in $(seq ${wlen-1} -1 1)
do
newBranch=$1${word:i-1:1}
preBranch=$1${word:i-2:1}
if [[ $allBranches == *\ $preBranch* ]] && [[ $allBranches != *\ $newBranch* ]] ; then
echo "-> $newBranch"
git checkout -b $newBranch
git config branch.$newBranch.description "${2:-Not set}"
exit 0
fi
done
echo "Fail. Please clean up or choose another prefix"
2019/05/22
I found a bug for the 2019/05/13’s script that it cannot create a new branch if there are no branches matching prefixN
which N is a character from word
. Correct: change the if condition to:
[[ ($allBranches == *\ $preBranch* || $i == 1) && $allBranches != *\ $newBranch* ]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Full script:
allBranches=`git branch`
word=0123456789abcdefghijklmnopqrstuvwxyz
wlen=${#word}
for i in $(seq ${wlen-1} -1 1)
do
newBranch=$1${word:i-1:1}
preBranch=$1${word:i-2:1}
if [[ ($allBranches == *\ $preBranch* || $i == 1) && $allBranches != *\ $newBranch* ]] ; then
echo "-> $newBranch"
git checkout -b $newBranch
git config branch.$newBranch.description "${2:-Not set}"
exit 0
fi
done
echo "Fail. Please clean up or choose another prefix"