@ GIT CLI
Definition file gi.def
The definition file contains command definitions for the CLI builder.
@ GIT
aliasLeadChars: gi
# ---------------------------------------------------------------------------------------
= GENERAL
# ---------------------------------------------------------------------------------------
add commit push (acp) [<-f|--force>] [<message>] ::
force_yn=n
if [[ $1 == -f || $1 == --force ]]; then
force_yn=y
shift
fi
if [[ "$1" == "" ]]; then
message="Various"
else
message="$1"
fi
[ -f ./gen-readme ] && ./gen-readme
git add .
git status
if [[ "$1" != "-f" ]]; then
read -p 'Press a key to continue, CTRL-C to abort' dummy
fi
git commit -m 'Various'
git push origin
list branches local (lbl) [-d] ::
if [[ $1 == -d ]]; then
git branch --format='%(creatordate:short), %(refname:short)' | column -s, -t | sort
else
git branch --format='%(creatordate:short), %(refname:short)' | column -s, -t
fi
## -d - order by commit data
list branches remote (lbr) [-d] ::
if [[ $1 == -d ]]; then
git branch -r --format='%(creatordate:short), %(refname:short)' | column -s, -t | sort
else
git branch -r --format='%(creatordate:short), %(refname:short)' | column -s, -t
fi
## -d - order by commit data
clone (c) <url> ::
git clone $1
create archive (ca) <name> ::
git archive --format-zip HEAD -o $1.zip
## Create <name>.zip - contains the contents of the current checked out repo (no .git)
create bundle (cb) <name> ::
git bundle create $1.bundle --all
## Creates <name>.bundle - contains the repo with history
fetch (f) :: git fetch
history (h) ::
git log > /tmp/gi1
while read line; do echo $line
if [[ ${line:0:6} == commit ]]; then
git diff-tree --no-commit-id --name-only -r ${line:7:99} |
tr "\n" " " | fold -s -w 100; echo
fi
done < /tmp/gi1 |
sed "s/^ *//; /^$/d; s/^commit/${l80}\n${c_yel}Commit:/" |
sed "s/^Author/${c_lcya}Author/; s/^Date/${c_lgre}Date/; s/$/${c_whi}/"
rm -f /tmp/gi1 /tmp/gi2
pull (pu) ::
git pull
push origin (po) ::
git push origin
cmd gitsearch() {
show_branch_yn=n
if [[ $1 == -b ]]; then
show_branch_yn=y
fi
rm -f /tmp/gi-cli.tmp*
grep_args=""
[ -n "$1" ] && grep_args="$grep_args --grep=$1"
[ -n "$2" ] && grep_args="$grep_args --grep=$2"
[ -n "$3" ] && grep_args="$grep_args --grep=$3"
git log --all --oneline --all-match $grep_args > /tmp/gi-cli.tmp2
if [[ $show_branch_yn == n ]]; then
cat /tmp/gi-cli.tmp2
else
echo "$(wc -l < /tmp/gi-cli.tmp2) hits - fetching branch details"
while read hash msg; do
branches=$(git branch --all --contains "$hash" | head -1 | sed 's/^ *//')
echo "$branches || $msg" >> /tmp/gi-cli.tmp
printf "."
done < /tmp/gi-cli.tmp2
echo; column -s "||" -t < /tmp/gi-cli.tmp
fi
rm -f /tmp/gi-cli.tmp*; }
search commit messages (scm) [<-b>] <word> [<word>] [<word>] ::
gitsearch $1 $2 $3
## (-b show branch name)
status (s) :: git status
switch branch (sb) <branch-name> ::
git checkout $1 ## (git checkout)
Alias file
The alias file contains:
-
Shortcut alias commands generated by the CLI builder.
-
A CLI command completer for the shortcut commands where one is defined in the CLI definition file.
# Completion function
_gi_complete() {
local cur prev all
all=""
for ((i = 1; i < ${#COMP_WORDS[@]}; i++)); do
word="${COMP_WORDS[i]}"
[[ $word != -* ]] && all+="$word "
done
all="$(echo $all | xargs)"
cur="${COMP_WORDS[COMP_CWORD]}"
prev_step=1
prev="${COMP_WORDS[COMP_CWORD-$prev_step]}"
while [[ "${prev:0:1}" == "-" ]]; do
let prev_step=prev_step+1
prev="${COMP_WORDS[COMP_CWORD-$prev_step]}"
done
}
complete -F _gi_complete gi @gihe @giacp @gilbl @gilbr @gic @gica @gicb @gif @gih @gipu @gipo @giscm @gis @gisb
# Shortcut aliases
alias @gihe='gi gihe'
alias @giacp='gi giacp'
alias @gilbl='gi gilbl'
alias @gilbr='gi gilbr'
alias @gic='gi gic'
alias @gica='gi gica'
alias @gicb='gi gicb'
alias @gif='gi gif'
alias @gih='gi gih'
alias @gipu='gi gipu'
alias @gipo='gi gipo'
alias @giscm='gi giscm'
alias @gis='gi gis'
alias @gisb='gi gisb'
Bash script
The CLI bash script is generated by the CLI builder based on the definition file. This is the CLI implementation.
#!/usr/bin/env bash
debug_yn=n
[[ "$1" == "-d" ]] && { debug_yn=y; shift; }
[[ "${CLI_DEBUG^^}" == "TRUE" ]] && debug_yn=y
C_CYA="\x1b[96m" C_GRE="\x1b[92m" C_MAG="\x1b[95m" C_WHI="\x1b[97m" C_DEF="\x1b[0m"
# param 1 - actual number of parameters
# param 2 - required number of parameters
# param 3 - incorrect parameters message
check_params() {
[[ "$1" < "$2" ]] && { echo -e "$3"; exit; }
}
print_command() {
[[ $debug_yn == y ]] && { echo "COMMAND: $*" | sed 's/"/\"/g'; echo "COMMAND: $*" | sed 's/./-/g'; }
}
section="HELP"
if [[ "$1" == "help" || "$1" == "gihe" ]]; then
[[ "$1" == "gihe" ]] && shift || shift 1
usage="\x1b[95mhelp \x1b[96m(gihe)\x1b[97m [filter]\x1b[92m # Show help, optionally filtered by pattern\x1b[0m"
check_params $# 0 "Usage: $usage"
echo -e "\x1b[92m---\x1b[0m"
echo -e "\x1b[92mGIT\x1b[0m"
echo -e "\x1b[92m---\x1b[0m"
echo -e "\x1b[95mgenerated:2026-09-14 17:03\x1b[0m"
echo
filter="$1"
if [[ -n "$filter" ]]; then
# Show all section headers but only matching commands
while IFS= read -r line; do
if [[ "$line" =~ ^section= ]]; then
# Always show section headers
echo -e "\x1b[92m${line#section=}\x1b[0m"
elif [[ "$line" =~ usage= ]]; then
# Show command if it matches the filter
cmd_line="${line#*usage=}"
if echo "$cmd_line" | grep -iq "$filter"; then
echo -e " $cmd_line"
fi
fi
done < <(egrep "^section=|^ usage=" "$0" | sed 's/\"//g')
else
# Show everything
while IFS= read -r line; do echo -e "${line}${CRESET}"; done < <(egrep "^section=|^ usage=" "$0" | sed "s/.*usage=/ /; s/.*section=/\x1b[92m/; s/\"//g")
fi
exit
fi
section="GENERAL"
if [[ "$1 $2 $3" == "add commit push" || "$1" == "giacp" ]]; then
[[ "$1" == "giacp" ]] && shift || shift 3
usage="\x1b[95madd commit push \x1b[96m(giacp)\x1b[97m [-f|--force] [message]\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " force_yn=n; if [[ $1 == -f || $1 == --force ]]; then; force_yn=y; shift; fi; if [[ \"$1\" == \"\" ]]; then; message=\"Various\"; else; message=\"$1\"; fi; [ -f ./gen-readme ] && ./gen-readme; git add .; git status; if [[ \"$1\" != \"-f\" ]]; then; read -p 'Press a key to continue, CTRL-C to abort' dummy; fi; git commit -m 'Various'; git push origin"
force_yn=n
if [[ $1 == -f || $1 == --force ]]; then
force_yn=y
shift
fi
if [[ "$1" == "" ]]; then
message="Various"
else
message="$1"
fi
[ -f ./gen-readme ] && ./gen-readme
git add .
git status
if [[ "$1" != "-f" ]]; then
read -p 'Press a key to continue, CTRL-C to abort' dummy
fi
git commit -m 'Various'
git push origin
exit
fi
if [[ "$1 $2 $3" == "list branches local" || "$1" == "gilbl" ]]; then
[[ "$1" == "gilbl" ]] && shift || shift 3
usage="\x1b[95mlist branches local \x1b[96m(gilbl)\x1b[97m [-d]\x1b[92m # -d - order by commit data\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " if [[ $1 == -d ]]; then; git branch --format='%(creatordate:short), %(refname:short)' | column -s, -t | sort; else; git branch --format='%(creatordate:short), %(refname:short)' | column -s, -t; fi"
if [[ $1 == -d ]]; then
git branch --format='%(creatordate:short), %(refname:short)' | column -s, -t | sort
else
git branch --format='%(creatordate:short), %(refname:short)' | column -s, -t
fi
exit
fi
if [[ "$1 $2 $3" == "list branches remote" || "$1" == "gilbr" ]]; then
[[ "$1" == "gilbr" ]] && shift || shift 3
usage="\x1b[95mlist branches remote \x1b[96m(gilbr)\x1b[97m [-d]\x1b[92m # -d - order by commit data\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " if [[ $1 == -d ]]; then; git branch -r --format='%(creatordate:short), %(refname:short)' | column -s, -t | sort; else; git branch -r --format='%(creatordate:short), %(refname:short)' | column -s, -t; fi"
if [[ $1 == -d ]]; then
git branch -r --format='%(creatordate:short), %(refname:short)' | column -s, -t | sort
else
git branch -r --format='%(creatordate:short), %(refname:short)' | column -s, -t
fi
exit
fi
if [[ "$1" == "clone" || "$1" == "gic" ]]; then
[[ "$1" == "gic" ]] && shift || shift 1
usage="\x1b[95mclone \x1b[96m(gic)\x1b[97m <url>\x1b[0m"
check_params $# 1 "Usage: $usage"
print_command " git clone $1"
git clone $1
exit
fi
if [[ "$1 $2" == "create archive" || "$1" == "gica" ]]; then
[[ "$1" == "gica" ]] && shift || shift 2
usage="\x1b[95mcreate archive \x1b[96m(gica)\x1b[97m <name>\x1b[92m # Create <name>.zip - contains the contents of the current checked out repo (no .git)\x1b[0m"
check_params $# 1 "Usage: $usage"
print_command " git archive --format-zip HEAD -o $1.zip"
git archive --format-zip HEAD -o $1.zip
exit
fi
if [[ "$1 $2" == "create bundle" || "$1" == "gicb" ]]; then
[[ "$1" == "gicb" ]] && shift || shift 2
usage="\x1b[95mcreate bundle \x1b[96m(gicb)\x1b[97m <name>\x1b[92m # Creates <name>.bundle - contains the repo with history\x1b[0m"
check_params $# 1 "Usage: $usage"
print_command " git bundle create $1.bundle --all"
git bundle create $1.bundle --all
exit
fi
if [[ "$1" == "fetch" || "$1" == "gif" ]]; then
[[ "$1" == "gif" ]] && shift || shift 1
usage="\x1b[95mfetch \x1b[96m(gif)\x1b[97m\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " git fetch"
git fetch
exit
fi
if [[ "$1" == "history" || "$1" == "gih" ]]; then
[[ "$1" == "gih" ]] && shift || shift 1
usage="\x1b[95mhistory \x1b[96m(gih)\x1b[97m\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " git log > /tmp/gi1; while read line; do echo $line; if [[ ${line:0:6} == commit ]]; then; git diff-tree --no-commit-id --name-only -r ${line:7:99} |; tr \"\n\" \" \" | fold -s -w 100; echo; fi; done < /tmp/gi1 |; sed \"s/^ *//; /^$/d; s/^commit/${l80}\n${c_yel}Commit:/\" |; sed \"s/^Author/${c_lcya}Author/; s/^Date/${c_lgre}Date/; s/$/${c_whi}/\"; rm -f /tmp/gi1 /tmp/gi2"
git log > /tmp/gi1
while read line; do echo $line
if [[ ${line:0:6} == commit ]]; then
git diff-tree --no-commit-id --name-only -r ${line:7:99} |
tr "\n" " " | fold -s -w 100; echo
fi
done < /tmp/gi1 |
sed "s/^ *//; /^$/d; s/^commit/${l80}\n${c_yel}Commit:/" |
sed "s/^Author/${c_lcya}Author/; s/^Date/${c_lgre}Date/; s/$/${c_whi}/"
rm -f /tmp/gi1 /tmp/gi2
exit
fi
if [[ "$1" == "pull" || "$1" == "gipu" ]]; then
[[ "$1" == "gipu" ]] && shift || shift 1
usage="\x1b[95mpull \x1b[96m(gipu)\x1b[97m\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " git pull"
git pull
exit
fi
if [[ "$1 $2" == "push origin" || "$1" == "gipo" ]]; then
[[ "$1" == "gipo" ]] && shift || shift 2
usage="\x1b[95mpush origin \x1b[96m(gipo)\x1b[97m\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " git push origin"
git push origin
exit
fi
gitsearch() {
show_branch_yn=n
if [[ $1 == -b ]]; then
show_branch_yn=y
fi
rm -f /tmp/gi-cli.tmp*
grep_args=""
[ -n "$1" ] && grep_args="$grep_args --grep=$1"
[ -n "$2" ] && grep_args="$grep_args --grep=$2"
[ -n "$3" ] && grep_args="$grep_args --grep=$3"
git log --all --oneline --all-match $grep_args > /tmp/gi-cli.tmp2
if [[ $show_branch_yn == n ]]; then
cat /tmp/gi-cli.tmp2
else
echo "$(wc -l < /tmp/gi-cli.tmp2) hits - fetching branch details"
while read hash msg; do
branches=$(git branch --all --contains "$hash" | head -1 | sed 's/^ *//')
echo "$branches || $msg" >> /tmp/gi-cli.tmp
printf "."
done < /tmp/gi-cli.tmp2
echo; column -s "||" -t < /tmp/gi-cli.tmp
fi
rm -f /tmp/gi-cli.tmp*; }
if [[ "$1 $2 $3" == "search commit messages" || "$1" == "giscm" ]]; then
[[ "$1" == "giscm" ]] && shift || shift 3
usage="\x1b[95msearch commit messages \x1b[96m(giscm)\x1b[97m [-b] <word> [word] [word]\x1b[92m # (-b show branch name)\x1b[0m"
check_params $# 1 "Usage: $usage"
print_command " gitsearch $1 $2 $3"
gitsearch $1 $2 $3
exit
fi
if [[ "$1" == "status" || "$1" == "gis" ]]; then
[[ "$1" == "gis" ]] && shift || shift 1
usage="\x1b[95mstatus \x1b[96m(gis)\x1b[97m\x1b[0m"
check_params $# 0 "Usage: $usage"
print_command " git status"
git status
exit
fi
if [[ "$1 $2" == "switch branch" || "$1" == "gisb" ]]; then
[[ "$1" == "gisb" ]] && shift || shift 2
usage="\x1b[95mswitch branch \x1b[96m(gisb)\x1b[97m <branch-name>\x1b[92m # (git checkout)\x1b[0m"
check_params $# 1 "Usage: $usage"
print_command " git checkout $1"
git checkout $1
exit
fi
if [[ "$1" == "" ]]; then
echo "No option passed"
else
echo "$*: invalid option"
fi
echo "Try "gi help" for more information."