67 lines
2.8 KiB
Bash
67 lines
2.8 KiB
Bash
#!/usr/bin/env bash
|
||||
|
|
# =====================================================================
|
|||
|
|
# 一条命令把本机提交推到所有远端(CNB 主仓 + 自建 Gitea 代码辅仓)
|
|||
|
|
#
|
|||
|
|
# 为什么需要「先 fetch 再 rebase」:
|
|||
|
|
# 线上写作后台(editor-api 容器,post.usj.cc)发布文章时是**直接往 main 推**的。
|
|||
|
|
# 所以本机在「上次 fetch 之后」只要后台发过文章,本机 main 就与远端分叉 ——
|
|||
|
|
# 此时直接 push 会被 rejected(fetch first)。
|
|||
|
|
# 这不是异常,是**日常**:2026-10-06 第一次实测就撞上了。
|
|||
|
|
# 所以推送前先把自己的提交 rebase 到远端之上,保持线性历史。
|
|||
|
|
#
|
|||
|
|
# 安全边界:
|
|||
|
|
# · 只 rebase **本机未推送的**提交,不外加强推
|
|||
|
|
# · 有冲突就**停在 rebase 中途**交给人工处理(`git rebase --abort` 可放弃)
|
|||
|
|
# · 工作区不干净时 git 自己会拒绝 rebase,不会吞掉改动
|
|||
|
|
# · 任一远端推送失败**不改判另一个** —— 主仓失败时辅仓照样推,
|
|||
|
|
# 备份的意义正在于「主仓出问题时它那儿还有」;但退出码以第一次失败为准
|
|||
|
|
#
|
|||
|
|
# 用法:
|
|||
|
|
# git pushall (别名指向本脚本,等价于直接 bash scripts/pushall.sh)
|
|||
|
|
# bash scripts/pushall.sh
|
|||
|
|
# =====================================================================
|
|||
|
|
set -uo pipefail
|
|||
|
|
|
|||
|
|
cd "$(git rev-parse --show-toplevel)" || exit 1
|
|||
|
|
|
|||
|
|
REMOTES=("origin")
|
|||
|
|
git remote | grep -qx gitea && REMOTES+=("gitea")
|
|||
|
|
|
|||
|
|
echo "1/3 同步远端 (origin)…"
|
|||
|
|
git fetch origin --prune 2>&1 | sed 's/^/ /' || { echo "!! fetch 失败,中止"; exit 1; }
|
|||
|
|
|
|||
|
|
if git rev-parse --verify --quiet origin/main >/dev/null; then
|
|||
|
|
behind=$(git rev-list --count HEAD..origin/main)
|
|||
|
|
if [ "$behind" -gt 0 ]; then
|
|||
|
|
echo " 远端领先 $behind 笔(大概是后台发的文章)→ rebase 到其之上"
|
|||
|
|
if ! git rebase origin/main 2>&1 | sed 's/^/ /'; then
|
|||
|
|
echo "!! rebase 冲突 —— 已停在 rebase 中途,请处理:"
|
|||
|
|
echo " git status 看冲突文件"
|
|||
|
|
echo " git rebase --continue 解决后继续"
|
|||
|
|
echo " git rebase --abort 放弃本次 rebase(回到原状)"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
else
|
|||
|
|
echo " 本机已是最新"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
echo "2/3 推送 → ${REMOTES[*]}"
|
|||
|
|
ec=0
|
|||
|
|
for r in "${REMOTES[@]}"; do
|
|||
|
|
# set -o pipefail 在,所以管道退出码 = git push 的(sed 不会掩盖它)
|
|||
|
|
if ! git push "$r" main 2>&1 | sed "s/^/ [$r] /"; then
|
|||
|
|
# ★ 这里不能写 ec=$? —— `!` 之后的 $? 是取反后的结果(0),不是 git 的退出码
|
|||
|
|
[ "$ec" -eq 0 ] && ec=1
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
if [ "$ec" -eq 0 ]; then
|
|||
|
|
echo "3/3 ✓ 全部远端同步完成"
|
|||
|
|
for r in "${REMOTES[@]}"; do
|
|||
|
|
echo " $r = $(git ls-remote "$r" refs/heads/main 2>/dev/null | cut -c1-8)"
|
|||
|
|
done
|
|||
|
|
else
|
|||
|
|
echo "3/3 ✗ 有远端推送失败(退出码 $ec)"
|
|||
|
|
fi
|
|||
|
|
exit "$ec"
|