manage-branches.sh 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #!/usr/bin/env bash
  2. # 分支管理自动化脚本
  3. # 实现智能分支检查、清理和流程指导
  4. set -e
  5. # 颜色定义
  6. RED='\033[0;31m'
  7. GREEN='\033[0;32m'
  8. YELLOW='\033[1;33m'
  9. BLUE='\033[0;34m'
  10. NC='\033[0m' # No Color
  11. # 获取仓库根目录
  12. get_repo_root() {
  13. if git rev-parse --show-toplevel >/dev/null 2>&1; then
  14. git rev-parse --show-toplevel
  15. else
  16. echo "Error: 不是Git仓库或未初始化Git" >&2
  17. exit 1
  18. fi
  19. }
  20. # 分析分支状态
  21. analyze_branches() {
  22. local repo_root="$1"
  23. local current_branch=$(git branch --show-current)
  24. local main_branch="main"
  25. echo -e "${BLUE}📊 分支状态分析${NC}"
  26. echo "===================================="
  27. # 列出所有功能分支
  28. local feature_branches=()
  29. while IFS= read -r branch; do
  30. branch=$(echo "$branch" | sed 's/^[* ] //')
  31. if [[ "$branch" =~ ^[0-9]{3}- ]] && [[ "$branch" != "$main_branch" ]]; then
  32. feature_branches+=("$branch")
  33. fi
  34. done < <(git branch)
  35. if [ ${#feature_branches[@]} -eq 0 ]; then
  36. echo -e "${GREEN}✅ 无功能分支,分支状态干净${NC}"
  37. return 0
  38. fi
  39. echo -e "${YELLOW}📋 发现 ${#feature_branches[@]} 个功能分支:${NC}"
  40. for branch in "${feature_branches[@]}"; do
  41. local spec_dir="$repo_root/specs/$branch"
  42. local has_spec_dir=""
  43. local has_implementation=""
  44. local commits_ahead=""
  45. # 检查是否有specs目录
  46. if [ -d "$spec_dir" ]; then
  47. has_spec_dir="✅"
  48. else
  49. has_spec_dir="❌"
  50. fi
  51. # 检查是否有实现代码(src目录中的变更)
  52. local changed_files=$(git diff --name-only "$main_branch..$branch" 2>/dev/null | grep "^src/" | wc -l || echo "0")
  53. if [ "$changed_files" -gt 0 ]; then
  54. has_implementation="✅ ($changed_files files)"
  55. else
  56. has_implementation="❌"
  57. fi
  58. # 检查相对main的提交数
  59. commits_ahead=$(git rev-list --count "$main_branch..$branch" 2>/dev/null || echo "0")
  60. # 输出分支状态
  61. printf " %-25s | Spec: %s | Code: %-12s | Commits: %s\n" \
  62. "$branch" "$has_spec_dir" "$has_implementation" "$commits_ahead"
  63. done
  64. echo ""
  65. return ${#feature_branches[@]}
  66. }
  67. # 建议操作
  68. suggest_actions() {
  69. local branch_count=$1
  70. local current_branch=$(git branch --show-current)
  71. echo -e "${BLUE}💡 建议操作${NC}"
  72. echo "===================================="
  73. if [ "$branch_count" -eq 0 ]; then
  74. echo -e "${GREEN}✨ 可以安全创建新功能分支${NC}"
  75. return 0
  76. fi
  77. if [ "$branch_count" -eq 1 ] && [[ "$current_branch" =~ ^[0-9]{3}- ]]; then
  78. echo -e "${YELLOW}🎯 专注完成当前分支: $current_branch${NC}"
  79. echo "建议: 完成后运行 'manage-branches.sh --merge' 合并到main"
  80. elif [ "$branch_count" -ge 2 ]; then
  81. echo -e "${RED}⚠️ 发现多个功能分支,建议清理${NC}"
  82. echo "选项1: 删除重复或不需要的分支"
  83. echo "选项2: 完成并合并已完成的分支"
  84. echo "选项3: 运行 'manage-branches.sh --cleanup' 进行交互式清理"
  85. fi
  86. }
  87. # 交互式分支清理
  88. interactive_cleanup() {
  89. local repo_root="$1"
  90. local current_branch=$(git branch --show-current)
  91. local main_branch="main"
  92. echo -e "${BLUE}🧹 交互式分支清理${NC}"
  93. echo "===================================="
  94. # 获取所有功能分支
  95. local feature_branches=()
  96. while IFS= read -r branch; do
  97. branch=$(echo "$branch" | sed 's/^[* ] //')
  98. if [[ "$branch" =~ ^[0-9]{3}- ]] && [[ "$branch" != "$main_branch" ]]; then
  99. feature_branches+=("$branch")
  100. fi
  101. done < <(git branch)
  102. if [ ${#feature_branches[@]} -eq 0 ]; then
  103. echo -e "${GREEN}✅ 没有需要清理的功能分支${NC}"
  104. return 0
  105. fi
  106. for branch in "${feature_branches[@]}"; do
  107. echo ""
  108. echo -e "${YELLOW}📝 分支: $branch${NC}"
  109. # 显示分支信息
  110. local commits=$(git rev-list --count "$main_branch..$branch" 2>/dev/null || echo "0")
  111. local spec_dir="$repo_root/specs/$branch"
  112. echo " 提交数: $commits"
  113. if [ -d "$spec_dir" ]; then
  114. echo " 规范目录: ✅ $spec_dir"
  115. else
  116. echo " 规范目录: ❌ 不存在"
  117. fi
  118. # 询问操作
  119. echo ""
  120. echo "选择操作:"
  121. echo " 1) 保留分支"
  122. echo " 2) 删除分支 (谨慎!)"
  123. echo " 3) 合并到main并删除"
  124. echo " 4) 跳过"
  125. read -p "请选择 (1-4): " choice
  126. case $choice in
  127. 1)
  128. echo -e "${GREEN}✅ 保留分支 $branch${NC}"
  129. ;;
  130. 2)
  131. echo -e "${RED}⚠️ 确认删除分支 $branch? 这将丢失所有变更!${NC}"
  132. read -p "输入 'DELETE' 确认: " confirm
  133. if [ "$confirm" = "DELETE" ]; then
  134. git branch -D "$branch"
  135. rm -rf "$spec_dir"
  136. echo -e "${RED}🗑️ 已删除分支 $branch${NC}"
  137. else
  138. echo -e "${YELLOW}❌ 取消删除${NC}"
  139. fi
  140. ;;
  141. 3)
  142. echo -e "${BLUE}🔄 合并分支 $branch 到 main${NC}"
  143. # 检查是否有未提交的变更
  144. if ! git diff-index --quiet HEAD --; then
  145. echo -e "${YELLOW}⚠️ 当前分支有未提交的变更,请先提交${NC}"
  146. continue
  147. fi
  148. # 切换到main并合并
  149. git checkout main
  150. git merge "$branch"
  151. git branch -d "$branch"
  152. echo -e "${GREEN}✅ 已合并并删除分支 $branch${NC}"
  153. ;;
  154. 4)
  155. echo -e "${BLUE}⏭️ 跳过分支 $branch${NC}"
  156. ;;
  157. *)
  158. echo -e "${RED}❌ 无效选择,跳过${NC}"
  159. ;;
  160. esac
  161. done
  162. }
  163. # 自动合并当前分支
  164. auto_merge_current() {
  165. local current_branch=$(git branch --show-current)
  166. local main_branch="main"
  167. if [[ ! "$current_branch" =~ ^[0-9]{3}- ]]; then
  168. echo -e "${RED}❌ 当前不在功能分支上${NC}"
  169. exit 1
  170. fi
  171. echo -e "${BLUE}🔄 自动合并当前分支: $current_branch${NC}"
  172. # 检查是否有未提交的变更
  173. if ! git diff-index --quiet HEAD --; then
  174. echo -e "${YELLOW}⚠️ 发现未提交的变更,正在提交...${NC}"
  175. git add .
  176. git commit -m "完成功能实现 - 自动提交"
  177. fi
  178. # 切换到main并合并
  179. git checkout main
  180. git merge "$current_branch" --no-ff -m "合并功能分支: $current_branch"
  181. git branch -d "$current_branch"
  182. echo -e "${GREEN}✅ 已成功合并并删除分支: $current_branch${NC}"
  183. }
  184. # 检查新功能创建前的状态
  185. pre_create_check() {
  186. echo -e "${BLUE}🔍 新功能创建前检查${NC}"
  187. echo "===================================="
  188. local branch_count
  189. analyze_branches "$(get_repo_root)"
  190. branch_count=$?
  191. if [ "$branch_count" -eq 0 ]; then
  192. echo -e "${GREEN}✅ 可以安全创建新功能分支${NC}"
  193. return 0
  194. elif [ "$branch_count" -eq 1 ]; then
  195. local current_branch=$(git branch --show-current)
  196. if [[ "$current_branch" =~ ^[0-9]{3}- ]]; then
  197. echo -e "${YELLOW}⚠️ 建议先完成当前分支: $current_branch${NC}"
  198. echo "运行 'manage-branches.sh --merge' 来合并当前分支"
  199. else
  200. echo -e "${YELLOW}⚠️ 发现1个功能分支,建议清理后再创建新功能${NC}"
  201. fi
  202. return 1
  203. else
  204. echo -e "${RED}🚫 发现多个功能分支,强烈建议先清理${NC}"
  205. echo "运行 'manage-branches.sh --cleanup' 进行清理"
  206. return 2
  207. fi
  208. }
  209. # 显示帮助信息
  210. show_help() {
  211. echo "分支管理自动化工具"
  212. echo ""
  213. echo "用法: $0 [选项]"
  214. echo ""
  215. echo "选项:"
  216. echo " --status 显示分支状态分析"
  217. echo " --cleanup 交互式分支清理"
  218. echo " --merge 自动合并当前功能分支到main"
  219. echo " --check 新功能创建前检查"
  220. echo " --help 显示帮助信息"
  221. echo ""
  222. echo "示例:"
  223. echo " $0 --status # 查看当前分支状态"
  224. echo " $0 --check # 检查是否适合创建新功能"
  225. echo " $0 --cleanup # 交互式清理分支"
  226. echo " $0 --merge # 合并当前分支到main"
  227. }
  228. # 主函数
  229. main() {
  230. local repo_root
  231. repo_root=$(get_repo_root)
  232. cd "$repo_root"
  233. case "${1:-}" in
  234. --status)
  235. analyze_branches "$repo_root"
  236. suggest_actions $?
  237. ;;
  238. --cleanup)
  239. interactive_cleanup "$repo_root"
  240. ;;
  241. --merge)
  242. auto_merge_current
  243. ;;
  244. --check)
  245. pre_create_check
  246. ;;
  247. --help|-h)
  248. show_help
  249. ;;
  250. "")
  251. # 默认行为:显示状态和建议
  252. analyze_branches "$repo_root"
  253. suggest_actions $?
  254. ;;
  255. *)
  256. echo -e "${RED}❌ 未知选项: $1${NC}" >&2
  257. show_help
  258. exit 1
  259. ;;
  260. esac
  261. }
  262. main "$@"