如何实现GitHub Compare Commit API返回结果的分页
核心原因
GitHub Compare Commit 接口本身不支持标准分页逻辑,接口硬编码限制单次返回最多300个变更文件,传入per_page、page等常规分页参数不会生效,响应头也不会生成分页用的Link字段,和你请求写法是否正确没有关系,翻官方分页指南找不到对应方案是正常的。
替代实现方案
要拿到两个commit/分支之间的全量变更文件,只能绕开原生compare接口,用支持分页的commits列表接口搭配单commit详情查询曲线实现,逻辑如下:
- 分页拉取base节点到head节点之间的所有commit列表,直到遍历到base节点为止
- 逐个查询每个commit的变更文件列表
- 对重复出现的文件路径做去重,最终得到全量变更文件集合
JavaScript可运行实现代码如下:
async function getFullCompareFileList(owner, repo, baseRef, headRef, githubToken) { const requestHeaders = { 'Accept': 'application/vnd.github+json', 'Authorization': `Bearer ${githubToken}`, 'X-GitHub-Api-Version': '2022-11-28' }; const changedFileSet = new Set(); let currentPage = 1; let stopFetch = false; while (!stopFetch) { // 拉取当前页的commit列表 const commitListResp = await fetch( `https://api.github.com/repos/${owner}/${repo}/commits?sha=${headRef}&per_page=100&page=${currentPage}`, { headers: requestHeaders } ); if (!commitListResp.ok) { throw new Error(`拉取commit列表失败,状态码:${commitListResp.status}`); } const commitList = await commitListResp.json(); if (commitList.length === 0) break; for (const commitItem of commitList) { // 遍历到基准commit时停止拉取 if (commitItem.sha.startsWith(baseRef)) { stopFetch = true; break; } // 拉取单个commit的详情,获取变更文件 const commitDetailResp = await fetch( `https://api.github.com/repos/${owner}/${repo}/commits/${commitItem.sha}`, { headers: requestHeaders } ); if (!commitDetailResp.ok) { throw new Error(`拉取commit ${commitItem.sha} 详情失败,状态码:${commitDetailResp.status}`); } const commitDetail = await commitDetailResp.json(); commitDetail.files.forEach(file => changedFileSet.add(file.filename)); } currentPage++; } return Array.from(changedFileSet); } // 调用示例 // getFullCompareFileList('仓库所属组织/用户名', '仓库名', '基准commit/分支', '目标commit/分支', '你的GitHub个人访问令牌') // .then(fileList => console.log('全量变更文件:', fileList)) // .catch(err => console.error('执行失败:', err));
使用说明
- 必须传入有效的GitHub个人访问令牌,未鉴权的API请求每小时仅60次额度,很容易触发限流;鉴权后每小时额度为5000次,可满足绝大多数场景需求
- 如果两个比对节点之间commit数量极大,会产生较多API请求,建议根据业务场景加本地缓存,减少重复请求
- 该方案返回的结果和原生compare接口的文件列表一致,同时可以突破原生接口最多返回300个文件的限制
内容的提问来源于stack exchange,提问作者Andrew B
相关产品推荐
相关产品推荐

