git_all_info_list
Git 仓库完整信息 列表美化
一键脚本
bash <(curl -sL https://gitee.com/meimolihan/cmdbox/raw/master/sh/git_all_info_list.sh) /目标目录
bash <(curl -sL ../sh/git_all_info_list.sh) /目标目录
| 模式 | 命令 | 说明 |
|---|---|---|
| 交互模式 | ./脚本名.sh |
默认分析当前目录 |
| 传参模式 | ./脚本名.sh /目标目录 |
分析指定 Git 仓库 |
效果预览
补充说明
该脚本全面展示指定 Git 仓库的详细信息,涵盖仓库基本信息、用户配置、远程仓库、分支标签、提交统计、工作区状态等 12 个维度,适合需要快速了解仓库全貌的场景。
功能特点
- 一键汇总:自动收集并展示 Git 仓库 12 个维度的完整信息,无需逐条敲命令
- 传参灵活:默认分析当前目录,支持通过参数指定目标仓库目录
- 标签详情:逐一展示每个版本标签的创建人、创建时间、绑定提交哈希、提交作者、提交说明,自动将英文星期/月份翻译为中文
- 提交统计:展示仓库总提交次数、跟踪文件总数、全仓库作者提交次数排名
- 差异对比:直观展示本地与远程 main 分支的领先/落后提交数
- 分支展示:区分当前分支(绿色)、远程分支(黄色)、本地分支(白色),一目了然
- 状态着色:工作区变更用颜色区分新增(绿色)、修改(黄色)、删除(红色)
输出说明
脚本输出包含以下信息区块:
| 区块 | 说明 |
|---|---|
| 仓库根目录 | 本地路径、完整提交哈希、简短提交哈希 |
| Git 用户配置 | 本地/全局用户名和邮箱 |
| 远程仓库配置 | 远程名称、仓库地址、同步类型(fetch/push) |
| 当前分支上游关联 | 本地分支名称、关联的远程分支 |
| 本地与远程提交差异 | 领先/落后远程的提交数量 |
| 仓库本地配置 | git config --local 全部键值对 |
| 全部分支列表 | 本地分支(白色)、当前分支(绿色★)、远程分支(黄色) |
| 仓库所有版本标签 | 每个标签的创建人、创建时间、备注、绑定提交、提交作者、提交说明(中文星期/月份) |
| 当前分支最新提交 | 最新一次提交的哈希、作者、时间、备注 |
| 仓库整体提交统计 | 总提交次数、跟踪文件总数 |
| 全仓库提交作者统计 | 每位作者的提交次数 |
| 工作区变更状态 | 新增(绿色)、修改(黄色)、删除(红色) |
| 忽略规则 | .gitignore 文件内容 |
| 仓库底层对象存储统计 | git count-objects -v 输出 |
注意事项
- 指定目录必须是一个已初始化 Git 仓库的目录
- 脚本会自动进入目标目录,执行完毕自动返回原目录
- 领先/落后提交数基于 origin/main 分支计算,需先 git fetch 更新远程信息
- 标签详情仅支持附注标签(annotated tag),轻量标签(lightweight tag)无创建人/时间信息
- 提交说明中的英文 "update" 会自动翻译为中文 "更新"
脚本源码
#!/bin/bash
set -uo pipefail
list_color_init() {
export gl_hui=$'\033[38;5;59m'
export gl_hong=$'\033[38;5;9m'
export gl_lv=$'\033[38;5;10m'
export gl_huang=$'\033[38;5;11m'
export gl_lan=$'\033[38;5;32m'
export gl_bai=$'\033[38;5;15m'
export gl_zi=$'\033[38;5;13m'
export gl_bufan=$'\033[38;5;14m'
export reset=$'\033[0m'
}
list_color_init
break_end() {
echo -e "${gl_lv}操作完成${gl_bai}"
echo -e "${gl_bai}按任意键继续 ${gl_hong}.${gl_huang}.${gl_lv}.${gl_bai}\c"
read -r -n 1 -s -r -p ""
echo ""
clear
}
column_if_available() {
if command -v column &> /dev/null; then
column -t -s $'\t'
else
cat
fi
}
print_title() {
local title="$1"
echo -e "\n${gl_huang}>>>【${title}】${gl_bufan}"
echo -e "${gl_bufan}————————————————————————————————————————————————${gl_bai}"
}
print_kv() {
local k="$1"
local v="$2"
printf "%s%s\t%s%s\n" "${gl_lan}" "${k}" "${gl_bufan}" "${v}" | column_if_available
}
print_single_tag() {
local tag="$1"
echo -e ""
echo -e "${gl_huang}>>>【版本标签】${gl_lv}${tag}${gl_bai}"
echo -e "${gl_bufan}————————————————————————————————————————————————${gl_bai}"
local full_raw
full_raw=$(git show "${tag}" 2>/dev/null | sed '/^diff --git/Q')
if [[ -z "${full_raw}" ]]; then
printf "%s%s\t%s%s\n" "$gl_huang" "提示" "$gl_hong" "标签 ${tag} 读取失败" "$reset" | column_if_available
return 0
fi
echo "${full_raw}" | sed '/^tag '"${tag}"'/d' | awk -v key_color="$gl_lan" -v val_color="$gl_bufan" -v reset="$reset" '
BEGIN {
FS=": "; OFS="\t"
map_key["Tagger"] = "标签创建人"
map_key["Date"] = "标签创建时间"
map_key["commit"] = "绑定提交哈希"
map_key["Author"] = "提交作者"
map_week["Mon"]="周一"; map_week["Tue"]="周二"; map_week["Wed"]="周三"
map_week["Thu"]="周四"; map_week["Fri"]="周五"; map_week["Sat"]="周六"; map_week["Sun"]="周日"
map_month["Jan"]="01月"; map_month["Feb"]="02月"; map_month["Mar"]="03月"; map_month["Apr"]="04月"
map_month["May"]="05月"; map_month["Jun"]="06月"; map_month["Jul"]="07月"; map_month["Aug"]="08月"
map_month["Sep"]="09月"; map_month["Oct"]="10月"; map_month["Nov"]="11月"; map_month["Dec"]="12月"
state = "tag_info"
desc_flag = 0
msg_flag = 0
}
/^commit [0-9a-f]+/ {
sub(/^commit /,"",$0)
print key_color "绑定提交哈希" reset, val_color $0 reset
state = "commit_info"
next
}
state=="tag_info" && /^Tagger/ {
print key_color map_key["Tagger"] reset, val_color $2 reset
desc_flag=0
next
}
state=="tag_info" && /^Date/ {
raw_dt = $2
split(raw_dt, dt, " ")
w=dt[1]; m=dt[2]; day=dt[3]; time=dt[4]; year=dt[5]; zone=dt[6]
cn_week = w in map_week ? map_week[w] : w
cn_month = m in map_month ? map_month[m] : m
cn_dt = year "年" cn_month day "日 " time " " cn_week " " zone
print key_color map_key["Date"] reset, val_color cn_dt reset
desc_flag=0
next
}
state=="tag_info" && NF>0 && !/^[A-Za-z]+: / {
gsub(/^[ \t]+/,"",$0)
if (desc_flag == 0) {
print key_color "标签备注" reset, val_color $0 reset
desc_flag=1
} else {
print key_color "" reset, val_color $0 reset
}
next
}
state=="commit_info" && /^Author/ {
print key_color map_key["Author"] reset, val_color $2 reset
msg_flag=0
next
}
state=="commit_info" && /^Date/ { next }
state=="commit_info" && NF>0 {
gsub(/^[ \t]+/,"",$0)
gsub(/update/,"更新",$0)
if (msg_flag == 0) {
print key_color "提交说明" reset, val_color $0 reset
msg_flag=1
} else {
print key_color "" reset, val_color $0 reset
}
next
}
' | column_if_available
}
git_show_all_info() {
local target_dir="$PWD"
local arg
for arg in "$@"; do
target_dir=$(realpath "$arg")
done
local origin_pwd="$PWD"
if ! cd "${target_dir}"; then
echo -e "${gl_hong}错误:目录 ${target_dir} 不存在或无法进入!${gl_bai}"
break_end
return 1
fi
clear
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo -e "${gl_hong}错误:「${target_dir}」不是合法Git工作仓库!${gl_bai}"
cd "${origin_pwd}"
break_end
return 0
fi
local repo_name
repo_name=$(basename "$PWD")
echo -e "${gl_zi}>>> 项目仓库:${gl_huang}${repo_name}${gl_zi} 完整信息汇总${gl_bai}"
echo -e "${gl_bufan}————————————————————————————————————————————————${gl_bai}"
print_title "仓库根目录"
print_kv "本地路径" "$(git rev-parse --show-toplevel)"
print_kv "完整提交哈希" "$(git rev-parse HEAD)"
print_kv "简短提交哈希" "$(git rev-parse --short HEAD)"
print_title "Git用户配置信息"
print_kv "本地仓库用户名" "$(git config --local user.name 2>/dev/null || echo 未设置)"
print_kv "本地仓库邮箱" "$(git config --local user.email 2>/dev/null || echo 未设置)"
print_kv "全局用户名" "$(git config --global user.name 2>/dev/null || echo 未设置)"
print_kv "全局邮箱" "$(git config --global user.email 2>/dev/null || echo 未设置)"
print_title "远程仓库配置"
git remote -v | awk -v kc="$gl_lan" -v vc="$gl_bufan" -v r="$reset" '{
if(NF==3){
print kc"远程名称"r, vc$1r;
print kc"仓库地址"r, vc$2r;
print kc"同步类型"r, vc$3r;
print ""
}
}' | column_if_available
print_title "当前分支上游关联"
git branch -vv | awk -v kc="$gl_lan" -v vc="$gl_bufan" -v r="$reset" '
/^\*/{
sub(/^\* /,"")
split($0,arr," ")
print kc"本地分支"r,vc arr[1]r
print kc"关联远程分支"r,vc arr[3]r
}' | column_if_available
print_title "本地与远程提交差异"
local ahead_cnt
ahead_cnt=$(git rev-list --count HEAD ^origin/main 2>/dev/null)
local behind_cnt
behind_cnt=$(git rev-list --count ^HEAD origin/main 2>/dev/null)
print_kv "本地领先远程提交数" "${ahead_cnt:-0}"
print_kv "本地落后远程提交数" "${behind_cnt:-0}"
print_title "仓库本地配置"
git config --local --list | awk -v kc="$gl_lan" -v vc="$gl_bufan" -v r="$reset" '
BEGIN{FS="=";OFS="\t"}
{
sub(/=/,"\t");
print kc$1r, vc$2r
}' | column_if_available
print_title "全部分支列表(本地+远程)"
git branch -a | awk -v cur="$gl_lv" -v rem="$gl_huang" -v nor="$gl_bai" '
/^\*/ {print cur "【当前分支】" substr($0,2);next}
/remotes\// {print rem "【远程】" substr($0,9);next}
{print nor "【本地】" $0}
'
print_title "仓库所有版本标签"
local tag_list
tag_list=$(git tag 2>/dev/null | sort -t'v' -k2 -nr)
if [[ -z "${tag_list}" ]]; then
echo -e "${gl_hong}当前仓库无任何版本标签${gl_bai}"
else
echo "${tag_list}"
echo -e "${gl_hui}———— 标签详细信息 ————${gl_bai}"
while IFS= read -r single_tag; do
[[ -z "${single_tag}" ]] && continue
print_single_tag "${single_tag}"
done <<< "${tag_list}"
fi
print_title "当前分支最新提交"
git log --oneline -1 | awk -v c="$gl_lv" '{print c $0}'
echo ""
git show HEAD --pretty=full -q | awk -v kc="$gl_lan" -v vc="$gl_bufan" -v r="$reset" '
BEGIN{FS=": ";OFS="\t"}
/^commit/ {sub(/commit /,"");print kc"提交哈希"r,vc$0r;next}
/^Author/ {print kc"提交作者"r,vc$2r;next}
/^Date/ {print kc"提交时间"r,vc$2r;next}
NF>0 && !/^[A-Za-z]+:/ {
gsub(/^[ \t]+/,"");gsub(/update/,"更新");
print kc"提交备注"r,vc$0r
}' | column_if_available
print_title "仓库整体提交统计"
print_kv "仓库总提交次数" "$(git rev-list --all | wc -l)"
print_kv "仓库跟踪文件总数" "$(git ls-files | wc -l)"
print_title "全仓库提交作者统计"
local stat_log
stat_log=$(git shortlog -sn 2>/dev/null)
if [[ -z "${stat_log}" ]]; then
git log --format="%an <%ae>" | sort | uniq -c | sort -nr | awk -v kc="$gl_lan" -v vc="$gl_bufan" '{
print kc"提交次数"r,vc$1r;
print kc"作者信息"r,vc substr($0,index($0,$2))r;
print ""
}' | column_if_available
else
echo "${stat_log}" | awk -v kc="$gl_lan" -v vc="$gl_bufan" '{
print kc"提交次数"r,vc$1r;
print kc"作者名称"r,vc substr($0,index($0,$2))r;
print ""
}' | column_if_available
fi
print_title "工作区变更状态"
git status -s | awk -v add="$gl_lv" -v mod="$gl_huang" -v del="$gl_hong" '
/^A/ {print add "【新增】" substr($0,4);next}
/^M/ {print mod "【修改】" substr($0,4);next}
/^D/ {print del "【删除】" substr($0,4);next}
{print $0}
'
if [[ -z "$(git status -s)" ]]; then
echo -e "${gl_lv}工作区无未提交修改${gl_bai}"
fi
print_title "忽略规则(.gitignore)"
if [[ -f .gitignore ]]; then
cat .gitignore | awk -v gray="$gl_hui" '{print gray $0}'
else
echo -e "${gl_hong}仓库不存在.gitignore文件${gl_bai}"
fi
print_title "仓库底层对象存储统计"
git count-objects -v | awk -v kc="$gl_lan" -v vc="$gl_bufan" '
BEGIN{FS=": ";OFS="\t"}
{print kc$1r,vc$2r}
' | column_if_available
echo -e "${gl_bufan}————————————————————————————————————————————————${gl_bai}"
cd "${origin_pwd}"
break_end
}
git_show_all_info "$@"
创建本地脚本
new_script="new_test.sh"
cat > "$new_script" << 'EOF'
#!/bin/bash
# 粘贴脚本源码
EOF
chmod +x "$new_script" && ./"$new_script" && rm -f "$new_script"