libgit2使用教程(九)git fetch & pull

目前 libgit2 对 pull 操作的支持还不是太好,所以目前能找到的资料都指出 pull 操作就是先 fetch 然后再 merge 目标分支。比如要实现 git pull origin master ,就先 fetch 然后将 master 切换到 head 再将 origin master 合并到 head。

那么就先 fetch

git_remote_fetch 这个接口的后三个参数都是可以传 null 的,但是如果报了下面这个错:
authentication required but no callback set
说明远端地址需要验证身份,所以我们要设置 ssh 证书的回调。

这样就完成了 fetch 操作。so easy

prune 也是 fetch 操作的一个重要参数。表示:清理掉远端已经删除的分支对应的本地分支,有点绕,不过应该还好理解吧。具体信息可以查一下下面这个命令。
git fetch -p (或 git fetch –prune)
在代码里实现只需要在 option 参数里做一个设置:

这样就强制使用 prune 参数了。另外几个可选枚举值可以去读注释。

接下来为了实现类似 pull 的效果,就是蛋疼的合并操作了,顺便可以复习一下之前的内容。
首先将本地 master 设为 head

然后去拿 origin master 的 commit

合并

解决冲突

add 和 commit

清空状态

打完收工。

示例代码:sample9

《libgit2使用教程(九)git fetch & pull》有8个想法

  1. 博主好。我尝试libgit2 merge失败了,参考了你sample9里的代码。git_remote_fetch以后FETCH_HEAD文件更新成功的,.git\refs\remotes\origin\master文件里的commit id和FETCH_HEAD里的一致,.git\refs\heads\master里的和前面两个不同。那我猜测是后面add and commit时几个write函数出错了,我加了出错打印,发现函数调用都是成功的,不知道哪里出了差错,请指教啊。

    1. 感谢,我之前确实忽略掉了这个问题。之所以会多出一个 oid ,是生成的新 commit 。如果需要不生成新的 commit ,只要把远端的更新拉到本地,有一个方法:
      const char *refs[] = {“refs/heads/master:refs/heads/master”};
      git_strarray refspecs = {(char**)refs, 1};

      git_remote_fetch(remote, &refspecs, &fetch_opts, nullptr);
      在 fetch 的时候传入 refspecs 。 本地分支可以直接同步成远端分支,只不过所有改动会在暂存区保留一份,需要手动 reset 掉。
      如果是在本地分支有修改的情况下,行为就不对了。
      如果找到了更好的方法也希望可以分享一下。

      1. 我目前是只需要把远端的分支覆盖的本地就好了,参照你说的方法成功了,谢谢。

        如果本地也修改了,把本地的commit id 和 远端的commit id合并生成一个新的commit id,
        然后再reset是不是能同时保留本地和远端的修改呢(在不发生冲突的条件下)?

        1. 如果有修改,我觉得还是用 merge 的方式,新建 commit 会好一些。就是文章里写的这种方法。 git_status_list 在 reset 之前能取到吧?可以考虑先取数据再 reset。 另外获取文件改动信息可以通过 diff 的方式 比对两个 commit id 对应的 tree 。

          1. 用你文章里介绍的merge方法,我想把远端分支的内容更新到本地,没有成功。

            现象就是git_remote_fetch以后FETCH_HEAD文件更新成功,然而本地分支并没有被更新,我不知道问题出在哪儿了。代码的话基本上和你sample9里的一致,郁闷中。。。请指教。

          2. git_merge 合并的结果是 stage 的,相当于 add 之后的结果,需要新建 commit 才能加入到版本库中。不过如果一 commit 就会出现你第一个回复的问题,新添一个新的 commit id。

      2. 我把远端分支同步到本地以后,还想通过git_status_list_entrycount知道哪些文件被修改过了,
        但是发现reset以后,git_status_list_entrycount返回值为0。

        通过git_remote_fetch得到commit id以后,有其他方法既能把远端分支同步到本地又能获取相应的git_status_list_entrycount吗?

发表评论

电子邮件地址不会被公开。