You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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}")
问题分析
  1. API接口选择错误:原脚本使用/git/refs/tags接口,该接口返回的标签引用中,附注标签的object.sha指向标签对象本身而非对应Commit SHA,导致无法匹配到目标Tag。
  2. Authorization头格式不统一:两个函数分别使用Bearer和Token前缀,虽GitHub均支持,但统一格式更规范。
  3. 未处理分页:若仓库标签数量较多,/git/refs/tags默认仅返回30个标签,可能遗漏目标Tag。
修复方案
  1. 改用/repos/{owner}/{repo}/tags接口,该接口直接返回标签完整信息,支持区分轻量标签(取object.sha)和附注标签(取关联Commit的sha)。
  2. 统一使用Bearer {auth_token}作为Authorization头格式。
  3. 实现分页遍历逻辑,确保覆盖所有标签,避免遗漏。
修复后的代码
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 13:35:18