#!/usr/bin/env bash # sync-upstream.sh # 将 upstream/main 的最新代码同步合并到本地 main 分支 # 用法: ./scripts/sync-upstream.sh [upstream-remote] [upstream-branch] set -euo pipefail # ── 配置 ──────────────────────────────────────────────────────────────────── UPSTREAM="${1:-upstream}" UPSTREAM_BRANCH="${2:-main}" LOCAL_BRANCH="main" MERGE_MSG="merge: 同步 ${UPSTREAM}/${UPSTREAM_BRANCH} 新功能到定制版本" # ── 颜色输出 ───────────────────────────────────────────────────────────────── RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $*"; } ok() { echo -e "${GREEN}[OK]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } error() { echo -e "${RED}[ERROR]${NC} $*"; } step() { echo -e "\n${CYAN}▶ $*${NC}"; } # ── 检查:必须在 git 仓库内 ─────────────────────────────────────────────────── if ! git rev-parse --git-dir &>/dev/null; then error "当前目录不是 git 仓库" exit 1 fi # ── 检查:必须在 LOCAL_BRANCH 上 ───────────────────────────────────────────── CURRENT_BRANCH=$(git branch --show-current) if [[ "$CURRENT_BRANCH" != "$LOCAL_BRANCH" ]]; then error "当前分支是 '$CURRENT_BRANCH',请先切换到 '$LOCAL_BRANCH'" error " git checkout $LOCAL_BRANCH" exit 1 fi # ── 检查:是否有未提交的改动 ────────────────────────────────────────────────── step "检查工作区状态" DIRTY=$(git status --porcelain) if [[ -n "$DIRTY" ]]; then warn "检测到未提交的本地修改:" git status --short echo "" echo -e " ${YELLOW}选项:${NC}" echo " [1] 自动提交为 WIP commit,合并完成后可再整理(推荐)" echo " [2] 退出,手动处理后再运行" echo "" read -rp "请选择 [1/2]: " choice case "$choice" in 1) step "提交本地修改为 WIP commit" git add -A git commit -m "chore: WIP - 合并 upstream 前保存本地修改" ok "WIP commit 已创建" ;; *) info "已退出,请手动处理后再运行此脚本" exit 0 ;; esac fi # ── 拉取 upstream ───────────────────────────────────────────────────────────── step "拉取 ${UPSTREAM}/${UPSTREAM_BRANCH}" if ! git fetch "$UPSTREAM" 2>&1; then error "fetch ${UPSTREAM} 失败,请检查网络或 remote 配置" git remote -v exit 1 fi # ── 检查是否有新提交 ────────────────────────────────────────────────────────── NEW_COMMITS=$(git log HEAD.."${UPSTREAM}/${UPSTREAM_BRANCH}" --oneline) if [[ -z "$NEW_COMMITS" ]]; then ok "已是最新,无需合并" exit 0 fi info "以下 upstream 提交将被合并:" echo "$NEW_COMMITS" | while IFS= read -r line; do echo " + $line" done # ── 执行合并 ────────────────────────────────────────────────────────────────── step "合并 ${UPSTREAM}/${UPSTREAM_BRANCH} → ${LOCAL_BRANCH}" if git merge "${UPSTREAM}/${UPSTREAM_BRANCH}" --no-ff -m "$MERGE_MSG" 2>&1; then ok "合并成功,无冲突" else # 有冲突 CONFLICTS=$(git diff --name-only --diff-filter=U) echo "" error "合并产生冲突,需要手动解决以下文件:" echo "$CONFLICTS" | while IFS= read -r f; do echo " ✗ $f" done echo "" echo -e "${YELLOW}解决步骤:${NC}" echo " 1. 用编辑器打开冲突文件,搜索 <<<<<<< 并逐一解决" echo " 2. 解决完成后运行:" echo " git add <已解决的文件>" echo " git commit -m \"$MERGE_MSG\"" echo "" echo -e "${YELLOW}常用工具:${NC}" echo " git diff # 查看所有冲突内容" echo " git checkout --ours # 保留我们的版本" echo " git checkout --theirs # 保留 upstream 版本" echo " npx biome check --write --unsafe # 修复可自动修复的 lint 错误" echo "" echo -e "${YELLOW}放弃本次合并:${NC}" echo " git merge --abort" exit 1 fi # ── 运行 lint 检查 ──────────────────────────────────────────────────────────── step "运行 biome 检查" if npx biome check 2>&1 | grep -q "Found.*error"; then warn "发现 lint 错误,尝试自动修复..." npx biome check --write --unsafe 2>&1 | tail -3 # 再检查一次 REMAINING=$(npx biome check 2>&1 | grep "Found.*error" || true) if [[ -n "$REMAINING" ]]; then warn "仍有无法自动修复的 lint 错误,请手动处理:" npx biome check 2>&1 | grep "lint/" | grep -v "FIXABLE\|Unsafe\|i " | sort -u else ok "lint 错误已全部自动修复" # 如果 biome 修改了文件,需要重新提交 if [[ -n "$(git diff --name-only)" ]]; then git add -A git commit -m "fix: 修复合并后的 lint 错误" ok "lint 修复已提交" fi fi else ok "biome 检查通过,无错误" fi # ── 完成 ─────────────────────────────────────────────────────────────────────── echo "" ok "同步完成!最新提交记录:" git log --oneline -5 echo "" info "如需推送到远端(kxsw):" echo " git push kxsw main"