Git历史提交未合并分支统计需求:含已删分支及按时间统计
如何查询Git历史时点的未合并分支数量(含已删除分支)及按周期统计
我来帮你拆解这个问题,分两部分解决:先搞定历史特定时点的未合并分支统计(包括后来被删除的分支),再实现按日/过去X天/月的周期统计。
1. 查看指定历史时点的未合并分支数量(含已删除分支)
Git本身不会主动保存分支的历史状态,但我们可以通过reflog(分支操作日志)和commit历史来还原当时的场景。
步骤1:确定目标时点的master分支状态
首先得拿到你要查询的那个时间点,master分支的最新提交哈希——毕竟我们要对比的是当时的master,不是现在的。
- 如果用具体日期指定时点(比如2023年12月31日):
TARGET_DATE="2023-12-31 23:59:59" # 找到该日期前master的最后一个提交 MASTER_AT_TARGET=$(git log --before="$TARGET_DATE" --pretty=format:"%H" master | head -1)
- 如果已经知道目标时点的commit哈希,直接赋值就行:
MASTER_AT_TARGET="abc123def456..."
步骤2:提取所有曾经存在过的远程分支
Git的reflog会记录所有分支的操作(包括创建、删除、更新),我们可以从中提取所有出现过的远程分支:
# 过滤出所有远程分支名称,去重后得到完整列表 ALL_REMOTE_BRANCHES=$(git reflog show --all | grep -E 'origin/[^ ]+' | awk '{print $5}' | sort | uniq)
注:如果你的远程仓库不是默认的origin,把命令里的origin/换成你的远程名称即可。
步骤3:统计未合并分支数量
遍历每个曾经的远程分支,找到它在目标时点的最新提交,再判断这个提交是否没被合并到当时的master:
UNMERGED_COUNT=0 for BRANCH in $ALL_REMOTE_BRANCHES; do # 获取该分支在目标时点的最后一个提交 BRANCH_COMMIT_AT_TARGET=$(git log --before="$TARGET_DATE" --pretty=format:"%H" "$BRANCH" | head -1) # 如果该分支在当时存在(有有效提交) if [ -n "$BRANCH_COMMIT_AT_TARGET" ]; then # 判断该提交是否未被合并到当时的master # 如果merge-base返回非0,说明未合并 if ! git merge-base --is-ancestor "$BRANCH_COMMIT_AT_TARGET" "$MASTER_AT_TARGET"; then UNMERGED_COUNT=$((UNMERGED_COUNT + 1)) fi fi done # 输出统计结果 echo "在目标时点未合并到master的分支数量:$UNMERGED_COUNT"
2. 按每日/过去X天/月统计未合并分支数量
核心思路就是遍历每个时间节点(比如每天的结束时点),重复上面的统计逻辑,然后输出每个时间点的结果。
示例:统计过去30天每天的未合并分支数量
下面的脚本会自动遍历过去30天的每一天,输出每天的未合并分支数:
# 定义统计的起始和结束日期(这里是过去30天到昨天) START_DATE=$(date -d "-30 days" +%Y-%m-%d) END_DATE=$(date -d "-1 day" +%Y-%m-%d) CURRENT_DATE="$START_DATE" # 循环遍历每一天 while [ "$CURRENT_DATE" != "$(date -d "$END_DATE +1 day" +%Y-%m-%d)" ]; do # 设置当天的结束时点(确保统计的是当天完整状态) TARGET_DATE="$CURRENT_DATE 23:59:59" # 获取当天master的最后一个提交 MASTER_AT_TARGET=$(git log --before="$TARGET_DATE" --pretty=format:"%H" master | head -1) # 如果当天master没有有效提交(比如仓库刚创建),跳过统计 if [ -z "$MASTER_AT_TARGET" ]; then echo "$CURRENT_DATE: 无有效master提交" CURRENT_DATE=$(date -d "$CURRENT_DATE +1 day" +%Y-%m-%d) continue fi # 统计当天的未合并分支数量 UNMERGED_COUNT=0 ALL_REMOTE_BRANCHES=$(git reflog show --all | grep -E 'origin/[^ ]+' | awk '{print $5}' | sort | uniq) for BRANCH in $ALL_REMOTE_BRANCHES; do BRANCH_COMMIT_AT_TARGET=$(git log --before="$TARGET_DATE" --pretty=format:"%H" "$BRANCH" | head -1) if [ -n "$BRANCH_COMMIT_AT_TARGET" ]; then if ! git merge-base --is-ancestor "$BRANCH_COMMIT_AT_TARGET" "$MASTER_AT_TARGET"; then UNMERGED_COUNT=$((UNMERGED_COUNT + 1)) fi fi done # 输出当天的统计结果 echo "$CURRENT_DATE: $UNMERGED_COUNT" # 日期加1天,进入下一轮循环 CURRENT_DATE=$(date -d "$CURRENT_DATE +1 day" +%Y-%m-%d) done
实用优化建议
- 如果统计周期很长(比如几个月),上面的脚本会比较慢——可以提前把所有分支的历史commit时间导出到一个文件,批量处理能大幅提升效率。
- 要按月份统计的话,只需要把日期遍历改成每月的最后一天即可,比如用
date -d "$YEAR-$MONTH-01 +1 month -1 day" +%Y-%m-%d生成每月最后一天的日期。 - 注意:Git的reflog默认只保留90天的记录,如果要查询更早的历史,得确保仓库的reflog没被清理,或者你有之前备份的refs目录。
内容的提问来源于stack exchange,提问作者devguydavid
相关产品推荐
相关产品推荐

