团队协作久了,本地会堆积大量已合并的分支。每次手动 git branch -d xxx 逐条删除既低效又容易漏掉。今天我们用 OpenCode,4 分钟内用 Go 写出一个命令行 Git 分支清理工具,自动扫描已合并分支并一键清理。
技术栈:Go 1.21+,标准库(os/exec + bufio)
核心功能:
-f 参数跳过安装 Go(1.21+)
安装 OpenCode:参考 opencode.ai
确认 OpenCode 正常工作:在终端输入 opencode 进入交互界面
打开终端,进入工作目录。直接告诉 OpenCode 要做什么:
> 我对 OpenCode 说的提示词:
>
> 用 Go 写一个命令行 Git 分支清理工具 gclean,扫描所有已合并的分支并删除。初始化 go module,项目放在 gclean 目录下。
OpenCode 的响应: 自动执行 mkdir gclean && cd gclean && go mod init gclean,然后生成 main.go:
package main
import (
"fmt"
"os"
"os/exec"
"strings"
)
func main() {
out, err := exec.Command("git", "branch", "--merged").Output()
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
}
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
branch := strings.TrimSpace(line)
if branch == "" {
continue
}
if err := exec.Command("git", "branch", "-d", strings.TrimSpace(branch)).Run(); err != nil {
fmt.Fprintf(os.Stderr, "failed to delete %s: %v\n", branch, err)
} else {
fmt.Printf("deleted: %s\n", branch)
}
}
}
关键要点: OpenCode 生成的代码已经可以直接运行,但有一个问题——它会把 main/master 等保护分支也干掉。我们需要加上安全保护。
> 我对 OpenCode 说的提示词:
>
> 加一个保护分支白名单,main、master、develop 不能删除。把分支名收集到列表里,统一处理。
OpenCode 的响应: 在代码中增加了 protected map 和白名单过滤逻辑,同时把分支收集和删除逻辑分开:
var protected = map[string]bool{
"main": true, "master": true, "develop": true,
}
var branches []string
for _, line := range strings.Split(string(out), "\n") {
branch := strings.TrimSpace(line)
branch = strings.TrimPrefix(branch, "* ")
if branch == "" || protected[branch] {
continue
}
branches = append(branches, branch)
}
关键要点: strings.TrimPrefix(branch, "* ") 这个细节很重要——git branch --merged 输出中,当前分支前面有 * 前缀,直接拿去做删除会导致 branch name 不匹配。
> 我对 OpenCode 说的提示词:
>
> 添加一个确认步骤,删除前列出所有待删分支并让用户输入 y/N 确认。再用 flag 包加一个 -f 参数,跳过确认直接删除。
OpenCode 的响应: 引入了 flag 和 bufio 包,增加了交互确认逻辑:
if !*force {
fmt.Print("\ndelete these branches? [y/N]: ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
if strings.ToLower(strings.TrimSpace(scanner.Text())) != "y" {
fmt.Println("cancelled")
return
}
}
> 我对 OpenCode 说的提示词:
>
> 编译这个项目,生成 gclean.exe 可执行文件。
OpenCode 的响应: 执行 go build -o gclean.exe,编译成功。
然后我们试用一下:
$ ./gclean.exe merged branches: feature/login fix/typo delete these branches? [y/N]: y deleted: feature/login deleted: fix/typo
关键要点: git branch -d 只会删除已经合并的分支,比 -D 更安全。即使代码逻辑有误,Git 自身也会兜底。
package main
import (
"bufio"
"flag"
"fmt"
"os"
"os/exec"
"strings"
)
var protected = map[string]bool{
"main": true, "master": true, "develop": true,
}
func main() {
force := flag.Bool("f", false, "skip confirmation")
flag.Parse()
out, err := exec.Command("git", "branch", "--merged").Output()
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
}
var branches []string
for _, line := range strings.Split(string(out), "\n") {
line = strings.TrimSpace(line)
line = strings.TrimPrefix(line, "* ")
if line == "" || protected[line] {
continue
}
branches = append(branches, line)
}
if len(branches) == 0 {
fmt.Println("no merged branches to clean up")
return
}
fmt.Println("merged branches:")
for _, b := range branches {
fmt.Println(" ", b)
}
if !*force {
fmt.Print("\ndelete these branches? [y/N]: ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
if strings.ToLower(strings.TrimSpace(scanner.Text())) != "y" {
fmt.Println("cancelled")
return
}
}
for _, b := range branches {
if err := exec.Command("git", "branch", "-d", b).Run(); err != nil {
fmt.Fprintf(os.Stderr, "failed to delete %s: %v\n", b, err)
} else {
fmt.Printf("deleted: %s\n", b)
}
}
}
总共 59 行代码,从敲下第一句话到编译出可执行文件,全程不超过 4 分钟。整个过程我只用自然语言描述了 4 次需求,OpenCode 完成了代码生成、模块初始化、编译构建全套流程。
最让我满意的点:
* 前缀的去除,我一开始没提,OpenCode 在第二步就主动加上了-d 的安全策略,双重保障不会误删这就是 OpenCode 的核心价值:把“写代码”变成“描述需求”,让 AI 替你完成机械的编码工作,你只需要关注业务逻辑本身。