You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
8.8 KiB
314 lines
8.8 KiB
#!/bin/bash
|
|
|
|
# 快速 Git 提交脚本
|
|
# 自动执行 git add . git commit -m 'update' git push
|
|
# 自动输入密码: Git@2018
|
|
|
|
PASSWORD="Git@2018"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# 查找所有 Git 仓库
|
|
find_git_repos() {
|
|
local current_dir="$1"
|
|
local repos=()
|
|
|
|
# 查找所有 .git 目录(包括当前目录和子目录,最多搜索 3 层深度)
|
|
while IFS= read -r -d '' git_dir; do
|
|
# 获取仓库根目录(去掉 .git 部分)
|
|
repo_path=$(dirname "$git_dir")
|
|
# 标准化路径(去除相对路径符号)
|
|
repo_path=$(cd "$repo_path" && pwd)
|
|
repos+=("$repo_path")
|
|
done < <(find "$current_dir" -maxdepth 3 -type d -name ".git" -print0 2>/dev/null)
|
|
|
|
# 去重并排序
|
|
printf '%s\n' "${repos[@]}" | sort -u
|
|
}
|
|
|
|
# 执行 Git 操作的函数
|
|
execute_git_operations() {
|
|
local repo_path="$1"
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "正在处理仓库: $repo_path"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
# 切换到仓库目录
|
|
cd "$repo_path" || {
|
|
echo "错误: 无法切换到目录 $repo_path"
|
|
return 1
|
|
}
|
|
|
|
# 执行 git add .
|
|
echo "执行: git add ."
|
|
git add .
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "错误: git add 失败"
|
|
return 1
|
|
fi
|
|
|
|
# 执行 git commit
|
|
echo "执行: git commit -m 'update'"
|
|
git commit -m 'update'
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "警告: git commit 可能没有新的更改需要提交"
|
|
fi
|
|
|
|
# 检查是否有 expect 命令
|
|
if ! command -v expect &> /dev/null; then
|
|
echo ""
|
|
echo "错误: 未找到 expect 命令"
|
|
echo "请先安装 expect: brew install expect"
|
|
echo ""
|
|
echo "或者手动执行: git push"
|
|
return 1
|
|
fi
|
|
|
|
# 获取所有远程仓库
|
|
local remotes=($(git remote))
|
|
|
|
if [ ${#remotes[@]} -eq 0 ]; then
|
|
echo ""
|
|
echo "警告: 当前仓库没有配置远程仓库,跳过 push"
|
|
return 0
|
|
fi
|
|
|
|
# 获取当前分支名
|
|
local current_branch=$(git branch --show-current)
|
|
if [ -z "$current_branch" ]; then
|
|
current_branch="master"
|
|
fi
|
|
|
|
# 选择远程仓库
|
|
local selected_remote=""
|
|
if [ ${#remotes[@]} -eq 1 ]; then
|
|
# 只有一个远程仓库,直接使用
|
|
selected_remote="${remotes[0]}"
|
|
echo ""
|
|
echo "检测到 1 个远程仓库: $selected_remote"
|
|
else
|
|
# 多个远程仓库,让用户选择
|
|
echo ""
|
|
echo "检测到 ${#remotes[@]} 个远程仓库:"
|
|
echo ""
|
|
for i in "${!remotes[@]}"; do
|
|
local_index=$((i + 1))
|
|
local remote_url=$(git remote get-url "${remotes[$i]}")
|
|
echo " [$local_index] ${remotes[$i]} ($remote_url)"
|
|
done
|
|
echo ""
|
|
|
|
# 读取用户选择
|
|
while true; do
|
|
read -p "请选择要推送的远程仓库编号 (1-${#remotes[@]}): " choice
|
|
|
|
# 检查输入是否为数字
|
|
if ! [[ "$choice" =~ ^[0-9]+$ ]]; then
|
|
echo "错误: 请输入有效的数字"
|
|
continue
|
|
fi
|
|
|
|
# 处理选择
|
|
if [ "$choice" -ge 1 ] && [ "$choice" -le ${#remotes[@]} ]; then
|
|
selected_remote="${remotes[$((choice - 1))]}"
|
|
break
|
|
else
|
|
echo "错误: 请输入 1-${#remotes[@]} 之间的数字"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# 执行 git push 的函数
|
|
do_git_push() {
|
|
local password="$1"
|
|
local remote="$2"
|
|
local branch="$3"
|
|
local temp_output=$(mktemp)
|
|
local push_failed=0
|
|
|
|
# 使用 tee 同时输出到终端和文件,以便后续检查错误
|
|
expect << EOF 2>&1 | tee "$temp_output"
|
|
set timeout 30
|
|
spawn git push $remote $branch
|
|
expect {
|
|
"Password:" {
|
|
send "$password\r"
|
|
exp_continue
|
|
}
|
|
"password:" {
|
|
send "$password\r"
|
|
exp_continue
|
|
}
|
|
"passphrase:" {
|
|
send "$password\r"
|
|
exp_continue
|
|
}
|
|
"Username:" {
|
|
exp_continue
|
|
}
|
|
"Authentication failed" {
|
|
set push_failed 1
|
|
exp_continue
|
|
}
|
|
"Permission denied" {
|
|
set push_failed 1
|
|
exp_continue
|
|
}
|
|
eof {
|
|
catch wait result
|
|
set exit_code [lindex \$result 3]
|
|
if {\$exit_code != 0} {
|
|
set push_failed 1
|
|
}
|
|
exit \$exit_code
|
|
}
|
|
timeout {
|
|
set push_failed 1
|
|
exit 1
|
|
}
|
|
}
|
|
EOF
|
|
|
|
local exit_code=$?
|
|
local output=$(cat "$temp_output" 2>/dev/null)
|
|
rm -f "$temp_output"
|
|
|
|
# 检查退出码和输出中的错误信息
|
|
if [ $exit_code -ne 0 ]; then
|
|
return 1
|
|
fi
|
|
|
|
# 检查输出中是否包含认证失败相关的错误
|
|
if echo "$output" | grep -qiE "(Authentication failed|Permission denied|fatal:.*authentication|error:.*authentication)"; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# 执行 push
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "执行 git push"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
# 使用局部变量保存当前使用的密码
|
|
local current_password="$PASSWORD"
|
|
|
|
# 首先尝试使用默认密码 push
|
|
echo "执行: git push $selected_remote $current_branch (使用默认密码)"
|
|
if do_git_push "$current_password" "$selected_remote" "$current_branch"; then
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "执行结果"
|
|
echo "=========================================="
|
|
echo "✅ Push: 成功"
|
|
echo ""
|
|
echo "✅ 仓库 $repo_path 提交完成!"
|
|
echo "=========================================="
|
|
else
|
|
# 默认密码失败,提示用户输入密码
|
|
echo ""
|
|
echo "⚠️ 默认密码 push 失败,请手动输入密码"
|
|
echo ""
|
|
read -sp "请输入 Git 密码: " user_password
|
|
echo ""
|
|
echo ""
|
|
echo "使用您输入的密码重新执行: git push $selected_remote $current_branch"
|
|
|
|
if do_git_push "$user_password" "$selected_remote" "$current_branch"; then
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "执行结果"
|
|
echo "=========================================="
|
|
echo "✅ Push: 成功"
|
|
echo ""
|
|
echo "✅ 仓库 $repo_path 提交完成!"
|
|
echo "=========================================="
|
|
else
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "执行结果"
|
|
echo "=========================================="
|
|
echo "❌ Push: 失败"
|
|
echo ""
|
|
echo "❌ 仓库 $repo_path push 失败,请检查密码和网络连接"
|
|
echo "=========================================="
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
# 主程序
|
|
echo "开始执行 Git 快速提交..."
|
|
echo ""
|
|
|
|
# 查找所有 Git 仓库
|
|
echo "正在查找 Git 仓库..."
|
|
repos=($(find_git_repos "$SCRIPT_DIR"))
|
|
|
|
if [ ${#repos[@]} -eq 0 ]; then
|
|
echo "错误: 未找到任何 Git 仓库"
|
|
exit 1
|
|
fi
|
|
|
|
# 如果只有一个仓库,直接执行
|
|
if [ ${#repos[@]} -eq 1 ]; then
|
|
echo "找到 1 个 Git 仓库:"
|
|
echo " [1] ${repos[0]}"
|
|
echo ""
|
|
execute_git_operations "${repos[0]}"
|
|
else
|
|
# 多个仓库,让用户选择
|
|
echo "找到 ${#repos[@]} 个 Git 仓库:"
|
|
echo ""
|
|
for i in "${!repos[@]}"; do
|
|
local_index=$((i + 1))
|
|
echo " [$local_index] ${repos[$i]}"
|
|
done
|
|
echo ""
|
|
echo " [0] 全部执行"
|
|
echo ""
|
|
|
|
# 读取用户选择
|
|
while true; do
|
|
read -p "请选择要操作的仓库编号 (0-${#repos[@]}): " choice
|
|
|
|
# 检查输入是否为数字
|
|
if ! [[ "$choice" =~ ^[0-9]+$ ]]; then
|
|
echo "错误: 请输入有效的数字"
|
|
continue
|
|
fi
|
|
|
|
# 处理选择
|
|
if [ "$choice" -eq 0 ]; then
|
|
# 全部执行
|
|
echo ""
|
|
echo "将执行所有仓库的操作..."
|
|
for repo in "${repos[@]}"; do
|
|
execute_git_operations "$repo"
|
|
done
|
|
break
|
|
elif [ "$choice" -ge 1 ] && [ "$choice" -le ${#repos[@]} ]; then
|
|
# 执行选中的仓库
|
|
selected_repo="${repos[$((choice - 1))]}"
|
|
execute_git_operations "$selected_repo"
|
|
break
|
|
else
|
|
echo "错误: 请输入 0-${#repos[@]} 之间的数字"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "所有操作完成!"
|
|
echo "=========================================="
|
|
|