Python脚本化Git的操作详解

 更新时间:2024年03月15日 08:58:01   作者:郝同学的测开笔记  
如何判定此次测试是否达标,代码覆盖率是衡量的标准之一,利用fastapi框架重写了覆盖率统计服务,然后通过diff操作统计增量代码覆盖率,当然要使用diff操作,避免不了与git打交道,那python如何操作gi t呢,本文将详细介绍了Python脚本化Git的操作

前言

如何判定此次测试是否达标,代码覆盖率是衡量的标准之一。前段时间,利用fastapi框架重写了覆盖率统计服务,核心其实就是先获取全量代码覆盖率,然后通过diff操作统计增量代码覆盖率,当然要使用diff操作,避免不了与git打交道,那python如何操作gi t呢?

GitPython

GitPython库提供了访问和操作Git仓库的方法,使得在Python环境下进行Git操作变得非常简单。

安装GitPython

使用pip包管理器来安装GitPython:

pip install gitpython

克隆仓库

在开始使用GitPython操作Git仓库之前,我们首先需要克隆一个Git仓库到本地。下面是一个简单的示例代码:

from git import Repo
​
​
remote_url = 'https://github.com/username/repository.git'
local_path = '/path/to/local/repository'
​
​
Repo.clone_from(remote_url, local_path)

上述代码中,设置远程仓库的URL和本地路径,最后使用Repo.clone_from()方法来克隆远程仓库到本地。

当然,如果本地仓库已经存在,就不需要调用clone_from()进行克隆了,可以增加判断,变为下面这样

remote_url = 'https://github.com/username/repository.git'
local_path = '/path/to/local/repository'
if os.path.exists(local_path):
    repo = Repo(local_path)
else:
    repo = Repo.clone_from(remote_url, local_path)

我们判断了本地仓库是否存在,不存在进行克隆,如果存在直接实例化

获取分支信息

接下来,我们将获取已克隆仓库的所有分支信息。

from git import Repo
​
repo_path = '/path/to/your/git/repository'
​
repo = Repo(repo_path)
branches = repo.heads
​
for branch in branches:
    print(f"Branch: {branch.name}, Commit ID: {branch.commit}")

通过heads来获取所有分支,然后遍历输出分支名称和对应的 commit ID

提交更改

要提交更改,我们需要添加文件到暂存区,并提交更改。

from git import Repo
​
repo_path = '/path/to/your/git/repository'
​
repo = Repo(repo_path)
repo.index.add(['file1.py', 'file2.py'])
repo.index.commit("Commit message")

这部分功能,在代码覆盖率统计中未用到,这里做一个记录了解吧。

查看状态

from git import Repo
​
​
​
repo_path = '/path/to/your/git/repository'
​
repo = Repo(repo_path)
​
repo_status = repo.git.status()
print(repo_status)

代码中通过status来查看状态,其实和gi t的命令是一样的。

切换分支和合并代码

from git import Repo
​
​
​
repo_path = '/path/to/your/git/repository'
repo = Repo(repo_path)
​
repo.git.checkout('develop')
​
repo.git.merge('feature-branch')
​

以上代码使用checkout切换到指定分支然后使用merge合并代码。

获取远程仓库的最新变更

from git import Repo
​
​
repo_path = '/path/to/your/git/repository'
​
repo = Repo(repo_path)
repo.fetch()

从远程仓库获取最新的提交记录、分支和文件,但并不自动合并到本地代码。它只是将远程仓库的最新变更拉取到本地,但不会自动更新工作目录中的文件。这意味着在执行 git fetch 后,需要手动进行合并或重新基于远程分支进行开发。

diff操作

from git import Repo
​
​
repo_path = '/path/to/your/git/repository'
​
repo = Repo(repo_path)
repo.git.diff(base_branch, current_branch)

使用 git.diff() 方法比较了 base_branch 和 current_branch 之间的差异

实战案例

下面讲一下笔者统计增量覆盖率的核心代码

    def get_diff(self, current_branch: str, base_branch: str = "origin/master"):
        """获取版本之间代码差异"""
        diff = self.repo.git.diff(base_branch, current_branch).split("\n")
​
        ret = {}
        file_name = ""
        diff_lines = []
        current_line = 0
        for line in diff:
            if line.startswith("diff --git"):
                if file_name != "":
                    ret[file_name] = diff_lines
                file_name = re.findall("b/(\S+)$", line)[0]
                diff_lines = []
                current_line = 0
​
            elif re.match("@@ -\d+,\d+ +(\d+),\d+ @@", line):
                match = re.match("@@ -\d+,\d+ +(\d+),\d+ @@", line)
                current_line = int(match.group(1)) - 1
​
            elif line.startswith("-"):
                continue
            elif line.startswith("+") and not line.startswith("+++"):
                current_line += 1
                diff_lines.append(current_line)
            else:
                current_line += 1
        ret[file_name] = diff_lines
        return ret

这段用于获取两个分支之间的代码差异。

  • get_diff 方法接受两个参数 current_branchbase_branch,分别表示当前分支和基准分支,默认为 "origin/master"。
  • 通过调用 self.repo.git.diff(base_branch, current_branch) 方法获取基准分支和当前分支之间的代码差异,并将结果按行拆分成列表。
  • 使用一个字典 ret 来存储代码差异的信息,其中键为文件名,值为差异的行号列表。
  • 遍历代码差异行,根据行的内容进行不同的处理:

    • 如果遇到以 "diff --git" 开头的行,则表示开始处理一个新文件的差异,提取文件名。
    • 如果匹配到以 "@@ -\d+,\d+ +(\d+),\d+ @@" 格式的行,则提取新版本代码的起始行号。
    • 如果遇到以 "-" 开头的行,则表示该行在基准分支中有但在当前分支中没有,忽略。
    • 如果遇到以 "+" 开头且不以 "+++" 开头的行,则表示该行在当前分支中新增,记录当前行号并添加到差异行列表中。
    • 其他情况下,当前行号递增。
  • 最后将最后一个文件的差异行信息添加到字典中,并返回整体的差异信息。

这段代码的作用是从 Git 中提取两个版本之间的代码差异信息,并以文件名及差异行号的形式存储返回。

最后

GitPython极大方便了python操作gi t,让我更快速的实现了增量代码覆盖率的统计工作,当然这里只是笔者在实现覆盖率统计工作中用到的GitPython相关的方法,还有更多方法。

以上就是Python脚本化Git的操作详解的详细内容,更多关于Python脚本化Git 的资料请关注脚本之家其它相关文章!

相关文章

  • python实现自动发送报警监控邮件

    python实现自动发送报警监控邮件

    这篇文章主要为大家详细介绍了python实现自动发送报警监控邮件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Python实现csv文件(点表和线表)转换为shapefile文件的方法

    Python实现csv文件(点表和线表)转换为shapefile文件的方法

    这篇文章主要介绍了Python实现csv文件(点表和线表)转换为shapefile文件的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • 昨晚我用python帮隔壁小姐姐P证件照然后发现

    昨晚我用python帮隔壁小姐姐P证件照然后发现

    大家好,我是Lex 喜欢欺负超人那个Lex 建议大家收藏哦,以后帮小姐姐P自拍,证件照,调尺寸,背景,抠图,直接10行代码搞定,瞬间高大上
    2021-08-08
  • 使用Python实现图片位深转换终极指南

    使用Python实现图片位深转换终极指南

    图片位深(Bit Depth)指的是每个像素用于表示颜色的位数,常见的位深包括,1位,8位,24位和32位,本文主要介绍了如何使用Python实现图片位深转换,感兴趣的小伙伴可以了解下
    2025-07-07
  • 详解Python发送邮件实例

    详解Python发送邮件实例

    这篇文章主要介绍了Python发送邮件实例,Python发送邮件需要smtplib和email两个模块,感兴趣的小伙伴们可以参考一下
    2016-01-01
  • Python 中PyQt5 点击主窗口弹出另一个窗口的实现方法

    Python 中PyQt5 点击主窗口弹出另一个窗口的实现方法

    这篇文章主要介绍了Python 中PyQt5 点击主窗口弹出另一个窗口的实现方法,本文代码实例图文相结合的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • pandas按行按列遍历Dataframe的几种方式

    pandas按行按列遍历Dataframe的几种方式

    这篇文章主要介绍了pandas按行按列遍历Dataframe的几种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Tensorflow 定义变量,函数,数值计算等名字的更新方式

    Tensorflow 定义变量,函数,数值计算等名字的更新方式

    今天小编就为大家分享一篇Tensorflow 定义变量,函数,数值计算等名字的更新方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • 基于python实现一个简单的浏览器引擎

    基于python实现一个简单的浏览器引擎

    浏览器引擎是用来处理、渲染和显示网页内容的核心组件,其主要任务是将用户输入的URL所代表的网页资源加载并呈现出来,通常包括HTML、CSS、JavaScript以及各种多媒体内容,本文给大家介绍了如何基于python实现一个简单的浏览器引擎,需要的朋友可以参考下
    2024-10-10
  • Python中的Django视图与路由

    Python中的Django视图与路由

    本文给大家介绍Python中的Django视图与路由的相关操作,我们就从基础概念到实战代码,一步步拆解Django视图与路由的核心知识点,感兴趣的朋友一起看看吧
    2025-09-09

最新评论