GitoxideLabs/gitoxide

GitHub: GitoxideLabs/gitoxide

Gitoxide 是一个用纯 Rust 实现的高性能 Git,旨在提供安全、快速且易于集成的 Git 操作能力,可作为库或命令行工具使用。

Stars: 11208 | Forks: 456

[![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/5c8408489c200525.svg)](https://github.com/GitoxideLabs/gitoxide/actions) [![Crates.io](https://img.shields.io/crates/v/gitoxide.svg)](https://crates.io/crates/gitoxide) `gitoxide` 是一个用 Rust 编写的 `git` 实现,旨在开发追求正确性和性能的面向未来的应用程序,同时提供愉悦且符合预期的开发者体验。 使用 `gitoxide` 主要有两种方式: 1. **作为 Rust 库**:使用 [`gix`](https://docs.rs/gix) crate 作为 Cargo 依赖项以获取 API 访问权限。 2. **作为命令行工具**:`gix` 二进制文件作为开发工具,帮助在真实的代码库中测试 API, 以及带有工作流增强工具的 `ein` 二进制文件。这两个二进制文件可能永远是不稳定的, *不要在脚本中依赖它们*。 [![asciicast](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/2f2a53e2d9200526.svg)](https://asciinema.org/a/542159) ## 开发状态 命令行工具以及每个 crate 的状态在 [crate 状态文档](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md)中进行了描述。 用于应用程序时,请查找 [`gix`](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix) crate, 它作为各种低级底层 crate(例如 [`gix-config`](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-config))所提供功能的入口点。 ### 功能探索 上述问题可能很难回答,本段落旨在帮助您进行功能探索。 请查看 [`crate-status.md`](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md),这是一份相当详尽的文档,其中包含 已实现和计划中的功能。 此外,[带有 `git2` 搜索词的 `gix` crate 文档](https://docs.rs/gix/latest/gix?search=git2)有助于找到所有目前 已知的 `git2` 等效方法调用。请注意,此列表绝对尚未详尽,但如果您是从 `git2` 转型而来,它可能会有所帮助。 以下是一个高级别的功能列表以及计划中的功能: * [x] clone * [x] fetch * [ ] push * [x] blame (*底层管道*) * [x] status * [x] blob 和 tree-diff * [ ] merge - [x] blobs - [x] trees - [ ] commits * [x] commit - [ ] hooks * [x] commit-graph 遍历 * [ ] rebase * [x] worktree checkout 和 worktree stream * [ ] reset * [x] 对象的读写 * [x] refs 的读写 * [x] `.git/index` 的读写 * [x] git 配置的读写 * [x] pathspecs * [x] revspecs * [x] `.gitignore` 和 `.gitattributes` ### Crates 点击链接的 crate 名称以查看详细状态。请注意,所有 crate 均遵循 [semver] 以及 [稳定性指南]。 ### 生产级别 * **稳定性等级 1** - [gix-lock](https://github.com/GitoxideLabs/gitoxide/blob/main/gix-lock/README.md) * **稳定性等级 2** - [gix-tempfile](https://github.com/GitoxideLabs/gitoxide/blob/main/gix-tempfile/README.md) ### 候选稳定版 这些 crate 似乎已功能完整,但需要更多的使用考验才能发布为 1.0 版本。 文档已完整且至少经过了一次审查。 * [gix-mailmap](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-mailmap) * [gix-chunk](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-chunk) * [gix-ref](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-ref) * [gix-config](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-config) * [gix-config-value](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-config-value) * [gix-glob](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-glob) * [gix-actor](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-actor) * [gix-hash](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-hash) ### 初始开发阶段 这些 crate 可能缺少某些功能,因此略有欠缺,但现有部分 在某种程度上是可用的。 * **可用** _(具备粗略但完整的文档,功能可能不完整)_ * [gix](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix) (**⬅ 入口点**) * [gix-object](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-object) * [gix-validate](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-validate) * [gix-url](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-url) * [gix-packetline](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-packetline) * [gix-packetline_blocking](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-packetline) * [gix-transport](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-transport) * [gix-protocol](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-protocol) * [gix-pack](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-pack) * [gix-odb](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-odb) * [gix-commitgraph](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-commitgraph) * [gix-diff](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-diff) * [gix-traverse](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-traverse) * [gix-features](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-features) * [gix-credentials](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-credentials) * [gix-sec](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-sec) * [gix-quote](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-quote) * [gix-discover](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-discover) * [gix-path](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-path) * [gix-attributes](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-attributes) * [gix-ignore](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-ignore) * [gix-pathspec](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-pathspec) * [gix-index](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-index) * [gix-revision](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-revision) * [gix-revwalk](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-revwalk) * [gix-command](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-command) * [gix-prompt](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-prompt) * [gix-refspec](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-refspec) * [gix-fs](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-fs) * [gix-utils](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-utils) * [gix-hashtable](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-hashtable) * [gix-worktree](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-worktree) * [gix-bitmap](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-bitmap) * [gix-negotiate](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-negotiate) * [gix-filter](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-filter) * [gix-worktree-stream](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-worktree-stream) * [gix-archive](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-archive) * [gix-submodule](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-submodule) * [gix-status](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-status) * [gix-worktree-state](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-worktree-state) * [gix-date](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-date) * [gix-dir](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-dir) * [gix-merge](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-merge) * [gix-shallow](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-shallow) * [gix-error](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-error) * `gitoxide-core` * **非常早期** _(可能没有任何文档且有许多粗糙之处)_ * [gix-blame](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-blame) * **构思** _(仅作为名称占位符)_ * [gix-note](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-note) * [gix-fetchhead](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-fetchhead) * [gix-lfs](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-lfs) * [gix-rebase](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-rebase) * [gix-sequencer](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-sequencer) * [gix-tui](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-tui) * [gix-tix](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-tix) * [gix-bundle](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-bundle) * [gix-fsck](https://github.com/GitoxideLabs/gitoxide/blob/main/crate-status.md#gix-fsck) ### 压力测试 * [x] 验证巨大的 pack * [x] 将 pack 解包到磁盘 * [x] 生成并验证大型 commit graph * [ ] 从大量松散对象生成巨大的 pack ### 稳定性和 MSRV 我们的[稳定性指南]有助于判断依赖此工作区中的 crate 时可能预期会有多少变动。 ## 安装 ### 下载二进制发行版 使用 `cargo binstall`,您可以获取[二进制发行版][releases]。假设已安装 [rust 工具链][rustup],您可以通过 `cargo install cargo-binstall` 来安装它。 然后使用 `cargo binstall gitoxide` 安装 gitoxide。 有关手动安装以及根据您的需求(适用于 _Linux_、_MacOS_ 和 _Windows_)提供的各种 _更精简_ 或 _更小巧_ 的替代构建版本,请参阅 [releases 部分][releases]。 ### 从 Arch Linux 仓库下载 对于 Arch Linux,您可以从 `community` 仓库下载 `gitoxide`: ``` pacman -S gitoxide ``` ### 从 Exherbo Linux Rust 仓库下载 对于 Exherbo Linux,您可以从 [Rust](https://gitlab.exherbo.org/exherbo/rust/-/tree/master/packages/dev-scm/gitoxide) 仓库下载 `gitoxide`: ``` cave resolve -x repository/rust cave resolve -x gitoxide ``` ### 通过 Cargo 从源码构建 `cargo` 是 Rust 的包管理器,可以通过 [rustup] 轻松获取。有了它,您可以毫不费力地为您的特定 CPU 构建自己的二进制文件,以获得额外的性能提升。 最低支持的 Rust 版本[已记录在 Cargo 包中](https://github.com/GitoxideLabs/gitoxide/blob/main/gix/Cargo.toml#L12-L14), 最新稳定版也同样适用。 有多种构建配置,它们均已[记录在此处](https://docs.rs/crate/gitoxide/latest)。该文档对于 需要调整外部依赖的打包者也应有所帮助。 ``` # 一种在仅安装 Rust 和 C 编译器的情况下安装 `gitoxide` 的方法。 # 如果在 Clone 期间遇到 SSL 证书问题,请尝试省略 `--locked`。 cargo install gitoxide --locked --no-default-features --features max-pure # 默认安装 'max' 速度最快,但也需要 `cmake` 才能成功构建。 # 安装过程取决于平台。 cargo install gitoxide # 若要以牺牲不太出色的 CLI 实现为代价来换取更小的 Binaries 和更快的构建时间, # 请使用 `lean` feature。 cargo install gitoxide --locked --no-default-features --features lean ``` 以下命令可直接从 git 安装最新未发布的 `max` 版本: ``` cargo install --git https://github.com/GitoxideLabs/gitoxide gitoxide ``` #### 如何处理构建失败 在某些平台上,由于缺少 *C* 工具链所需的工具,安装可能会失败。通常可以通过以下安装方式来避免这种情况: ``` cargo install gitoxide --no-default-features --features max-pure ``` 以下是已知失败的列表。 - 在 Fedora 上,需要安装 `perl` 才能使 `OpenSSL` 正确构建。这可以通过以下命令完成(参见 [issue #592](https://github.com/GitoxideLabs/gitoxide/issues/592)): dnf install perl ### 使用 Docker 某些 CI/CD 流水线会利用代码库克隆。以下是一个可复制粘贴的示例,用于为此类工作流构建 Docker 镜像。 由于(目前)不存在官方镜像,因此必须首先构建一个镜像。 #### 构建最具兼容性的基础镜像 ``` docker build -f etc/docker/Dockerfile.alpine -t gitoxide:latest --compress . --target=pipeline ``` #### 流水线中的基本用法 例如,如果一个 `Dockerfile` 当前使用类似 `RUN git clone https://github.com/GitoxideLabs/gitoxide` 的内容,首先构建该镜像: ``` docker build -f etc/docker/Dockerfile.alpine -t gitoxide:latest --compress . ``` 然后将二进制文件复制到您的镜像中,并将 `git` 指令替换为等效的 `gix` 指令。 ``` COPY --from gitoxide:latest /bin/gix /usr/local/bin/ COPY --from gitoxide:latest /bin/ein /usr/local/bin/ RUN /usr/local/bin/gix clone --depth 1 https://github.com/GitoxideLabs/gitoxide gitoxide ``` ## 使用方法 安装后,有两个二进制文件可用: * **ein** * 高级命令,即 _porcelain_,供日常使用,旨在优化用户体验 * **gix** * 低级命令,即 _plumbing_,用于更专业的情况,并在真实场景中验证新编写的代码 ## 项目目标 随着我们了解的深入,项目目标可能会发生变化,并且它们是可以接受挑战的。 * **纯 Rust 实现的 git** * 包括 *transport*(传输)、*object database*(对象数据库)、*references*(引用)、*cli* 和 *tui* * 为最常见的 git 操作提供了一个简单的命令行界面,针对 用户体验进行了优化。如果你愿意的话,可以称之为一个 *simple-git*。 * 成为任何想要解决 git 相关问题的人的首选实现,并在此过程中成为 `GitPython` 和 *libgit2* 的*那个*替代品。 * 成为 GitHub 分布式替代方案的基础,甚至可能在 GitHub 内部使用 * **向最优秀者学习,以编写出尽可能符合惯用法的最佳 Rust 代码** * *libgit2* 是观察哪些抽象有效的绝佳资源,我们将利用它们 * 利用 Rust 的类型系统使误用成为不可能 * **成为性能最佳的实现** * 利用 Rust 的类型系统来优化未完成的工作,同时不使其难以使用 * 从一开始就利用并行性 * 第一天起便支持 _sparse checkout_(稀疏检出) * **保证磁盘一致性** * 确保读取永远不会干扰并发的写入 * 确保多个并发写入不会引起问题 * **走捷径,但绝不牺牲质量** * 二进制文件可以穷尽地使用 `anyhow::Error`,因为知道这些错误仅面向用户。 * 库使用通过 `quick-error` 或 `thiserror` 实现的轻量级自定义错误。 * 国际化目前不是我们关注的问题。 * 由于打开的文件句柄数量不足而导致的 IO 错误并不总是会导致操作失败 * **跨平台支持,包括 Windows** * 凭借此处可用的工具和经验,没有理由不支持 Windows。 * [Windows 会在 CI 中进行测试](https://github.com/GitoxideLabs/gitoxide/blob/df66d74aa2a8cb62d8a03383135f08c8e8c579a8/.github/workflows/rust.yml#L34) 并且失败确实会阻止发布。 ## 非目标 随着我们了解的深入,项目非目标可能会发生变化,并且它们是可以接受挑战。 * **完美复制 `git` 命令的功能** * `git` 就是 `git`,没有理由不使用它。我们的道路是简洁之路,让 git 的入门变得简单。 * **与 git 不兼容** * 磁盘上的格式必须保持兼容,我们永远不会与其发生冲突。 * **到处使用 async IO** * 在大多数情况下,git 操作严重依赖于内存映射的 IO 以及用于解压数据的 CPU, 这天然不适合开箱即用的 async IO。 * 使用 `blocking` 以及 `gix-features::interrupt` 将操作引入异步世界并控制 长时间运行的操作。 * 当通过 TCP 连接进行连接或式传输时,尤其是在服务器端接收数据时,async 似乎是 必不可少的,但需放在 feature flag 之后。 ## 贡献 如果到目前为止您所看到的内容激发了您贡献的兴趣,那么让我们说:我们很高兴您的加入,并将帮助您入门。 我们建议在开发过程中运行 `just test`,以确保在推送前 CI 是绿灯状态。 可供认领的工作积压[可在项目的看板中找到][project-board],其中包含有关如何 认领任务的说明。如果看板是空的,或者您有其他问题,请随时[发起讨论][discussions]或通过 [keybase][keybase] 私下联系 @Byron。 有关更多详细信息,另请参阅[协作指南]。 ### 通过视频教程入门 - [通过 Gitoxide 学习 Rust](https://youtube.com/playlist?list=PLMHbQxe1e9Mk5kOHrm9v20-umkE2ck_gE) - 在 17 集的内容中,您可以学到有意义地为 `gitoxide` 做贡献所需的一切。 - [走进 Gitoxide](https://youtube.com/playlist?list=PLMHbQxe1e9MkEmuj9csczEK1O06l0Npy5) - 获得 `gitoxide` 本身的介绍,这应该为任何贡献打下良好的基础,但也不是做出贡献的硬性要求。 - [赠予 Gitoxide](https://www.youtube.com/playlist?list=PLMHbQxe1e9MlhyyZQXPi_dc-bKudE-WUw) - 了解 PR 是如何被审查的,以及大量的内心独白。 #### 其他媒体 - [Rustacean Station 播客](https://rustacean-station.org/episode/055-sebastian-thiel/) ## 路线图 ### 1.0 版本的功能 为最基本的用户旅程提供一个 CLI: * [x] 初始化代码库 * [x] fetch * [ ] 以及更新工作区 * clone 一个代码库 - [ ] bare(裸仓库) - [ ] 带有工作树 * [ ] 在添加工作区文件后创建一个 commit * [x] 添加一个 remote * [ ] push * [x] 创建(thin)pack ### 示例想法 * [ ] `gix tool open-remote` 打开 remote 的 URL,可能在应用已知转换(从 `ssh` 转到 `https`)之后。 * [ ] `tix` 作为 `tig` 的示例实现,显示一版 commit graph,有助于练习如何制作高度响应的 GUI。 * [ ] 类似于 [`git-sizer`](https://github.com/github/git-sizer) 的工具,但利用索引 pack 的极限解压速度。 * [ ] 使用 [sqlite virtual tables](https://github.com/rusqlite/rusqlite/blob/master/tests/vtab.rs) 为 git 开启 SQL 支持。也可以查看 gitqlite。 MVP 会是什么样子?甚至可能是可以随 gitoxide 一起发布的东西。请参阅[这个 go 实现作为示例](https://github.com/filhodanuvem/gitql)。 * [ ] 一个真正出色的历史重写工具,它使理解发生的事情变得容易,同时避免所有陷阱。想象一下 BFG,但更棒,如果可能的话。 * [ ] `gix-tui` 应该在数据展示方面从 [fossil-scm] 那里学到很多东西。也许 [这个](https://github.com/Lutetium-Vanadium/requestty/) 可以用于提示。很可能 [magit] 也有很多值得借鉴的地方。 ### 衍生项目想法 * [ ] 一个与 `gix-lfs` 紧密集成的系统,以允许多层架构,从而将资产存储在 git 中并可通过内网位置快速访问 (例如,通过网络以只读方式访问存储),同时服务器会立即将更改推送到其他边缘位置,如 _云_ 或备份。稀疏检出以及资源管理器/Finder 集成 使得仅在本地处理一小部分文件变得方便。克隆可以包含某人在其所在位置高效工作所需的所有配置, 并且针对 git 历史以及 LFS 资源的认证使系统安全。可以想象在 _云_ 中不受信任的位置提供加密支持, 尽管需要进行更多研究才能使其真正安全。 * [ ] 一个类似 [syncthing] 的客户端/服务器应用程序。这是为了展示如何将底层 crate 组合到自定义应用程序中,使其仅使用 部分 git 技术来实现它们自己的目标。注意对大文件的支持、多设备交叉同步、对 不受信任目的地使用全加密的可能性、大小写不敏感与敏感的文件系统,以及扩展文件属性和忽略文件。 * 一个基于事件的数据库,使用 commit 消息来存储增量,同时偶尔在 tree 中聚合实际状态。当然,它天然是分布式的,允许 人们离线工作。 - 它被抽象为完全隐藏其背后的实际数据模型,允许在其之上实现各种功能。 - commits 可能需要为时间戳提供一个纳秒部分,这可以通过自定义 header 字段添加。 - 记录所有更改使得完美的合并成为可能,无论是在客户端还是在服务器上,同时保留自然的审计日志,这使其对于业务中 关键任务的数据库非常有用。 * **应用** - Markdown 可以用作数据库吗,这样问题跟踪器连同元数据就可以仅仅是大部分可由人类编辑的 markdown 文件吗?用户界面 可以感知元数据并仅隐藏那些现在可以在 GUI 本身中编辑的元数据块吗?这样做将使冲突的解决比 `sqlite` 数据库更容易。 - 一个时间追踪器 - 数据简单,天然无冲突,看到团队或公司使用它并以可能由 GitHub 支持认证的方式运作会很有趣。 - 支持多个不同的追踪器怎么样,比如不同的 remote? ## 缺陷与限制 请查看 [`SHORTCOMINGS.md` 文件](https://github.com/GitoxideLabs/gitoxide/blob/main/SHORTCOMINGS.md) 以获取详细信息。 ## 🙏 特别感谢 🙏 至少目前,这一部分专门用来重点介绍 [Josh Triplett](https://github.com/joshtriplett) 为我提供的令人难以置信的支持, 形式包括建议、赞助以及无数其他极具意义的帮助。如果没有他的参与,全职投入 `gitoxide` 几乎不可能 实现,我无比感激 😌。 ## 许可证 该项目遵循以下任一许可证: * Apache 许可证 2.0 版,([LICENSE-APACHE](LICENSE-APACHE) 或 http://www.apache.org/licenses/LICENSE-2.0) * MIT 许可证 ([LICENSE-MIT](LICENSE-MIT) 或 http://opensource.org/licenses/MIT) 任您选择。 ## 趣事 * 最初 @Byron 真的非常着迷于[这个问题](https://github.com/gitpython-developers/GitPython/issues/765#issuecomment-396072153) 并相信有了 `gitoxide`,就能为它提供最快的解决方案。 * @Byron 从 13 多年前第一次体验 `git` 开始,就被它彻底震撼了,并且 尝试以[各种形态](https://github.com/gitpython-developers/GitPython/pull/1028)和[形式](https://github.com/byron/gogit)多次 [实现](
标签:DNS解析, DNS 解析, Git, git2替代, gitoxide, gix, Rust, 代码库, 内存安全, 可视化界面, 安全可观测性, 安全测试工具, 底层库, 开发框架, 开源项目, 版本控制, 网络流量审计, 通知系统