【git】自动化合并推送脚本

背景

也可以写成skill交给AI

存档

bash 复制代码
function gc() {
  # 颜色定义
  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[1;33m'
  BLUE='\033[0;34m'
  NC='\033[0m' # No Color
  
  # 检查是否在 git 仓库中
  if ! git rev-parse --git-dir > /dev/null 2>&1; then
    echo -e "${RED}❌ 错误:当前目录不是 git 仓库${NC}"
    echo "   当前路径: $(pwd)"
    return 1
  fi
  
  # 获取当前分支
  local current_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
  echo -e "${BLUE}🌿 当前分支: ${GREEN}$current_branch${NC}"
  echo ""
  
  # ---------- 新逻辑:如果传入了第二个参数(测试主分支) ----------
  if [ -n "$2" ]; then
    local target_branch="$2"
    
    # ========== 第一步:先提交并推送当前业务分支 ==========
    echo -e "${BLUE}📦 第一步:提交并推送当前业务分支 '${current_branch}'${NC}"
    echo ""
    
    # 检查是否有变更
    if git diff --quiet && git diff --cached --quiet; then
      echo -e "${YELLOW}⚠️  当前分支没有需要提交的变更,跳过提交步骤${NC}"
    else
      # 显示将要提交的文件
      echo -e "${GREEN}📝 变更文件列表:${NC}"
      git status --short
      echo ""
      
      # 检查是否已经有暂存的文件
      if git diff --cached --quiet; then
        # 没有暂存的文件,添加所有变更
        echo -e "${GREEN}✅ 没有暂存的文件,正在添加所有变更...${NC}"
        git add .
        echo -e "${GREEN}✅ 已添加所有变更${NC}"
      else
        # 已经有暂存的文件,不再执行 git add .
        echo -e "${GREEN}✅ 检测到已有暂存的文件,跳过 git add .${NC}"
      fi
      echo ""
      
      # 提交(添加 --no-verify)
      if [ -z "$1" ]; then
        echo -e "${BLUE}💬 请输入提交信息(直接回车打开编辑器):${NC}"
        read -r msg
        if [ -z "$msg" ]; then
          echo -e "${BLUE}正在打开编辑器...${NC}"
          git commit --no-verify
        else
          git commit --no-verify -m "$msg"
        fi
      else
        git commit --no-verify -m "$1"
      fi
      
      # 检查提交是否成功
      if [ $? -ne 0 ]; then
        echo -e "${RED}❌ 提交失败${NC}"
        return 1
      fi
      
      echo -e "${GREEN}✅ 提交成功${NC}"
      echo ""
    fi
    
    # 推送当前业务分支
    echo -e "${BLUE}🚀 推送当前分支 '${current_branch}' 到远端...${NC}"
    
    # 检查远端分支是否存在
    if git ls-remote --heads origin "$current_branch" 2>/dev/null | grep -q "$current_branch"; then
      echo -e "${GREEN}✅ 远端分支存在,正在推送...${NC}"
      git push
    else
      echo -e "${YELLOW}⚠️  分支 '${current_branch}' 在远端不存在,正在创建并推送...${NC}"
      git push --set-upstream origin "$current_branch"
    fi
    
    # 检查推送结果
    if [ $? -ne 0 ]; then
      echo -e "${RED}❌ 推送失败,请检查网络连接或权限${NC}"
      return 1
    fi
    
    echo -e "${GREEN}✅ 业务分支推送成功${NC}"
    echo ""
    
    # ========== 第二步:切换到目标分支并合并 ==========
    echo -e "${BLUE}🔀 第二步:合并到目标分支 '${target_branch}'${NC}"
    echo ""
    
    # 切换到目标分支(如 test)
    echo -e "${BLUE}🔄 正在切换到分支 '${target_branch}'...${NC}"
    
    # 捕获切换输出和错误
    checkout_output=$(git checkout "$target_branch" 2>&1)
    checkout_exit_code=$?
    
    if [ $checkout_exit_code -ne 0 ]; then
      echo -e "${RED}❌ 错误:切换到分支 '${target_branch}' 失败${NC}"
      echo -e "${YELLOW}失败原因:${NC}"
      echo "$checkout_output"
      echo ""
      echo -e "${YELLOW}可能的原因:${NC}"
      echo "   - 分支 '${target_branch}' 不存在"
      echo "   - 本地有未提交的变更与切换冲突(Git 无法自动处理)"
      echo "   - 其他 Git 错误"
      return 1
    fi
    
    echo -e "${GREEN}✅ 已切换到分支 '${target_branch}'${NC}"
    if [ -n "$checkout_output" ] && [[ "$checkout_output" != *"Switched to branch"* ]]; then
      echo -e "${YELLOW}⚠️  $checkout_output${NC}"
    fi
    echo ""
    
    # 拉取远端最新代码(严格模式:失败则停止)
    echo -e "${BLUE}📦 正在拉取远端最新代码...${NC}"
    if ! git pull; then
      echo -e "${RED}❌ 拉取远端代码失败,停止合并${NC}"
      echo -e "${YELLOW}正在切换回原分支 '${current_branch}'...${NC}"
      git checkout "$current_branch" 2>/dev/null
      return 1
    fi
    echo -e "${GREEN}✅ 拉取成功${NC}"
    echo ""
    
    # 确认合并动作
    echo -e "${YELLOW}⚠️  即将把业务分支 '${current_branch}' 合并到当前分支 '${target_branch}'${NC}"
    echo -e -n "${BLUE}请确认是否继续?(y/N): ${NC}"
    read -r confirm
    if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
      echo -e "${YELLOW}❌ 已取消合并操作${NC}"
      # 切换回原分支
      git checkout "$current_branch" 2>/dev/null
      return 0
    fi
    
    # 执行合并
    echo -e "${BLUE}🔀 正在合并分支 '${current_branch}' -> '${target_branch}'...${NC}"
    merge_output=$(git merge "$current_branch" 2>&1)
    merge_exit_code=$?
    
    if [ $merge_exit_code -ne 0 ]; then
      echo -e "${RED}❌ 合并失败!${NC}"
      echo -e "${YELLOW}冲突详情:${NC}"
      echo "$merge_output"
      echo ""
      echo -e "${RED}请手动解决冲突后,执行:${NC}"
      echo -e "  1. git status  # 查看冲突文件"
      echo -e "  2. 手动编辑解决冲突"
      echo -e "  3. git add . && git commit"
      echo -e "  4. git push"
      echo ""
      echo -e "${YELLOW}当前仍在分支 '${target_branch}' 上,未自动推送。${NC}"
      return 1
    fi
    
    echo -e "${GREEN}✅ 合并成功${NC}"
    echo ""
    
    # 推送合并后的目标分支
    echo -e "${BLUE}🚀 正在推送分支 '${target_branch}' 到远端...${NC}"
    if git push; then
      echo -e "${GREEN}✅ 推送成功${NC}"
    else
      echo -e "${RED}❌ 推送失败,请检查网络或权限后手动执行 git push${NC}"
      return 1
    fi
    
    # 切换回原业务分支
    echo -e "${BLUE}🔄 切换回原分支 '${current_branch}'...${NC}"
    git checkout "$current_branch" 2>/dev/null
    echo -e "${GREEN}✅ 完成!${NC}"
    return 0
  fi
  
  # ---------- 原有逻辑:没有第二个参数时保持不变 ----------
  # 检查是否有变更
  if git diff --quiet && git diff --cached --quiet; then
    echo -e "${YELLOW}⚠️  没有需要提交的变更${NC}"
    return 0
  fi
  
  # 显示将要提交的文件
  echo -e "${GREEN}📝 变更文件列表:${NC}"
  git status --short
  echo ""
  
  # 检查是否已经有暂存的文件
  if git diff --cached --quiet; then
    # 没有暂存的文件,添加所有变更
    echo -e "${GREEN}✅ 没有暂存的文件,正在添加所有变更...${NC}"
    git add .
    echo -e "${GREEN}✅ 已添加所有变更${NC}"
  else
    # 已经有暂存的文件,不再执行 git add .
    echo -e "${GREEN}✅ 检测到已有暂存的文件,跳过 git add .${NC}"
  fi
  echo ""
  
  # 提交(添加 --no-verify)
  if [ -z "$1" ]; then
    echo -e "${BLUE}💬 请输入提交信息(直接回车打开编辑器):${NC}"
    read -r msg
    if [ -z "$msg" ]; then
      echo -e "${BLUE}正在打开编辑器...${NC}"
      git commit --no-verify
    else
      git commit --no-verify -m "$msg"
    fi
  else
    git commit --no-verify -m "$1"
  fi
  
  # 检查提交是否成功
  if [ $? -ne 0 ]; then
    echo -e "${RED}❌ 提交失败${NC}"
    return 1
  fi
  
  echo -e "${GREEN}✅ 提交成功${NC}"
  echo ""
  
  # 重新获取分支名(防止 commit 时切换了分支)
  current_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
  
  # 推送
  echo -e "${BLUE}🚀 准备推送到远端...${NC}"
  
  # 检查远端分支是否存在
  if git ls-remote --heads origin "$current_branch" 2>/dev/null | grep -q "$current_branch"; then
    echo -e "${GREEN}✅ 远端分支存在,正在推送...${NC}"
    git push
  else
    echo -e "${YELLOW}⚠️  分支 '$current_branch' 在远端不存在,正在创建并推送...${NC}"
    git push --set-upstream origin "$current_branch"
  fi
  
  # 推送结果
  if [ $? -eq 0 ]; then
    echo ""
    echo -e "${GREEN}✅ 完成!${NC}"
    echo -e "   分支: ${GREEN}$current_branch${NC}"
    echo -e "   状态: ${GREEN}已同步到远端${NC}"
  else
    echo -e "${RED}❌ 推送失败,请检查网络连接或权限${NC}"
    return 1
  fi
}


# 快速提交并推送(不检查远端,适合已存在的分支)
alias gap='git add . && git commit --no-verify -m "quick-save" && git push'

# 快速提交带时间戳(适合临时保存)
alias gacpt='git add . && git commit --no-verify -m "save-$(date +%Y%m%d-%H%M%S)" && git push -u origin HEAD 2>/dev/null || git push'

# 查看当前 git 状态(增强版)
alias gs='git status'

# 查看简洁状态
alias gss='git status --short'

# 查看分支
alias gbr='git branch -a'

# 拉取最新代码
alias gp='git pull'

# 推送当前分支到远端并关联
alias gpo='git push -u origin HEAD'

# 切换分支
alias gco='git checkout'

# 创建并切换分支
alias gcob='git checkout -b'

echo "✅ Git 快捷命令已加载:"
echo "   gc     - 普通推送(自动 add .,带 --no-verify)"
echo "   gap    - 快速提交并推送(quick-save,带 --no-verify)"
echo "   gacpt  - 快速提交带时间戳(带 --no-verify)"
echo "   gs     - 查看状态"
echo "   gss    - 查看简洁状态"
echo "   gbr    - 查看分支"
echo "   gp     - 拉取代码"
echo "   gpo    - 推送当前分支到远端并关联"
echo "   gco    - 切换分支"
echo "   gcob   - 创建并切换分支"

整体流程

复制代码
                ┌─────────────────────────────────────────────────┐
                │                  gc 函数入口                     │
                └─────────────────────┬───────────────────────────┘
                                      ↓
                          ┌───────────────────────┐
                          │  $2 是否为空?         │
                          └───────────┬───────────┘
                                      │
                ┌─────────────────────┴─────────────────────┐
                ↓                                           ↓
       【无第二个参数】                              【有第二个参数】
┌─────────────────────────┐                    ┌─────────────────────────┐
│     原有提交流程         │                    │      合并流程            │
├─────────────────────────┤                    ├─────────────────────────┤
│ 1. 检查变更              │                    │ 【第一步】               │
│ 2. git add .(如需)     │                    │ 1. 检查变更              │
│ 3. git commit           │                    │ 2. git add .(如需)     │
│ 4. git push             │                    │ 3. git commit           │
│ 5. 完成                 │                    │ 4. git push 业务分支     │
└─────────────────────────┘                    │                         │
                                                │ 【第二步】               │
                                                │ 5. git checkout 目标分支 │
                                                │ 6. git pull(严格)      │
                                                │ 7. 用户确认合并          │
                                                │ 8. git merge 业务分支    │
                                                │ 9. git push 目标分支     │
                                                │ 10. git checkout 业务分支│
                                                │ 11. 完成                │
                                                └─────────────────────────┘
相关推荐
修己xj1 天前
Gogs: 打造属于你自己的轻量级 Git 服务
git
Mediary1 天前
Git本地忽略文件夹,只拉取目标文件夹
git
小羊Yveesss1 天前
从自动化到自主协同:2026年AIOps 2.0赋能DevOps的变革之路
大数据·自动化·devops
MY_TEUCK1 天前
【git工具篇】Git 常用实战手册:从基础命令到分支冲突解决(开发实战版)
大数据·git
幸运的大号暖贴1 天前
解决Vibe Coding时Idea经常不自动git add问题
java·人工智能·git·intellij-idea·claudecode·opencode
摇滚侠1 天前
如何打开 GitHub,GitHub 是基于 Git 版本控制系统的在线代码托管平台
git·github
MY_TEUCK1 天前
【Git 实习生小白专用】:最安全、永不翻车、公司最爱 的标准版本控制工作流程
git·安全·github
donecoding1 天前
第一次用 git worktree,连踩了三个坑(附无痛清理姿势)
git
spmcor1 天前
解决 Git 中已跟踪目录无法被 .gitignore 忽略的问题
git
qcx232 天前
【AI Engineering · Harness 系列】02 确定性外壳 × 非确定性内核——git push 红线的故事
人工智能·git·prompt·agent·engineering·harness