如何使用GitHub API从其他仓库cherry-pick提交
GitHub API没有提供直接的跨仓库cherry-pick端点,但可以通过模拟Git的cherry-pick流程来实现,以下是具体步骤:
前提条件
- 拥有repo1和repo2两个仓库的读写权限
- 生成具有
repo权限的GitHub个人访问令牌(PAT)
步骤1:获取repo1目标提交的Patch内容
先拿到要cherry-pick的提交的patch数据,这包含了该提交的所有变更:
curl -H "Authorization: token YOUR_GITHUB_PAT" https://api.github.com/repos/OWNER/repo1/commits/TARGET_COMMIT_SHA.patch
保存返回的patch内容,后续用于在repo2中应用变更。
步骤2:获取repo2目标分支的基础信息
获取repo2目标分支的最新commit SHA和对应的tree SHA,作为后续操作的基础:
# 获取目标分支的最新commit信息 curl -H "Authorization: token YOUR_GITHUB_PAT" https://api.github.com/repos/OWNER/repo2/branches/TARGET_BRANCH_NAME
从返回结果中提取commit.sha(记为BASE_COMMIT_SHA)和commit.tree.sha(记为BASE_TREE_SHA)。
步骤3:将Patch变更转换为GitHub API可识别的文件更新
Patch中的每个文件变更都需要单独处理:
获取目标文件的原始内容:针对patch中修改的每个文件,从repo2的基础tree中获取当前内容:
curl -H "Authorization: token YOUR_GITHUB_PAT" https://api.github.com/repos/OWNER/repo2/git/blobs/${BASE_TREE_SHA}:FILE_PATH将返回的
content(base64编码)解码后,应用patch中的修改,得到更新后的文件内容。创建新的Blob对象:将更新后的文件内容重新编码为base64,创建新的blob:
curl -X POST -H "Authorization: token YOUR_GITHUB_PAT" -H "Content-Type: application/json" \ https://api.github.com/repos/OWNER/repo2/git/blobs \ -d '{ "content": "BASE64_ENCODED_UPDATED_CONTENT", "encoding": "base64" }'记录返回的
sha(记为NEW_BLOB_SHA)。创建新的Tree对象:基于基础tree,替换修改后的文件对应的blob:
curl -X POST -H "Authorization: token YOUR_GITHUB_PAT" -H "Content-Type: application/json" \ https://api.github.com/repos/OWNER/repo2/git/trees \ -d '{ "base_tree": "'"${BASE_TREE_SHA}"'", "tree": [ { "path": "FILE_PATH", "mode": "100644", "type": "blob", "sha": "'"${NEW_BLOB_SHA}"'" } ] }'记录返回的
sha(记为NEW_TREE_SHA)。
步骤4:创建Cherry-Pick提交
基于新的tree和基础commit,创建一个新的提交,复用原提交的信息:
curl -X POST -H "Authorization: token YOUR_GITHUB_PAT" -H "Content-Type: application/json" \ https://api.github.com/repos/OWNER/repo2/git/commits \ -d '{ "message": "Cherry-pick: ORIGINAL_COMMIT_MESSAGE", "tree": "'"${NEW_TREE_SHA}"'", "parents": ["'"${BASE_COMMIT_SHA}"'"] }'
记录返回的sha(记为NEW_COMMIT_SHA)。
步骤5:更新repo2的目标分支
将目标分支的引用指向新创建的commit:
curl -X PATCH -H "Authorization: token YOUR_GITHUB_PAT" -H "Content-Type: application/json" \ https://api.github.com/repos/OWNER/repo2/git/refs/heads/TARGET_BRANCH_NAME \ -d '{ "sha": "'"${NEW_COMMIT_SHA}"'", "force": false }'
注意:如果目标分支在操作期间有新提交,会出现冲突,此时需要先拉取最新变更解决冲突,或者设置
force: true强制推送(不推荐,可能覆盖他人提交)。
冲突处理
如果patch应用时出现冲突,GitHub API不会自动解决,你需要:
- 创建一个临时分支,基于目标分支的最新commit
- 在本地克隆repo2的临时分支,手动解决冲突
- 将解决后的变更推送到临时分支
- 合并临时分支到目标分支(通过API或Web界面)
内容的提问来源于stack exchange,提问作者Dave Haron

