Git2go - pull&&合并

时间:2015-10-14 10:20:36

标签: git merge git-pull libgit2

我正在尝试实施一些可以让我得到git pullgit fetch && git merge结果的内容。我得到了这个部分工作,但我遇到的问题是,在运行以下代码后,当前的回购仍然认为有本地更改要提交。

据我所知,我相信我可能没有从正确的HEAD创建带注释的提交,或者我需要再次提交? (我不确定)。

我的代码看起来像这样,我被困住了:

func (repo *Repo) Pull() error {
    // Get remote
    remote, err := repo.Remotes.Lookup("origin")
    if err != nil {
        remote, err = repo.Remotes.Create("origin", repo.Path())
        if err != nil {
            return err
        }
    }

    // Get the branch
    branch, err := repo.Branch()
    if err != nil {
        return err
    }

    // Get the name
    branchName, err := branch.Name()
    if err != nil {
        return err
    }

    if err := remote.Fetch([]string{}, &git.FetchOptions{}, ""); err != nil {
        return err
    }

    // Merge
    remoteRef, err := repo.References.Lookup("refs/remotes/origin/" + branchName)
    if err != nil {
        return err
    }

    mergeRemoteHead, err := repo.AnnotatedCommitFromRef(remoteRef)
    if err != nil {
        return err
    }

    mergeHeads := make([]*git.AnnotatedCommit, 1)
    mergeHeads[0] = mergeRemoteHead
    if err = repo.Merge(mergeHeads, nil, nil); err != nil {
        return err
    }

    return nil
}

运行之后,我从远程合并更新了工作目录,但它告诉我需要进行提交。

我认为我的问题与this question的OP类似。

2 个答案:

答案 0 :(得分:7)

这就是libgit2 git_merge功能的记录方式:

  

任何更改都会进行提交,并且任何冲突都会写入索引。调用者应在完成后检查存储库的索引,解决所有冲突并准备提交。

所以你必须添加代码来检查是否index has conflicts。如果没有,您可以commit上演的内容。否则,您可能希望提示用户解决冲突。

答案 1 :(得分:4)

使用上面TotalCost的答案中的输入,我能够整合这个功能的工作版本,我想我会分享这个突破。正如所指出的,libgit2中的sschuberth函数(在本例中为Git2go)与repo.Merge()的函数差不多。让我一步一步解释(我的立场已经纠正):

正如here所述,git pull实际上是git pull,然后是git fetch,这就是我们要做的事情:

找到遥控器以从

中检索更改
git merge

从远程

获取更改
remote, err := repo.Remotes.Lookup("origin")
if err != nil {
    return err
}

获取相应的远程参考

if err := remote.Fetch([]string{}, nil, ""); err != nil {
    return err
}

您现在可以从遥控器进行更改但是您需要让Git告诉您如何进一步处理它们。所以,做一个合并分析。

执行合并分析

remoteBranch, err := repo.References.Lookup("refs/remotes/origin/branch_name")
if err != nil {
    return err
}

现在,您需要检查annotatedCommit, err := repo.AnnotatedCommitFromRef(remoteBranch) if err != nil { return err } // Do the merge analysis mergeHeads := make([]*git.AnnotatedCommit, 1) mergeHeads[0] = annotatedCommit analysis, _, err := repo.MergeAnalysis(mergeHeads) if err != nil { return err } 的值,以查看它指向哪个status value并相应地进行合并。

测试返回值

确保在二进制级别上进行测试,因此请使用按位运算符。例如:

analysis

这里没什么可做的(在我的情况下)。一切都是最新的。

if analysis & git.MergeAnalysisUpToDate != 0 {
    return nil
}

简而言之,上面的代码块只是执行合并并测试之后的冲突。如果遇到任何冲突,请处理它们(也许提示用户)。这将导致未提交的更改,因此请务必在之后创建提交。

else if analysis & git.MergeAnalysisNormal != 0 {
    // Just merge changes
    if err := repo.Merge([]*git.AnnotatedCommit{annotatedCommit}, nil, nil); err != nil {
        return err
    }
    // Check for conflicts
    index, err := repo.Index()
    if err != nil {
        return err
    }

    if index.HasConflicts() {
        return errors.New("Conflicts encountered. Please resolve them.")
    }

    // Make the merge commit
    sig, err := repo.DefaultSignature()
    if err != nil {
        return err
    }

    // Get Write Tree
    treeId, err := index.WriteTree()
    if err != nil {
        return err
    }

    tree, err := repo.LookupTree(treeId)
    if err != nil {
        return err
    }

    localCommit, err := repo.LookupCommit(head.Target())
    if err != nil {
        return err
    }

    remoteCommit, err := repo.LookupCommit(remoteBranchID)
    if err != nil {
        return err
    }

    repo.CreateCommit("HEAD", sig, sig, "", tree, localCommit, remoteCommit)

    // Clean up
    repo.StateCleanup()
}

在上面的代码中,没有任何要合并的内容。您只需要将远程更改重播到本地并更新HEAD指向的位置。

以上对我来说已经足够了。我希望这种方法对你有帮助。在this gist

上找到完整的功能