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

如何正确使用git2::Remote::push?git2.rs本地推送失败排查

git2.rs 推送本地仓库到裸仓库失败问题排查

问题背景

我正在开发一个用git2.rs管理Git操作的内部应用,在编写git init、git add、commit和推送远程仓库的测试用例时,卡在了推送环节。

测试流程是:先创建普通本地仓库,完成初始化Git、创建文件、添加到索引、提交操作,这部分流程均正常。接着创建本地裸仓库作为origin远程,调用remote实例的push方法无报错,但仓库内容并未被推送。裸仓库中仅包含Git结构文件,将该裸仓库克隆到新目录后,也看不到提交的文件,得到的是空仓库。

相关代码

定义的Git trait

use git2::Repository;
use std::path::PathBuf;

pub trait Git {
    // ... 其他方法省略...

    fn _set_remote<'a, T: Into<PathBuf>>(
        repo_dir: T,
        name: &str,
        url: &str,
    ) -> Result<(), git2::Error> {
        let repo = Self::_repo(repo_dir)?;
        repo.remote(name, url)?;
        Ok(())
    }

    fn git_init(&self) -> Result<Repository, git2::Error>;
    fn git_add<'a, E: Into<&'a str>>(&self, expr: E) -> Result<git2::Index, git2::Error>;
    fn git_commit<'a, M: Into<&'a str>>(&self, message: M) -> Result<git2::Oid, git2::Error>;
    fn git_set_remote(&self, name: &str, url: &str) -> Result<(), git2::Error>;
}

测试代码实现

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write;

    struct TestGit {
        pub dir: PathBuf,
        pub state: String,
    }

   // TestGit 基础实现省略...

    impl Git for TestGit {
        fn git_init(&self) -> Result<Repository, git2::Error> {
            // ... 实现省略
        }

        fn git_add<'a, E: Into<&'a str>>(&self, expr: E) -> Result<git2::Index, git2::Error> {
            // ... 实现省略
        }

        fn git_commit<'a, M: Into<&'a str>>(&self, message: M) -> Result<git2::Oid, git2::Error> {
            // ... 实现省略
        }

        fn git_set_remote(&self, name: &str, url: &str) -> Result<(), git2::Error> {
            Self::_set_remote(&self.dir, name, url)
        }
    }

   // init、add、commit等基础测试用例省略...

    #[test]
    fn test_push() {
        let testgit = TestGit {
            dir: std::env::current_dir().unwrap().join("test/base"),
            state: String::from("Hello"),
        };

        let base_repo = testgit.git_init().unwrap();

        let testgitremote = create_testgit_instance("test/remote");
        <TestGit as Git>::_init::<&PathBuf>(&testgitremote.dir, true).unwrap();

        testgit
            .git_set_remote(
                "origin",
                format!("file://{}", testgitremote.dir.to_str().unwrap()).as_str(),
            )
            .unwrap();

        testgit.write_file("test.txt").unwrap(); // 在仓库根目录创建test.txt,内容为"Hello"

        testgit.git_add(".").unwrap();
        testgit.git_commit("test commit").unwrap();
        // 到这一步都正常,之前的测试验证过提交后索引有新增内容

        let mut remote = base_repo.find_remote("origin").unwrap();

        remote.push::<&str>(&[], None).unwrap(); // 这里是问题所在,推测没有推送实际内容,但git2.rs文档没讲清楚,源码里也没找到push示例

        let mut clonebuilder = git2::build::RepoBuilder::new();

        let clonerepo_dir = testgit.dir.parent().unwrap().join("clone");

        clonebuilder
            .clone(remote.url().unwrap(), &clonerepo_dir)
            .unwrap();

        assert!(clonerepo_dir.join("test.txt").exists()); // 断言失败

        std::fs::remove_dir_all(&testgit.dir.parent().unwrap()).unwrap();
    }
}

已尝试的无效方案

  • 手动指定refspec推送:
let mut remote = base_repo.find_remote("origin").unwrap();

remote.push::<&str>(&["refs/heads/master:refs/heads/master"], None).unwrap();
  • 先添加推送配置再推送:
let mut remote = base_repo.find_remote("origin").unwrap();

base_repo
    .remote_add_push("origin", "refs/heads/master:refs/heads/master")
    .unwrap();

remote.push::<&str>(&[], None).unwrap();

求助需求

希望找出推送失败的原因,给出git2.rs中正确的推送实现方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:53:12