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

调用os.system命令后Python代码仅处理首个Git仓库即停止的问题

解决Git批量推送脚本仅处理第一个仓库的问题

问题根源

你的代码中使用os.chdir()修改了进程的全局工作目录,处理第一个Git仓库后,当前工作目录切换到该仓库根目录,导致后续os.walk()基于新的工作目录继续遍历,无法找到初始路径下的其他仓库。即使使用线程,线程共享进程的工作目录,第一个线程的os.chdir()操作仍会干扰主线程的遍历逻辑。

解决方案核心

不修改全局工作目录,而是在执行Git命令时直接指定仓库路径。可以通过Git的-C参数指定工作目录,或使用subprocess模块的cwd参数实现。


方案1:基于os.system的修改版本

import os
import threading

def push_repository(repo_path):
    try:
        # 使用git -C参数指定仓库路径,无需切换全局工作目录
        os.system(f'git -C "{repo_path}" add *')
        # 捕获commit输出,避免无修改时的报错中断流程
        commit_output = os.popen(f'git -C "{repo_path}" commit -m "Automated commit"').read()
        print(f"{repo_path} 提交结果:\n{commit_output}")
        push_output = os.popen(f'git -C "{repo_path}" push').read()
        print(f"{repo_path} 推送结果:\n{push_output}")
    except Exception as e:
        print(f"{repo_path} 处理出错: {str(e)}")

def commit_and_push_git_folders(path):
    for root, dirs, files in os.walk(path):
        if '.git' in dirs:
            print(f"找到仓库: {os.path.join(root, '.git')}")
            # 仓库根目录即为当前root路径
            t = threading.Thread(target=push_repository, args=(root,))
            t.start()
            # 移除.git目录,避免遍历其内部文件,提升效率
            dirs.remove('.git')

commit_and_push_git_folders('.')

方案2:更健壮的subprocess版本(推荐)

subprocess模块比os.system更灵活,能更好地处理命令输出和错误:

import os
import threading
import subprocess

def push_repository(repo_path):
    try:
        # 执行git add操作
        add_result = subprocess.run(
            ['git', '-C', repo_path, 'add', '*'],
            capture_output=True,
            text=True
        )
        if add_result.returncode != 0:
            print(f"{repo_path} 添加文件失败: {add_result.stderr.strip()}")
            return
        
        # 执行git commit,无修改时返回非0属于正常情况
        commit_result = subprocess.run(
            ['git', '-C', repo_path, 'commit', '-m', 'Automated commit'],
            capture_output=True,
            text=True
        )
        if commit_result.returncode == 0:
            print(f"{repo_path} 提交成功:\n{commit_result.stdout.strip()}")
        else:
            print(f"{repo_path} 无修改可提交:\n{commit_result.stderr.strip()}")
        
        # 执行git push操作
        push_result = subprocess.run(
            ['git', '-C', repo_path, 'push'],
            capture_output=True,
            text=True
        )
        if push_result.returncode == 0:
            print(f"{repo_path} 推送成功:\n{push_result.stdout.strip()}")
        else:
            print(f"{repo_path} 推送失败:\n{push_result.stderr.strip()}")
            
    except Exception as e:
        print(f"{repo_path} 处理异常: {str(e)}")

def commit_and_push_git_folders(path):
    for root, dirs, files in os.walk(path):
        if '.git' in dirs:
            print(f"找到仓库: {os.path.join(root, '.git')}")
            t = threading.Thread(target=push_repository, args=(root,))
            t.start()
            dirs.remove('.git')

commit_and_push_git_folders('.')

关键改进点

  1. 移除os.chdir()操作,改用git -C <仓库路径>指定命令执行的工作目录,不影响全局进程状态。
  2. 在os.walk中移除.git目录,避免遍历其内部文件,提升遍历效率。
  3. 增强错误处理,捕获命令执行的输出,方便排查问题。

内容的提问来源于stack exchange,提问作者Alexander Shestak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:58:21