0
点赞
收藏
分享

微信扫一扫

一键搞定:如何用自动化脚本拯救“手动合并”焦虑


一键搞定:如何用自动化脚本拯救“手动合并”焦虑

你是否也经历过这样的时刻:刚写完一大段代码,正准备起身倒杯咖啡放松一下,却猛然想起还有分支需要合并到测试环境。不仅要切换分支、拉代码、合并,还得小心翼翼避免操作失误,仿佛在踩一地的“雷”。更惨的是,这样的操作还不是一次两次,而是反复

在我们项目的开发初期,这一幕几乎每天都在上演。频繁的手动操作不仅让人疲惫,还极大地浪费了开发时间。于是,我们决定放大招:用脚本解放双手,让开发者能安心享受咖啡的香气,而不是纠结在Git命令中。

问题重现:小操作背后的大痛点

每次将功能分支合并到测试环境分支的流程都差不多是这样的:

  1. 切换到目标分支(测试环境分支)。
  2. 拉取最新代码。
  3. 将当前分支合并到目标分支。
  4. 推送合并后的代码到远程。
  5. 切回原来的功能分支。

看起来流程简单?但当你一天需要重复三五次、还要担心是否手抖输错命令时,这种“简单”就变成了开发者的心智噩梦。

问题显而易见:我们需要一种能“傻瓜化”这一切的方式。能不能写个脚本,一键搞定这些事?

决策:写!脚!本!

作为开发者,遇到机械重复的工作,第一个念头当然是:写脚本!解决问题的过程就像RPG游戏闯关一样,让人充满成就感。

于是,我们撸起袖子,干了这件事。目标很明确:
把切换分支、合并、推送这一整套操作“自动化”,让它快到你连咖啡都喝不上一口。

第一关:初版脚本问世

第一版脚本直接用Node.js实现,使用child_process模块来调用Git命令。逻辑很简单:逐步执行“获取当前分支名”、“切换分支”、“拉取代码”、“合并分支”、“推送代码”、“切换回原分支”这些操作。下面是初版代码:

const { exec } = require('child_process')

// 获取命令行参数
const targetBranch = process.argv[2]

if (!targetBranch) {
  console.error('请提供目标分支名')
  process.exit(1)
}

// 获取当前分支名
exec('git rev-parse --abbrev-ref HEAD', (err, stdout, stderr) => {
  if (err) {
    console.error(`exec error: ${err}`)
    return
  }

  const currentBranch = stdout.trim()

  // 切换到目标分支
  exec(`git checkout ${targetBranch}`, (err, stdout, stderr) => {
    if (err) {
      console.error(`exec error: ${err}`)
      return
    }

    // 拉取目标分支的最新代码
    exec(`git pull origin ${targetBranch}`, (err, stdout, stderr) => {
      if (err) {
        console.error(`exec error: ${err}`)
        return
      }

      // 将当前分支的代码合并到目标分支
      exec(`git merge ${currentBranch} --no-ff`, (err, stdout, stderr) => {
        if (err) {
          console.error(`exec error: ${err}`)
          return
        }

        // 推送到远端
        exec(`git push origin ${targetBranch}`, (err, stdout, stderr) => {
          if (err) {
            console.error(`exec error: ${err}`)
            return
          }

          console.log(`代码已成功合并到${targetBranch}分支并推送到远端`)

          // 切换回原来的分支
          exec(`git checkout ${currentBranch}`, (err, stdout, stderr) => {
            if (err) {
              console.error(`exec error: ${err}`)
              return
            }

            console.log(`已切换回${currentBranch}分支`)
          })
        })
      })
    })
  })
})

尽管功能完整,但这个脚本的问题也很明显:回调地狱让代码看起来就像个“意大利面条”,不够优雅!而且处理错误的逻辑不够清晰,维护起来比较麻烦。

一键搞定:如何用自动化脚本拯救“手动合并”焦虑

你是否也经历过这样的时刻:刚写完一大段代码,正准备起身倒杯咖啡放松一下,却猛然想起还有分支需要合并到测试环境。不仅要切换分支、拉代码、合并,还得小心翼翼避免操作失误,仿佛在踩一地的“雷”。更惨的是,这样的操作还不是一次两次,而是反复

在我们国际商城项目的开发初期,这一幕几乎每天都在上演。频繁的手动操作不仅让人疲惫,还极大地浪费了开发时间。于是,我们决定放大招:用脚本解放双手,让开发者能安心享受咖啡的香气,而不是纠结在Git命令中。

问题重现:小操作背后的大痛点

每次将功能分支合并到测试环境分支的流程都差不多是这样的:

  1. 切换到目标分支(测试环境分支)。
  2. 拉取最新代码。
  3. 将当前分支合并到目标分支。
  4. 推送合并后的代码到远程。
  5. 切回原来的功能分支。

看起来流程简单?但当你一天需要重复三五次、还要担心是否手抖输错命令时,这种“简单”就变成了开发者的心智噩梦。

问题显而易见:我们需要一种能“傻瓜化”这一切的方式。能不能写个脚本,一键搞定这些事?

决策:写!脚!本!

作为开发者,遇到机械重复的工作,第一个念头当然是:写脚本!解决问题的过程就像RPG游戏闯关一样,让人充满成就感。

于是,我们撸起袖子,干了这件事。目标很明确:
把切换分支、合并、推送这一整套操作“自动化”,让它快到你连咖啡都喝不上一口。

第一关:初版脚本问世

第一版脚本直接用Node.js实现,使用child_process模块来调用Git命令。逻辑很简单:逐步执行“获取当前分支名”、“切换分支”、“拉取代码”、“合并分支”、“推送代码”、“切换回原分支”这些操作。下面是初版代码:

const { exec } = require('child_process')

// 获取命令行参数
const targetBranch = process.argv[2]

if (!targetBranch) {
  console.error('请提供目标分支名')
  process.exit(1)
}

// 获取当前分支名
exec('git rev-parse --abbrev-ref HEAD', (err, stdout, stderr) => {
  if (err) {
    console.error(`exec error: ${err}`)
    return
  }

  const currentBranch = stdout.trim()

  // 切换到目标分支
  exec(`git checkout ${targetBranch}`, (err, stdout, stderr) => {
    if (err) {
      console.error(`exec error: ${err}`)
      return
    }

    // 拉取目标分支的最新代码
    exec(`git pull origin ${targetBranch}`, (err, stdout, stderr) => {
      if (err) {
        console.error(`exec error: ${err}`)
        return
      }

      // 将当前分支的代码合并到目标分支
      exec(`git merge ${currentBranch} --no-ff`, (err, stdout, stderr) => {
        if (err) {
          console.error(`exec error: ${err}`)
          return
        }

        // 推送到远端
        exec(`git push origin ${targetBranch}`, (err, stdout, stderr) => {
          if (err) {
            console.error(`exec error: ${err}`)
            return
          }

          console.log(`代码已成功合并到${targetBranch}分支并推送到远端`)

          // 切换回原来的分支
          exec(`git checkout ${currentBranch}`, (err, stdout, stderr) => {
            if (err) {
              console.error(`exec error: ${err}`)
              return
            }

            console.log(`已切换回${currentBranch}分支`)
          })
        })
      })
    })
  })
})

尽管功能完整,但这个脚本的问题也很明显:回调地狱让代码看起来就像个“意大利面条”,不够优雅!而且处理错误的逻辑不够清晰,维护起来比较麻烦。

加入快捷命令:让脚本更方便运行

初版脚本虽然功能完整,但每次都要在命令行手动输入 node ./scripts/mergeBranch.js <目标分支> 来运行,还是略显麻烦。为了让团队成员能够更快捷地使用脚本,我们决定将它集成到项目的package.json文件中,通过npm run命令轻松调用。

配置步骤
  1. 打开项目根目录下的package.json文件。
  2. scripts字段中新增一条命令:

"merge:dev": "node ./scripts/mergeBranch.js dev"

这条命令的作用是:将当前分支的代码合并到dev分支,并触发脚本的所有操作。

修改后的package.json文件示例:

{
  "name": "your-project",
  "version": "1.0.0",
  "scripts": {
    "start": "vite",
    "build": "vite build",
    "merge:dev": "node ./scripts/mergeBranch.js dev"
  },
  "dependencies": {
    // 省略其他依赖
  }
}

使用方法

在终端运行以下命令:

npm run merge:dev

这条命令会自动执行脚本,将当前分支的代码合并到dev分支,无需再手动输入目标分支名称。脚本完成所有操作后,会提示合并完成并切换回原分支。

第二关:优化脚本,解放灵魂

为了解决初版的缺陷,我们进行了优化:使用Promiseasync/await重构代码。这样一来,不仅代码逻辑更清晰,还能轻松扩展和处理错误。优化后的代码如下:

const { exec } = require('child_process')

// 封装exec为Promise返回
const execPromise = command => {
  return new Promise((resolve, reject) => {
    exec(command, (err, stdout, stderr) => {
      if (err) {
        reject(err)
      } else {
        resolve(stdout)
      }
    })
  })
}

async function mergeBranch() {
  // 获取命令行参数
  const targetBranch = process.argv[2]

  if (!targetBranch) {
    console.error('请提供目标分支名')
    process.exit(1)
  }

  try {
    // 获取当前分支名
    let currentBranch = await execPromise('git rev-parse --abbrev-ref HEAD')
    currentBranch = currentBranch.trim()

    // 切换到目标分支
    await execPromise(`git checkout ${targetBranch}`)
    // 拉取目标分支的最新代码
    await execPromise(`git pull origin ${targetBranch}`)
    // 将当前分支的代码合并到目标分支
    await execPromise(`git merge ${currentBranch} --no-ff`)
    // 推送到远端
    await execPromise(`git push origin ${targetBranch}`)
    console.log(`代码已成功合并到${targetBranch}分支并推送到远端`)

    // 切换回原来的分支
    await execPromise(`git checkout ${currentBranch}`)
    console.log(`已切换回${currentBranch}分支`)
  } catch (error) {
    console.error(error)
  }
}

mergeBranch()

是不是清爽多了?借助async/await,脚本的流程一目了然,处理错误也变得优雅可靠。


举报

相关推荐

0 条评论