使用go-github创建提交遇422错误:更新非快进式
问题原因与修复方案
错误根源
你这段代码的逻辑存在核心问题:
- 你先拉取了分支当前的提交(记为
C1),直接修改它的提交信息后就调用CreateCommit生成新提交C2 - 但原提交
C1的父节点是它自己的上游提交(比如C0),所以新创建的C2的父节点依然是C0,而非C1 - 此时分支的HEAD指向
C1,你试图把分支改为指向C2,但C2并不是C1的后代——二者是共享同一父节点的兄弟提交,这种更新不属于快进式更新(快进要求目标提交必须是当前HEAD的直接后代),因此GitHub API返回422错误。
修复后的代码
要实现仅修改提交信息、且属于快进更新的操作,需要让新提交以当前分支的HEAD作为父节点,同时复用原提交的Tree(保证不修改文件内容)。修改后的代码如下:
func GHAPICreateCommit(ctx context.Context, client *github.Client, commitOpts *CommitOptions) error { // 获取分支引用 ref, _, err := client.Git.GetRef(ctx, repoOwner, commitOpts.Repo, "refs/heads/"+commitOpts.Branch) if err != nil { return err } // 获取当前分支的最新提交 originalCommit, _, err := client.Git.GetCommit(ctx, repoOwner, commitOpts.Repo, *ref.Object.SHA) if err != nil { return err } // 构造新提交:以原提交为父节点,复用原Tree,仅修改提交信息 newCommitReq := &github.Commit{ Message: github.String(commitOpts.CommitMessage), Tree: originalCommit.Tree, // 复用原提交的Tree,不改动任何文件 Parents: []*github.Commit{{SHA: originalCommit.SHA}}, // 将原提交设为新提交的父节点 } // 创建新提交 newCommit, _, err := client.Git.CreateCommit(ctx, repoOwner, commitOpts.Repo, newCommitReq) if err != nil { return err } // 更新分支引用指向新提交 ref.Object.SHA = newCommit.SHA _, _, err = client.Git.UpdateRef(ctx, repoOwner, commitOpts.Repo, ref, false) if err != nil { return err } return nil }
关键说明
- 新提交必须以原分支的HEAD提交作为父节点,这样新提交就是原提交的直接后代,分支更新时才会被判定为快进式更新
- 复用原提交的
Tree对象,确保不会修改任何文件内容,完全匹配你的需求
内容的提问来源于stack exchange,提问作者pkaramol
相关产品推荐
相关产品推荐

