Last active
March 3, 2026 09:46
-
-
Save Wxh16144/e6231fabd1ad4374618e976bc0456467 to your computer and use it in GitHub Desktop.
Auto Update Repos Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # 配置:定义仓库路径,格式为 "路径|分支|命令" | |
| # - 分支:可选。指定要拉取的分支,如 "main" 或 "develop"。留空则使用当前检出的分支。 | |
| # - 命令:可选。pull 成功后执行的命令。 | |
| # | |
| # 示例: | |
| # "path/to/repo|main|npm install" -> 强制 main 分支,执行 npm install | |
| # "path/to/repo||npm install" -> 跟随当前分支,执行 npm install | |
| # "path/to/repo|develop" -> 强制 develop 分支,无后续命令 | |
| # "path/to/repo" -> 最简配置:跟随当前分支,无命令 | |
| repos=( | |
| "/Users/wuxh/Code/company/preview/common-editor|develop" | |
| "/Users/wuxh/Code/company/preview/savery-editor|develop" | |
| "/Users/wuxh/Code/company/saveryconfig" | |
| "/Users/wuxh/Code/company/savery-webgpu||./fast-webgpu" | |
| ) | |
| # 可选:定义全局默认分支(仅当配置中分支字段为空,且这里设置了值时生效。留空则默认各自的当前分支) | |
| default_global_branch="" | |
| echo "---------------------------- $(date +'%Y-%m-%d %H:%M:%S') ----------------------------" | |
| current_date=$(date +%Y%m%d) | |
| result="" | |
| for item in "${repos[@]}"; do | |
| # 解析配置项 | |
| # 使用 IFS 将字符串分割为数组 | |
| IFS='|' read -r -a config <<<"$item" | |
| repo_path="${config[0]}" | |
| target_repo_branch="${config[1]}" | |
| post_cmd="${config[2]}" | |
| # 去除可能的前后空格(虽通常不建议路径带空格,但也防一手) | |
| repo_path=$(echo "$repo_path" | xargs) | |
| target_repo_branch=$(echo "$target_repo_branch" | xargs) | |
| post_cmd=$(echo "$post_cmd" | xargs) | |
| # 检查目录是否存在 | |
| if [ ! -d "$repo_path" ]; then | |
| echo "🚫 目录未找到: $repo_path" | |
| result="$result\n🚫 $(basename "$repo_path") (未找到)" | |
| continue | |
| fi | |
| # 检查是否为 git 仓库 | |
| if [ -d "$repo_path/.git" ]; then | |
| echo | |
| echo "🚀 正在处理: $repo_path" | |
| # 进入目录 | |
| cd "$repo_path" || { | |
| echo "❌ 无法进入目录: $repo_path" | |
| result="$result\n❌ $(basename "$repo_path") (拒绝访问)" | |
| continue | |
| } | |
| short_dir="$(basename "$(dirname "$repo_path")")/$(basename "$repo_path")" | |
| current_branch=$(git rev-parse --abbrev-ref HEAD) | |
| # 1. 先检查当前状态,如果有未提交更改,先 stash 起来,避免切换分支失败 | |
| if [[ -n $(git status --porcelain) ]]; then | |
| echo "📦 当前目录不干净 ($current_branch),正在暂存(Stash)更改(包含新建文件)..." | |
| git stash save -u "auto_stash_$current_date" | |
| fi | |
| # 2. 确定要拉取的最终目标分支 | |
| # 优先级:单项配置 > 全局默认 | |
| final_target_branch="" | |
| if [[ -n "$target_repo_branch" ]]; then | |
| final_target_branch="$target_repo_branch" | |
| elif [[ -n "$default_global_branch" ]]; then | |
| final_target_branch="$default_global_branch" | |
| fi | |
| # 3. 如果指定了目标分支且与当前不一致,则切换 | |
| if [[ -n "$final_target_branch" && "$current_branch" != "$final_target_branch" ]]; then | |
| echo "⚠️ 检测到当前分支 ($current_branch) 与目标 ($final_target_branch) 不一致,正在切换..." | |
| git checkout "$final_target_branch" | |
| if [[ $? -ne 0 ]]; then | |
| echo "❌ 切换到 $final_target_branch 失败,跳过..." | |
| result="$result\n❌ $short_dir (切换失败)" | |
| continue | |
| fi | |
| # 更新当前分支变量 | |
| current_branch="$final_target_branch" | |
| fi | |
| echo "⬇️ 正在拉取 origin $current_branch..." | |
| pull_output=$(git pull origin "$current_branch" 2>&1) | |
| pull_exit_code=$? | |
| # Output the pull result to console so user can see details if running manually | |
| echo "$pull_output" | |
| if [ $pull_exit_code -eq 0 ]; then | |
| status_icon="✅" | |
| extra_msg="" | |
| current_hash=$(git rev-parse --short HEAD) | |
| # Detect if there were actual updates | |
| status_no_change="" | |
| has_updates=false | |
| if [[ "$pull_output" == *"Already up to date."* ]]; then | |
| status_no_change=" (无变动)" | |
| else | |
| status_no_change=" 🆙" | |
| has_updates=true | |
| fi | |
| # 如果存在、拉取成功且有代码变更,则执行后置命令 | |
| if [[ -n "$post_cmd" ]]; then | |
| if [[ "$has_updates" == "true" ]]; then | |
| echo "⚙️ 检测到代码更新,执行后置命令: $post_cmd" | |
| if eval "$post_cmd"; then | |
| extra_msg=" + 命令成功" | |
| else | |
| status_icon="⚠️ " | |
| extra_msg=" + 命令失败" | |
| echo "❌ 后置命令失败。" | |
| fi | |
| else | |
| echo "💤 无代码变更,跳过后置命令。" | |
| fi | |
| fi | |
| result="${result}\n${status_icon} ${short_dir} (${current_branch} @ ${current_hash})${status_no_change}${extra_msg}" | |
| else | |
| echo "❌ 拉取目录 $repo_path 失败" | |
| result="${result}\n❌ ${short_dir} (拉取失败)" | |
| fi | |
| echo | |
| else | |
| echo "🚫 $repo_path 不是有效的 git 仓库。" | |
| result="${result}\n🚫 $(basename "$repo_path") (非 git 仓库)" | |
| fi | |
| done | |
| echo | |
| echo "============================================================" | |
| echo -e "📊 执行汇总报告: $(date +'%Y-%m-%d %H:%M:%S') $result" | |
| echo "============================================================" | |
| echo |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Auto Update Repos Script
这个脚本用于批量更新多个 Git 仓库,支持自动处理未提交的更改、切换分支以及执行更新后的命令。
功能特性
git stash暂存,防止冲突。npm install)。配置说明
编辑脚本文件
auto-update-repos.sh中的repos数组进行配置。配置格式:
"绝对路径|分支名|后置命令"示例配置:
repos=( # 强制拉取 main 分支,并执行安装和构建 "/Users/name/project-a|main|npm install && npm run build" # 强制拉取 develop 分支,无后续命令 "/Users/name/project-b|develop" # 保持当前分支,更新后运行 setup "/Users/name/project-c||make setup" # 最简配置:仅拉取当前分支 "/Users/name/project-d" )使用方法
⏰ 进阶:如何在 macOS 上设置定时自动运行 (Crontab)
你可以使用
crontab让这个脚本每天自动运行(例如每天早上上班前)。打开 Crontab 编辑器:
在终端中运行:
添加定时任务:
进入编辑模式后添加一行。
例如:每天早上 9:00 运行脚本,并将日志输出到
update.log文件:(注意:请务必使用脚本的绝对路径)
保存并退出:
Esc,输入:wq然后回车。Ctrl+O回车保存,然后Ctrl+X退出。验证任务:
运行
crontab -l查看任务列表。