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

使用PyGithub批量提交文件到单个Commit时遇路径格式错误

修复 "tree.path contains a malformed path component" 异常

问题根源分析

你的代码存在三个核心问题导致该异常:

  1. Git Blob内容错误:你把文件路径字符串传给了create_git_blob的content参数,而非读取文件的实际内容,这不仅生成无效Blob,还会干扰后续路径处理。
  2. 路径格式不兼容Git要求:
    • 本地路径包含./apiproxy前缀,仓库中的路径需要是相对于该目录的相对路径(而非完整本地路径)。
    • Windows环境下路径分隔符是\,但Git要求使用/作为路径分隔符,必须替换。
  3. Base Tree获取错误:直接用分支名sandbox调用get_git_tree是错误的,分支名对应的是Commit对象,需要从分支最新Commit中获取Tree的SHA值。

修复步骤

1. 读取文件实际内容创建Blob

替换content=file为读取文件内容的逻辑,确保Blob存储的是文件本身的数据:

with open(file, 'r', encoding='utf-8') as f:
    content = f.read()
blob = repo.create_git_blob(content=content, encoding='utf-8')

2. 修正仓库内的路径格式

将本地路径转换为仓库内的相对路径,去掉前缀并统一分隔符:

# 生成相对于./apiproxy的路径
repo_path = os.path.relpath(file, start='./apiproxy')
# 替换系统分隔符为Git兼容的/
repo_path = repo_path.replace(os.sep, '/')

3. 正确获取Base Tree

从分支的最新Commit中获取Tree对象:

branch = repo.get_branch('sandbox')
base_tree = repo.get_git_tree(branch.commit.commit.tree.sha)

完整修复代码

from github import Github, InputGitTreeElement
import os

g = Github("XXXTokenXXX")
GITHUB_REPO = "你的仓库名/仓库路径"

def get_all_file_paths(directory): 
    file_paths = [] 
    for root, directories, files in os.walk(directory): 
        for filename in files: 
            filepath = os.path.join(root, filename) 
            file_paths.append(filepath) 
    return file_paths       
    
file_paths = get_all_file_paths("./apiproxy")

try:
    repo = g.get_repo(GITHUB_REPO)
    branch = repo.get_branch(branch="sandbox")
    base_tree = repo.get_git_tree(branch.commit.commit.tree.sha)
   
    tree_elements = []
   
    for file in file_paths: 
        # 读取文件实际内容
        with open(file, 'r', encoding='utf-8') as f:
            content = f.read()
        blob = repo.create_git_blob(content=content, encoding='utf-8')
        
        # 转换为仓库内的相对路径
        repo_path = os.path.relpath(file, start='./apiproxy')
        repo_path = repo_path.replace(os.sep, '/')
        
        tr = InputGitTreeElement(
            path=repo_path,
            mode="100644",
            type="blob",
            sha=blob.sha,
        )
        tree_elements.append(tr)    
   
    new_tree = repo.create_git_tree(tree_elements, base_tree=base_tree)
   
    # 创建Commit并更新分支
    commit = repo.create_git_commit(
        message="Add multiple files",
        tree=new_tree,
        parents=[branch.commit.commit],
    )  
    # 将分支指向新创建的Commit
    repo.get_git_ref(f"heads/{branch.name}").edit(sha=commit.sha)

    print(f'成功提交到 {branch.name} 分支,Commit SHA: {commit.sha}')

except Exception as e: 
    print(f"错误详情: {e}")
    print('Git操作失败')

额外说明

  • 若需要将文件放到仓库的apiproxy目录下(而非根目录),可修改路径生成逻辑:repo_path = f"apiproxy/{os.path.relpath(file, start='./apiproxy')}"后再替换分隔符。
  • 处理二进制文件时,需将编码改为base64并读取二进制内容:
    with open(file, 'rb') as f:
        content = f.read()
    blob = repo.create_git_blob(content=content, encoding='base64')
    

内容的提问来源于stack exchange,提问作者Arunava Paul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:54:53