【鸿蒙PC命令行适配】GitUI 移植的工程实践:双 Git 引擎(libgit2/gitoxide)的鸿蒙适配之路
【鸿蒙PC命令行适配】GitUI 移植的工程实践:双 Git 引擎(libgit2/gitoxide)的鸿蒙适配之路
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

摘要
开源鸿蒙(OpenHarmony)PC 版生态正在快速成长,但终端命令行工具依然稀缺。GitUI 是一款用 Rust 编写的终端 Git 客户端(TUI),依赖 ratatui/crossterm 渲染界面,核心 Git 能力则由 libgit2(经 git2 crate)与 gitoxide(纯 Rust 的 gix crate)双引擎共同提供,HTTPS 走 vendored OpenSSL。
将其移植到鸿蒙 PC(aarch64-unknown-linux-ohos)过程中,最棘手的并非 TUI 本身——Rust 代码大多可以直接交叉编译——而是背后三个"平台敏感"的依赖在鸿蒙沙箱模型与 musl libc 环境下的连环问题:
- vendored OpenSSL 交叉编译失败:
cccrate 找不到正确的交叉编译器,回落宿主 x86_64 GCC 编译 ARM 代码; - libgit2 目录所有权校验误报:鸿蒙的沙箱/单用户文件模型让 libgit2 的 owner 校验(类似 git
safe.directory)直接报Owner (-36); - gitoxide 索引槽位溢出崩溃:大仓库(几十个 pack)在 gix-odb 的固定槽位 slotmap 上触发
InsufficientSlotspanic,revlog、status、tags 等页面相继崩溃。
本文记录这三道坎的诊断过程与最终解法,并提炼出一条可复用的工程模式:在双引擎架构中,用 cfg(target_env) 按目标平台切换后端实现,而不是逐个依赖打补丁。
项目地址:
- 移植仓库:ohos-gitui(
main分支) - 上游 PR:gitui-org/gitui #2954(待合并)
- 上游仓库:gitui
1. 项目概览
| 项目 | 信息 |
|---|---|
| 目标平台 | OpenHarmony/HarmonyOS aarch64(aarch64-unknown-linux-ohos) |
| 编译器 | OHOS SDK clang 15.0.4(llvm/bin/clang) |
| 语言/构建 | Rust 1.88+ / Cargo(vendored OpenSSL) |
| 上游版本 | gitui 0.28.1(紧随上游 master 更新) |
| 核心依赖 | libgit2(git2 0.21)、gitoxide(gix 0.84)、OpenSSL 3.x(openssl-sys vendored) |
| 链接方式 | 动态链接 musl libc(/lib/ld-musl-aarch64.so.1) |
| 产物大小 | 约 15MB(release + LTO) |
| 构建状态 | ✅ 100% 构建成功,核心页面全部可用 |
| 移植周期 | 2026-05 起持续迭代 |
2. 为什么 GitUI 不能"直接编译过"?
GitUI 的界面层是纯 Rust(ratatui),理论上交叉编译到 OHOS 并无障碍——真正的问题集中在 Git 能力层的三个依赖上:
问题 1:OpenSSL 必须从源码构建。 GitUI 的 vendor-openssl 特性(默认开启)会让 openssl-sys 拉取 OpenSSL 源码现场编译。而 OpenSSL 的构建系统是 Configure + Make,跨平台编译时编译器选择完全依赖环境变量——这一步在鸿蒙目标上极其容易翻车。
问题 2:libgit2 带"安全校验"。 libgit2 在打开仓库时会做目录所有权校验(owner validation,与 git 的 safe.directory 同源,用于防范 CVE-2022-24765 一类攻击)。它比较文件系统上的 UID 与当前进程 EUID,这在传统 Linux 上是合理的安全防线,但在鸿蒙的沙箱文件模型下却成了误报源头。
问题 3:双引擎意味着双份平台兼容债。 GitUI 用 git2 承担 staging/diff/reset 等写操作,同时用 gix(gitoxide)承担 status 遍历、commit 解码、tag 枚举等读操作。任何一方的平台适配出问题,都会导致特定页面崩溃。
这三类问题叠加,构成了一个"表面能编、一跑就崩"的典型移植场景。
3. 环境准备
3.1 工具链
| 工具 | 版本/路径 | 说明 |
|---|---|---|
| Rust target | aarch64-unknown-linux-ohos | rustup target add aarch64-unknown-linux-ohos |
| OHOS SDK | command-line-tools(华为开发者网站下载) | 提供 clang/llvm-ar/sysroot |
| Clang | 15.0.4 | <SDK>/native/llvm/bin/clang |
| llvm-ar | 同 SDK | <SDK>/native/llvm/bin/llvm-ar |
SDK 下载:HarmonyOS command-line-tools,默认安装路径
~/command-line-tools/sdk/default/openharmony。
3.2 Cargo 目标配置(.cargo/config.toml)
[env]
CC_aarch64_unknown_linux_ohos = "/path/to/sdk/native/llvm/bin/clang"
CXX_aarch64_unknown_linux_ohos = "/path/to/sdk/native/llvm/bin/clang++"
[target.aarch64-unknown-linux-ohos]
linker = "/path/to/sdk/native/llvm/bin/clang"
ar = "/path/to/sdk/native/llvm/bin/llvm-ar"
rustflags = [
"-C", "link-arg=-target", "-C", "link-arg=aarch64-unknown-linux-ohos",
"-C", "link-arg=--sysroot=/path/to/sdk/native/sysroot",
"-C", "link-arg=-L/path/to/sdk/native/sysroot/usr/lib/aarch64-linux-ohos",
"-C", "link-arg=-Wl,--allow-multiple-definition",
"-C", "link-arg=-Wl,--undefined-version",
"-C", "link-arg=-Wl,--defsym=__xpg_strerror_r=0",
]
三个细节的来历:
--allow-multiple-definition/--undefined-version:OHOS 的 musl libc 与 Rust std 之间偶有符号重复/版本节差异,链接期放宽可规避;--defsym=__xpg_strerror_r=0:解决 musl 中strerror_r符号解析问题;CC_<triple>环境变量:这是第 4 节的主角,必须通过[env]或 shell 环境变量设置。
4. 难点一:vendored OpenSSL 交叉编译失败——cc crate 的"隐形回落"
问题诊断
第一次执行 cargo build --target aarch64-unknown-linux-ohos --release,编译到 openssl-sys 时在 C 代码里报:
crypto/arm_arch.h:50:6: error: #error "unsupported ARM architecture"
乍看是 OpenSSL 不认识 OHOS 架构。但仔细看 Makefile 里 PLATFORM=linux-aarch64 是对的,问题出在:
CC=$(CROSS_COMPILE)cc # ← 竟然是宿主 x86_64 GCC!
根本原因:OpenSSL 是由 openssl-src 的 build script 调用 cc crate 编译的。cc crate 选择编译器的顺序是:CC_<target> 环境变量 → CC → 系统 cc。我们虽然在 .cargo/config.toml 里配了 linker 和 ar,但那是给 rustc 链接期 用的,cc crate 根本不读 linker 配置——于是它静默回落到了宿主机的 x86_64 gcc,拿 x86_64 编译器去编 ARM 目标,arm_arch.h 自然找不到任何 ARM 架构宏,直接 #error。
.cargo/config.toml 的 linker ──→ 只服务 rustc 链接(final link)
✗ 不作用于 C 依赖编译
CC_aarch64_unknown_linux_ohos ──→ cc crate 查找(openssl/libgit2 等 C 代码)
✓ 这才是 C 交叉编译的开关
解决方案
在 .cargo/config.toml 顶部加 [env] 段,把 OHOS clang 注入为 C 编译器(同时配 CXX 以防 C++ 依赖):
[env]
CC_aarch64_unknown_linux_ohos = "/path/to/sdk/native/llvm/bin/clang"
CXX_aarch64_unknown_linux_ohos = "/path/to/sdk/native/llvm/bin/clang++"
注意 SDK 的 clang 默认 target 是宿主 x86_64,但作为 “generic clang” 它支持 -target aarch64-unknown-linux-ohos,且能自动找到内置 sysroot 的 include 路径,所以只要把它指给 cc crate 即可,无需额外传 --target。
通用适配模式提炼
Cargo 交叉编译有三套独立的工具链配置,别混淆:
[env] CC_<triple>→ C 依赖编译(cccrate);[target.<triple>] linker→ rustc 最终链接;[target.<triple>] rustflags→ 传给链接器的系统库路径与特殊 flag。排查交叉编译失败时,先确认 C 代码用的是哪个编译器——
cargo build -vv里搜CC=一行即可现形。
5. 难点二:libgit2 目录所有权校验误报——“不是当前用户拥有”
问题诊断
交叉编译通过后,在鸿蒙上运行报错:
Error: invalid repo path: repository path '.../iwara' is not owned by
current user; class=Config (7); code=Owner (-36)
更诡异的是:同一个目录下两个仓库,一个能打开、一个报错——这正是"按目录 UID 校验"的典型特征:两个仓库目录在鸿蒙文件系统上被记录了不同的 owner,libgit2 拿它们和当前进程 EUID 比较,一部分对不上就拒绝打开。
根本原因:鸿蒙的用户/进程模型是沙箱式的,文件系统层的 owner/UID 语义与进程视角并不一致(并非传统多用户 Linux 的"我的文件 vs 别人的文件")。libgit2 默认开启的 owner validation(对应 git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION),与 git 的 safe.directory 同一设计动机)在此场景下成为误报源。
解决方案
git2 crate 暴露了全局开关 git2::opts::set_verify_owner_validation(bool)。在鸿蒙目标上关闭它即可。为了避免给其他平台引入安全风险,所有改动都用 #[cfg(target_env = "ohos")] 条件编译隔离,且用 std::sync::Once 保证只初始化一次:
// asyncgit/src/sync/repository.rs
#[cfg(target_env = "ohos")]
use std::sync::Once;
#[cfg(target_env = "ohos")]
static INIT_OHOS: Once = Once::new();
#[cfg(target_env = "ohos")]
pub(crate) fn init_ohos_owner_validation() {
INIT_OHOS.call_once(|| {
#[allow(unsafe_code)]
unsafe {
git2::opts::set_verify_owner_validation(false).ok();
}
});
}
pub fn repo(repo_path: &RepoPath) -> Result<Repository> {
#[cfg(target_env = "ohos")]
init_ohos_owner_validation();
// ... Repository::open_ext(...)
}
需要在两个入口调用:repo()(所有同步 Git 操作的统一入口)与 repo_open_error()(启动时 ensure_valid_path 的校验入口),确保任何打开仓库的路径都已先关闭校验。
安全取舍说明:owner validation 是为多用户系统设计的防社工攻击防线。鸿蒙是单用户沙箱模型,目录归属的威胁模型不同,关闭该校验的收益(能打开本机自己的仓库)大于风险,故仅在
target_env = "ohos"下生效,不影响 Linux/macOS 等其他平台。
验证效果
修改后启动不再报 Owner 错误,之前"打不开"的那个仓库也能正常进入。
6. 难点三:gitoxide 槽位溢出崩溃——InsufficientSlots
这是整个移植中最隐蔽、也最有代表性的一道坎。
问题诊断
在 DevEcoStudio 项目这类大型仓库里,GitUI 会以两种方式崩溃:
场景 1:切换 log 页签(revlog)
panicked at asyncgit/src/revlog.rs:186:14:
failed to fetch: Gix(HeadPeelToCommit(PeelToObject(Peel(PeelReference(
ToId(Find(LoadIndex(InsufficientSlots { current: 32, needed: 4 }))))))))
场景 2:切换 files 页签(status)
Error: gix error: ... The slotmap turned out to be too small with 32
entries, would need 26 more
根本原因:gitoxide 的 ODB(对象数据库)采用"动态发现 + 槽位管理"的架构。gix-odb 的 dynamic store 用一张固定容量的 slotmap 管理已发现的 pack index / 多包索引 / loose object 目录;当仓库的索引文件数量(或刷新时新发现的索引数)超过初始槽位数时,load_index.rs 直接返回:
Error::InsufficientSlots {
current: self.files.len(), // 32
needed: index_paths_to_add.len() + 1, // 还要再加 20+ 个
}
也就是说:仓库 pack 越多、越大(DevEcoStudio 工程动辄几十上百个 pack),越容易踩中这个上限。这本质上是 gix-odb 0.7x 的实现缺陷(槽位扩容策略缺失),不是 GitUI 逻辑错误,也无法在应用层通过配置规避。
方案对比
| 方案 | 优点 | 缺点 | 结论 |
|---|---|---|---|
| 修复 gix-odb(fork/patch) | 根治 | 需维护整个 gix 依赖链的分叉,上游合入前每次升级都要重打 | ❌ 成本过高 |
| 等待上游修复 | 无成本 | gix 迭代周期不可控,且跨架构无法立刻验证 | ❌ 不可行 |
| 鸿蒙目标整体切回 git2 后端 | git2 无此问题,改动集中在少数入口 | OHOS 分支与上游 gix 演进需同步适配 | ✅ 采用 |
选方案 C 的关键前提是:GitUI 本来就是 git2/gix 双引擎架构,多数功能都有对应的 git2 实现(get_commits_info、LogWalker、repo.statuses() 等)。我们要做的不是给 gix 打补丁,而是在鸿蒙目标上把"默认走 gix"的入口切换成"走 git2"——一处切换,全链路受益。
解决方案:cfg 双后端切换
所有改动遵循同一模式:非 OHOS 平台保留原 gix 实现,OHOS 平台走 git2 实现。
(1)revlog:无 filter 的 commit 遍历
GitUI 的 log 页签在无搜索过滤时走 LogWalkerWithoutFilter(gix 实现),有过滤时走 LogWalker(git2 实现)。鸿蒙上把无过滤路径也切到 git2——LogWalker 本身支持 filter=None(全量收录),只需传一个恒真 filter:
fn fetch_helper(/* ... */, filter: Option<SharedCommitFilterFn>) -> Result<()> {
#[cfg(target_env = "ohos")]
{
Self::fetch_helper_with_filter(
repo_path, arc_current, arc_background, sender,
filter.unwrap_or_else(|| {
Arc::new(Box::new(|_: &git2::Repository, _: &CommitId| Ok(true)))
}),
)
}
#[cfg(not(target_env = "ohos"))]
{
filter.map_or_else(/* 原 gix 路径 */, /* 原 git2 路径 */)
}
}
(2)status:工作区/暂存区状态
get_status() 原实现完全基于 gix(repo.status(...).into_index_worktree_iter(...) 等)。鸿蒙版改用 git2 的 repo.statuses():
#[cfg(target_env = "ohos")]
pub fn get_status(/* ... */) -> Result<Vec<StatusItem>> {
let repo = repo(repo_path)?;
let mut options = StatusOptions::default();
options
.show(status_type.into()) // WorkingDir/Stage/Both → StatusShow
.update_index(true)
.include_untracked(/* ... */)
.renames_head_to_index(true)
.recurse_untracked_dirs(/* ... */);
let statuses = repo.statuses(Some(&mut options))?;
for entry in statuses.iter() {
let Ok(path) = entry.path() else { continue };
let status = entry.status();
if status_type == StatusType::Both {
// 暂存与工作区各自独立成条目
if status.is_wt_new() /* ... */ {
res.push(StatusItem { path: path.to_string(), status: StatusItemType::from_wt(status) });
}
if status.is_index_new() /* ... */ {
res.push(StatusItem { path: path.to_string(), status: StatusItemType::from_index(status) });
}
} else {
res.push(StatusItem { path: path.to_string(), status: status.into() });
}
}
res.sort_by(...);
Ok(res)
}
为支持 Both(stash 场景需要区分"已暂存/未暂存"),给 StatusItemType 增加了 from_wt() 与 from_index() 两个按位域转换的辅助方法,避免原 From<Status> 合并两种状态导致的语义丢失。
(3)tags:标签枚举
get_tags() 原实现走 gix 引用迭代 + Tag::decode。鸿蒙版改用 git2:
#[cfg(target_env = "ohos")]
pub fn get_tags(repo_path: &RepoPath) -> Result<Tags> {
let repo = repo(repo_path)?;
let tag_names = repo.tag_names(None)?;
for name in tag_names.iter().flatten() {
let Some(name) = name else { continue };
let Ok(reference) = repo.find_reference(&format!("refs/tags/{name}")) else { continue };
let target = reference.target(); // 指向的 commit
let tag = reference.peel_to_tag(); // 若为附注标签则解码
if let (Some(commit_id), Ok(tag)) = (target, tag) {
adder(commit_id.into(), Tag {
name: tag.name().unwrap_or(name).to_string(),
annotation: tag.message()?.map(ToString::to_string),
});
} else if let Some(commit_id) = target {
adder(commit_id.into(), Tag::new(name)); // 轻量标签
}
}
Ok(res)
}
(4)commit_info:单提交信息
get_commit_info() 原走 gix(find_commit + decode)。鸿蒙版直接委托已有的 git2 批量实现 get_commits_info()(单元素数组),把 “gix 专用解码逻辑” 从鸿蒙构建中整体裁剪。
(5)收尾:裁剪 gix 死代码
当上述入口都切到 git2 后,gix_repo() 及一批 gix-only 函数在 OHOS 构建里变成死代码(该 crate #![deny(dead_code)]),需要一并 cfg:
// repository.rs / mod.rs
#[cfg(not(target_env = "ohos"))]
pub fn gix_repo(repo_path: &RepoPath) -> Result<gix::Repository> { /* ... */ }
// status.rs / tags.rs / commits_info.rs / revlog.rs
#[cfg(not(target_env = "ohos"))]
use crate::sync::{gix_repo, LogWalkerWithoutFilter}; // 依文件而异
(6)文档同步
在 CONTRIBUTING.md 增加 “Cross-compiling for OpenHarmony” 一节,说明 SDK 下载地址、环境变量配置与注意事项,让后续维护者可以复现构建。
验证效果
| 功能页面 | 修复前 | 修复后 |
|---|---|---|
| 启动(repo 打开) | ❌ Owner (-36) | ✅ |
| log 页签(revlog) | ❌ InsufficientSlots panic | ✅ |
| files 页签(status) | ❌ InsufficientSlots error | ✅ |
| tags 页签 | ⚠️ 有风险(gix 引用迭代) | ✅ |
| commit 详情 | ⚠️ 有风险(gix decode) | ✅ |
| 大仓库(58+ pack) | ❌ | ✅ |
通用适配模式提炼
“双引擎架构下的按平台切换,优于逐个依赖打补丁。”
当项目天然存在两套后端实现(或新旧两套 API),且其中一套在目标平台不可靠时,优先在调用入口做cfg(target_env)分流,而不是深入第三方依赖内部修 bug——后者会把项目绑死在一个分叉版本上。代价是双实现需要跟上上游 API 演进(见第 7 节),因此要把平台差异集中到尽量少的文件中,并辅以
cfg(not(target_env))让非目标平台完全不感知改动。
7. 上游同步与 API 迁移(持续跟进)
移植分支不冻结,而是持续合并上游 master。上游在 2026 年中做了一次大的依赖升级:gix 0.78 → 0.84、git2 0.20 → 0.21。由于我们的改动全部收敛在"切换层"(cfg 分支 + 少量 git2 调用),与上游的 gix 内部重构天然不冲突,git merge master 几乎零冲突。
真正需要动手的是 git2 0.21 的破坏性 API 变更,恰好影响我们新增的 OHOS fallback 代码:
| git2 0.20 | git2 0.21 | 影响位置 |
|---|---|---|
StatusEntry::path() → Option<&str> | → Result<&str, Error> | status.rs |
Tag::name() → &str | → Option<&str> | tags.rs |
Tag::message() → Option<&str> | → Result<Option<&str>, Error> | tags.rs |
适配工作量很小:let Some(path) = ... 改为 let Ok(path) = ...,name/message 的取值处加一层解包。这说明平台差异代码越薄,上游升级成本越低——第 6 节"集中切换层"的设计在这里获得了回报。
8. 构建与部署
8.1 构建
rustup target add aarch64-unknown-linux-ohos
# 设置 .cargo/config.toml(见第 3.2 节)后:
cargo build --target aarch64-unknown-linux-ohos --release
产物:
target/aarch64-unknown-linux-ohos/release/gitui
≈ 15MB ELF 64-bit LSB pie executable, ARM aarch64
interpreter /lib/ld-musl-aarch64.so.1
8.2 代码签名
与 Neovim 移植一样,鸿蒙要求所有可执行文件必须签名后才能运行。开发阶段使用自签名即可:
# 自签名(适用于开发环境)
binary-sign-tool sign -inFile gitui -outFile gitui -selfSign 1
# 验证签名
binary-sign-tool verify -inFile gitui
关于签名工具:
binary-sign-tool随 DevBox(鸿蒙应用开发 IDE)附带,无需单独下载——直接在应用商店安装 DevBox 即可获得该工具。
8.3 运行验证
在鸿蒙 PC 终端进入任意 Git 仓库(如 DevEcoStudio 工程目录)后执行:
cd /storage/Users/currentUser/Documents/DevEcoStudioProjects/iwara
./gitui
逐项验证:
| 功能 | 结果 |
|---|---|
| 仓库打开(含大中型工程) | ✅ |
| log 历史翻页 / 搜索 | ✅ |
| files 页签状态遍历 | ✅ |
| stage/unstage / diff 预览 | ✅ |
| tags 列表 / commit 详情 | ✅ |
| 非 Git 目录启动 | ✅ 提示 invalid repo path 后退出(与上游一致) |
9. 总结与展望
9.1 关键成果
| 维度 | 数值 |
|---|---|
| 构建期问题 | 1 个(vendored OpenSSL 交叉编译) |
| 运行期问题 | 2 类(owner 校验误报 / gix 槽位溢出) |
| 新增 Rust 代码 | 约 150 行(全部 cfg(target_env = "ohos") 隔离) |
| 修改文件 | 6 个(repository/utils/status/tags/commits_info/revlog + CONTRIBUTING.md) |
| 上游 PR | gitui-org/gitui #2954 |
9.2 核心方法论
模式一:Cargo 交叉编译三套工具链要分清(见第 4 节)
C 编译器(
CC_<triple>)、rustc 链接器(linker)、系统库 flag(rustflags)是三条独立的配置通道,cargo build -vv是定位此类问题的最快路径。
模式二:平台安全特性按威胁模型取舍(见第 5 节)
移植到沙箱型单用户系统时,源自多用户安全模型的校验(owner validation / safe.directory)可能变成误报源。用
cfg(target_env)精准关闭,而不是全局降级安全。
模式三:双引擎架构按平台切换后端(见第 6 节)
与其 fork 修复第三方依赖的平台缺陷,不如在调用入口层按平台分流到已有且可靠的另一套后端。平台差异代码越薄,跟随上游升级的成本越低。
9.3 下一步建议
- 上游推进:推动 gitui-org 合并 #2954,将 OHOS 支持纳入主线;
- 回馈 gitoxide:
InsufficientSlots是 gix-odb 的通用缺陷,值得向 gix 上游提交扩容/动态增长方案,让所有 gitoxide 用户受益; - 打包分发:研究鸿蒙 HNP 打包与签名,让 gitui 可通过包管理器一键安装;
- 生态复制:该双后端切换模式可复用于其他同时依赖 libgit2 与 gitoxide 的 Rust 工具。
10. 常见问题(FAQ)
Q1:编译时报 arm_arch.h: #error "unsupported ARM architecture"?
C 依赖(OpenSSL)回落到了宿主编译器。确认 .cargo/config.toml 的 [env] 段里 CC_aarch64_unknown_linux_ohos 指向 OHOS SDK 的 clang,然后 cargo clean 后重编。
Q2:运行时提示 repository path ... is not owned by current user?
这是 libgit2 的 owner 校验在鸿蒙沙箱模型下的误报。请使用已含修复的移植分支(init_ohos_owner_validation 会在启动时自动关闭该校验);若为旧版本,可在代码初始化处调用 git2::opts::set_verify_owner_validation(false)。
Q3:log/files 页签崩溃,报 InsufficientSlots { current: 32, ... }?
gix-odb 的槽位溢出,常见于 pack 数较多的大仓库。移植分支已将 status/tags/commit-info/revlog 在 OHOS 上切换为 libgit2 后端,升级到最新即可;若坚持使用 gix,可尝试 git gc 合并 pack 减少索引数量,但这只是缓解。
Q4:--allow-multiple-definition 等链接 flag 是做什么的?
OHOS 的 musl libc 与 Rust std 存在少量符号重复与版本节差异,这些 flag 用于放宽链接期的符号冲突;--defsym=__xpg_strerror_r=0 解决 strerror_r 的解析问题。它们只影响链接行为,不影响产物正确性。
Q5:如何跟随上游更新移植分支?
git fetch origin master
git merge origin/master # 几乎零冲突(改动集中在 cfg 切换层)
cargo build --release # 宿主回归
cargo build --target aarch64-unknown-linux-ohos --release # 鸿蒙验证
11. 参考资料
- ohos-gitui 移植仓库(atomgit)
- 上游 PR:gitui-org/gitui #2954
- gitui 上游仓库
- libgit2 owner validation(GIT_OPT_SET_OWNER_VALIDATION)
- gitoxide / gix-odb dynamic store
- HarmonyOS command-line-tools 下载
- 本专栏系列:鸿蒙PC命令行适配
欢迎更多开发者加入鸿蒙生态建设,共同推动开源软件在 HarmonyOS 上的繁荣发展。
也欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net
本文首发于 CSDN 【鸿蒙PC命令行适配】专栏
最后更新:2026-09-03
文章版本:v1.0
更多推荐




所有评论(0)