如何正确使用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
相关产品推荐
相关产品推荐

