如何通过Python获取GitHub中关联指定Commit的Tag
问题
我编写了一段Python脚本,用于获取main分支的最新Commit SHA,以及基于该Commit创建的Tag。我们的流程是代码合并到main分支后会自动创建Tag,但目前脚本无法获取到对应的Tag。原脚本代码如下:
def get_latest_hash_id(repo_owner, repo_name, branch_name, auth_token): url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits/{branch_name}" headers = { "Authorization": f"Bearer {auth_token}" } response = requests.get(url, headers=headers) if response.status_code == 200: data = response.json() return data['sha'] return None def get_tag_with_hash(repo_owner, repo_name, hash_id, auth_token): url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/git/refs/tags" headers = { "Authorization": f"Token {auth_token}" } response = requests.get(url, headers=headers) if response.status_code == 200: data = response.json() print("json data = " ,data) for tag in data: if tag['object']['sha'] == hash_id: return tag['ref'] repo_owner = "company" repo_name = "app-api" branch_name = "main" auth_token = getpass.getpass("Enter your GitHub personal access token: ") hash_id = get_latest_hash_id(repo_owner, repo_name, branch_name, auth_token) if hash_id: tag = get_tag_with_hash(repo_owner, repo_name, hash_id, auth_token) if tag: print(f"The latest hash ID on branch {branch_name} is {hash_id}, and the tag created from that hash ID is: {tag}") else: print(f"No tag found with hash ID {hash_id}") else: print(f"No hash ID found for branch {branch_name}")
问题分析
- API接口选择错误:原脚本使用
/git/refs/tags接口,该接口返回的标签引用中,附注标签的object.sha指向标签对象本身而非对应Commit SHA,导致无法匹配到目标Tag。 - Authorization头格式不统一:两个函数分别使用
Bearer和Token前缀,虽GitHub均支持,但统一格式更规范。 - 未处理分页:若仓库标签数量较多,
/git/refs/tags默认仅返回30个标签,可能遗漏目标Tag。
修复方案
- 改用
/repos/{owner}/{repo}/tags接口,该接口直接返回标签完整信息,支持区分轻量标签(取object.sha)和附注标签(取关联Commit的sha)。 - 统一使用
Bearer {auth_token}作为Authorization头格式。 - 实现分页遍历逻辑,确保覆盖所有标签,避免遗漏。
修复后的代码
import requests import getpass def get_latest_hash_id(repo_owner, repo_name, branch_name, auth_token): url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits/{branch_name}" headers = { "Authorization": f"Bearer {auth_token}", "Accept": "application/vnd.github.v3+json" } response = requests.get(url, headers=headers) if response.status_code == 200: data = response.json() return data['sha'] print(f"获取最新Commit失败: {response.status_code} - {response.text}") return None def get_tag_with_hash(repo_owner, repo_name, hash_id, auth_token): headers = { "Authorization": f"Bearer {auth_token}", "Accept": "application/vnd.github.v3+json" } page = 1 while True: url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/tags?page={page}&per_page=100" response = requests.get(url, headers=headers) if response.status_code != 200: print(f"获取标签列表失败: {response.status_code} - {response.text}") break tags = response.json() if not tags: break # 无更多标签可遍历 for tag in tags: # 匹配轻量标签 if tag['object']['type'] == 'commit' and tag['object']['sha'] == hash_id: return tag['name'] # 匹配附注标签,需请求标签详情获取关联Commit SHA elif tag['object']['type'] == 'tag': tag_detail_res = requests.get(tag['object']['url'], headers=headers) if tag_detail_res.status_code == 200: tag_detail = tag_detail_res.json() if tag_detail['object']['sha'] == hash_id: return tag['name'] page += 1 return None if __name__ == "__main__": repo_owner = "company" repo_name = "app-api" branch_name = "main" auth_token = getpass.getpass("Enter your GitHub personal access token: ") hash_id = get_latest_hash_id(repo_owner, repo_name, branch_name, auth_token) if hash_id: tag = get_tag_with_hash(repo_owner, repo_name, hash_id, auth_token) if tag: print(f"main分支最新Commit SHA: {hash_id}, 对应的Tag: {tag}") else: print(f"未找到与SHA {hash_id}关联的Tag") else: print(f"无法获取main分支的最新Commit SHA")
内容的提问来源于stack exchange,提问作者Ajay k
相关产品推荐
相关产品推荐

