C++ 使用git init、fetch和checkout克隆git存储库
导言 我正在使用流行的用C编写的libgit2进行实验。 我正在尝试做一个克隆,但使用一种不常见的方式。按顺序,git命令: 初始化 git远程添加源https://repository.git git获取源 切换到主分支 通过使用gitbash和以下命令,我可以获得一个包含所有历史记录的现有存储库 问题:C++ 使用git init、fetch和checkout克隆git存储库,c++,libgit2,C++,Libgit2,导言 我正在使用流行的用C编写的libgit2进行实验。 我正在尝试做一个克隆,但使用一种不常见的方式。按顺序,git命令: 初始化 git远程添加源https://repository.git git获取源 切换到主分支 通过使用gitbash和以下命令,我可以获得一个包含所有历史记录的现有存储库 问题: 现在,让我们看看我当前的C++实现。下面的代码试图复制以前编写的git命令的行为 #define url "https://repository.git" #define p
现在,让我们看看我当前的C++实现。下面的代码试图复制以前编写的git命令的行为
#define url "https://repository.git"
#define path "./"
#define user "user"
#define pass "pass"
/** credential callback **/
int credentials(git_cred **cred, const char *, const char *, unsigned int, void *) {
return git_cred_userpass_plaintext_new(cred, user, pass);
}
class Git {
public:
Git() {
git_libgit2_init();
}
~Git() {
git_repository_free(repository);
git_libgit2_shutdown();
}
void update() {
init();
fetch();
checkout();
}
private:
void init() {
assertSuccess(git_repository_init(&repository, path, GIT_CVAR_FALSE));
git_remote *remote = nullptr;
git_remote_callbacks options = GIT_REMOTE_CALLBACKS_INIT;
assertSuccess(git_remote_create(&remote, repository, "origin", url));
options.credentials = credentials;
git_remote_connect(remote, GIT_DIRECTION_FETCH, &options, nullptr, nullptr);
}
void fetch() {
git_remote* remote = nullptr;
assertSuccess(git_remote_lookup(&remote, repository, "origin"));
git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
options.callbacks.credentials = credentials;
assertSuccess(git_remote_fetch(remote, nullptr, &options, nullptr));
}
void checkout() {
git_checkout_options options = GIT_CHECKOUT_OPTIONS_INIT;
options.checkout_strategy = GIT_CHECKOUT_FORCE;
assertSuccess(git_checkout_head(repository, &options));
assertSuccess(git_checkout_index(repository, nullptr, &options));
assertSuccess(git_repository_set_head(repository, "refs/heads/master"));
git_object *treeish = nullptr;
assertSuccess(git_revparse_single(&treeish, repository, "master"));
assertSuccess(git_checkout_tree(repository, treeish, &options));
}
void assertSuccess(int error) {
if (!error) return;
const git_error *e = giterr_last();
std::cout << "code: " << e->klass << " error: " << e->message << std::endl;
exit(1);
}
private:
git_repository *repository = nullptr;
};
int main() {
Git git;
git.update();
return 0;
}
git存储库已经创建,我可以看到通过git bash成功设置的远程源。我可以从GitBash手动执行git签出主控程序,所以我想我当前的签出实现是失败的
有人能告诉我这个错误吗?我找不到足够的资源,也找不到对所有在互联网上找到的例子的支持
编辑
因为测试代码可能会有所帮助,所以让我给出编译libgit2的CMakeLists.txt。源代码
缺少的链接是,由于您是从头开始构建存储库,所以您的存储库仍然未出生,即,它的头指向一个不存在的refs/heads/master ref。除此之外,在libgit2land中,checkout唯一关心的是从ODB中取出文件,它不会写入或更新引用 因此,您缺少git checkout在git update ref中使用的使master指向origin/master的OID的步骤,您可以通过 类似于以下内容: 静态整数设置\跟踪\分支CHAR*分支\名称,git \参考*上游 { git_参考*跟踪; git_oid up_oid=git_参考_目标_对等流; 字符*用户界面名称; 如果0 /*应该从“上游”建造。IIRC有一些 *git_引用访问器可以帮助 *例如,`refs/remotes/origin/heads/master`是`origin/master`。 */ 其他的 ui_name=原点/主节点; 恩迪夫 如果git\u引用\u创建\u匹配和跟踪, git_reference_ownerStream, 分支\u名称,上限\u oid,0,空,分支:从%s创建,ui\u名称<0|| git\u分支\u集合\u上游跟踪,git\u参考\u名称上游<0{ printfailed创建远程跟踪分支\n; 返回-1; } 清理: git_参考_自由跟踪; 返回0; }
这采用了您希望新分支为-b,远程分支为-t的名称,尽管这显然不是完全的重新实现,甚至不是正确的,所以YMMV。你能提供一个完整的例子吗?你能稍微谈谈为什么git clone不适合你吗?我需要在一个文件夹中设置一个git存储库,这个文件夹不是空的,基本上不可能使用git cloneThat,这是有意义的,但是你可以通过将文件移到其他地方,然后再返回来让它工作。如果您的FS具有廉价的重命名,那么可能会更容易。
code: 4 error: reference 'refs/heads/master' not found
cmake_minimum_required(VERSION 3.13)
project(test)
include_directories(libgit/include)
LINK_DIRECTORIES(${LIBSSH2_LIBRARY_DIRS})
add_subdirectory(libgit)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Release)
add_executable(test src/Git.h)
target_link_libraries(test git2)