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.

447 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/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 pull 的函数
do_git_pull() {
local password="$1"
local remote="$2"
local branch="$3"
local temp_output=$(mktemp)
# 使用 tee 同时输出到终端和文件,以便后续检查错误
expect << EOF 2>&1 | tee "$temp_output"
set timeout 30
spawn git pull $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" {
exp_continue
}
"Permission denied" {
exp_continue
}
"Merge conflict" {
exp_continue
}
"CONFLICT" {
exp_continue
}
eof {
catch wait result
set exit_code [lindex \$result 3]
exit \$exit_code
}
timeout {
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 "(CONFLICT|merge conflict|Automatic merge failed)"; then
echo ""
echo "⚠️ 检测到合并冲突,请手动解决冲突后再执行脚本"
return 2
fi
# 检查输出中是否包含认证失败相关的错误
if echo "$output" | grep -qiE "(Authentication failed|Permission denied|fatal:.*authentication|error:.*authentication)"; then
return 1
fi
return 0
}
# 执行 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
}
# 先执行 pull再执行 push
echo ""
echo "=========================================="
echo "步骤 1: 执行 git pull"
echo "=========================================="
echo ""
# 使用局部变量保存当前使用的密码
local current_password="$PASSWORD"
local pull_success=0
# 首先尝试使用默认密码 pull
echo "尝试使用默认密码执行: git pull $selected_remote $current_branch"
if do_git_pull "$current_password" "$selected_remote" "$current_branch"; then
pull_success=1
echo ""
echo "✅ Pull 成功(使用默认密码)"
else
local pull_result=$?
# 如果是认证失败,提示用户输入密码
if [ $pull_result -eq 1 ]; then
echo ""
echo "⚠️ 默认密码 pull 失败(可能是密码错误),请手动输入密码"
echo ""
read -sp "请输入 Git 密码: " user_password
echo ""
echo ""
echo "使用您输入的密码重新执行: git pull $selected_remote $current_branch"
if do_git_pull "$user_password" "$selected_remote" "$current_branch"; then
pull_success=1
current_password="$user_password"
echo ""
echo "✅ Pull 成功(使用手动输入的密码)"
else
pull_result=$?
if [ $pull_result -eq 2 ]; then
# 合并冲突
echo ""
echo "❌ Pull 失败:存在合并冲突,请手动解决后重试"
return 1
else
echo ""
echo "❌ Pull 失败,请检查密码和网络连接"
return 1
fi
fi
elif [ $pull_result -eq 2 ]; then
# 合并冲突
echo ""
echo "❌ Pull 失败:存在合并冲突,请手动解决后重试"
return 1
else
echo ""
echo "❌ Pull 失败,请检查网络连接"
return 1
fi
fi
# Pull 成功后执行 push
echo ""
echo "=========================================="
echo "步骤 2: 执行 git push"
echo "=========================================="
echo ""
echo "执行: git push $selected_remote $current_branch"
local push_success=0
if do_git_push "$current_password" "$selected_remote" "$current_branch"; then
push_success=1
else
# push 失败,如果之前使用的是默认密码,尝试让用户输入
if [ "$current_password" = "Git@2018" ]; then
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
push_success=1
fi
fi
fi
# 显示最终结果
echo ""
echo "=========================================="
echo "执行结果"
echo "=========================================="
if [ $pull_success -eq 1 ] && [ $push_success -eq 1 ]; then
echo "✅ Pull: 成功"
echo "✅ Push: 成功"
echo ""
echo "✅ 仓库 $repo_path 所有操作完成!"
elif [ $pull_success -eq 1 ] && [ $push_success -eq 0 ]; then
echo "✅ Pull: 成功"
echo "❌ Push: 失败"
echo ""
echo "⚠️ 仓库 $repo_path Pull 成功,但 Push 失败,请检查密码和网络连接"
else
echo "❌ Pull: 失败"
echo "❌ Push: 未执行"
echo ""
echo "❌ 仓库 $repo_path Pull 失败Push 未执行"
fi
echo "=========================================="
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 "=========================================="