首页 > 解决方案 > 尝试使用 libgit2 快进时“无法在符号引用上设置 OID”

问题描述

注意:我标记了CC++,因为libgit2是一个C库,并且我正在为常见的 git 命令编写一个C++包装器。我们将在这里看到CC++代码,就我而言,如果我得到面向CC++的解决方案并不重要(如果需要,我会自己调整它)。


gitPull()当分支可快速转发(使用libgit2)时,我正在尝试对函数中的存储库执行快进更新。我只想在必要时执行合并。

我的策略如下所示(我删除了错误检查,......为了只针对基本要素并使代码尽可能简单):

// INFO: I assume here I already have an open repository in a "repo" variable.

// Do the fetch --> works fine
// ...

// Compare HEAD and FETCH_HEAD
git_oid head_id;
git_reference_name_to_id(&head_id, repo, "HEAD");
git_oid fetch_head_id;
git_reference_name_to_id(&fetch_head_id, repo, "FETCH_HEAD");

if(!git_oid_equal(&fetch_head_id, &head_id)) // A pull is needed
{
    // Check if we can fast-forward or need a merge
    git_annotated_commit * fetch_head_annotated_commit = nullptr;
    git_annotated_commit_lookup(&fetch_head_annotated_commit, repo, &fetch_head_id);

    git_merge_analysis_t an_out;
    git_merge_preference_t pref_out;
    git_merge_analysis(&an_out, &pref_out, repo, const_cast<const git_annotated_commit **>(&fetch_head_annotated_commit),1);

    if(an_out & GIT_MERGE_ANALYSIS_FASTFORWARD) // A fast-forward is possible
    {
        git_reference * head_ref = nullptr;
        git_reference_lookup(&head_ref, repo, "HEAD");

        git_reference * new_head_ref = nullptr;
        git_reference_set_target(&new_head_ref, head_ref, &fetch_head_id, "");

        git_checkout_head(repo, nullptr);

        git_reference_free(new_head_ref);
        git_reference_free(head_ref);
    }
    else // A merge is needed
    {
        // Do the merge and create the related commit
        // ...
    }
    git_annotated_commit_free(fetch_head_annotated_commit);
}

奇怪的是条件if(an_out & GIT_MERGE_ANALYSIS_FASTFORWARD)true,但是当我运行该函数时git_reference_set_target(&new_head_ref, head_ref, &fetch_head_id, "");,出现以下错误:

“无法在符号引用上设置 OID”


我进行了一项研究,我在refs.clibgit2的源代码中发现了您可以在下面看到的内容:

static int ensure_is_an_updatable_direct_reference(git_reference *ref)
{
    if (ref->type == GIT_REFERENCE_DIRECT)
        return 0;

    git_error_set(GIT_ERROR_REFERENCE, "cannot set OID on symbolic reference");
    return -1;
}

int git_reference_set_target(
    git_reference **out,
    git_reference *ref,
    const git_oid *id,
    const char *log_message)
{
    int error;
    git_repository *repo;

    assert(out && ref && id);

    repo = ref->db->repo;

    if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0)
        return error;

    return git_reference_create_matching(out, repo, ref->name, id, 1, &ref->target.oid, log_message);
}

通过阅读这段代码,我们可以看到问题在于在我的例子中是“HEAD”ref引用的参数不是“可更新的直接引用”。 换句话说,没有找到从“HEAD”“FETCH_HEAD”的直接路径(因为我通过了)。
fetch_head_id

我不明白的是,如果我是正确的,检查分支是否可以快进的方法是验证它是否存在"HEAD""FETCH_HEAD"之间的直接路径。

因此,输入条件并听到它说它不是“可更新的直接引用”在我看来似乎是矛盾的。


我的问题是:我错过了什么?我误会了什么?(我知道相当广泛的问题,这就是为什么我提供尽可能多的细节)。

我将非常感谢任何可以帮助我摆脱问题并使其发挥作用的提示。

标签: c++clibgit2

解决方案


今天早上我才意识到我很愚蠢:)

在我的例子中, “HEAD”是对“refs/heads/master”的象征性引用。所以错误通知的是我需要传递直接引用,而不是别名。


推荐阅读