libgit2 git_checkout_head with GIT_CHECKOUT_SAFE do nothing with working dir

Vad*_*dim 6 c libgit2

I'm trying to do branch switching using libgit2. Repo already cloned and references to existing remote branches created.

If I put GIT_CHECKOUT_FORCE to checkout_strategy, it works as expected - create missing, modify existing, delete removed.

If GIT_CHECKOUT_RECREATE_MISSING - create missing only.

If GIT_CHECKOUT_SAFE - do nothing. Am I missing something?

git_reference_lookup(&branch_ref, repo, ref_name);
git_repository_set_head(repo, git_reference_name(branch_ref));
git_reference_symbolic_create(&head, repo, "HEAD", git_reference_name(branch_ref), 1, NULL);
git_checkout_head(repo, &opts);
Run Code Online (Sandbox Code Playgroud)

I got branches

  • master (current): f1.txt f2.txt
  • new: f1.txt (content differs from master's one)

After GIT_CHECKOUT_SAFE to new:

  • f1.txt (content from master)
  • f2.txt (staged to commit)

Jes*_*sak 2

我认为问题在于您尝试签出 HEAD 时存储库所处的状态。在代码运行之前,您拥有:

on disk  - f1: master's content, f2: master's content
in index - f1: master's content, f2: master's content
in HEAD  - f1: master's content, f2: master's content
Run Code Online (Sandbox Code Playgroud)

更新 HEAD 以指向您的new分支后,您现在拥有:

on disk  - f1: master's content, f2: master's content
in index - f1: master's content, f2: master's content
in HEAD  - f1: new's content,    f2: absent
Run Code Online (Sandbox Code Playgroud)

对于 git 来说,这与您在new分支上对 f1 进行更改并对git add索引进行这些更改没有什么区别。(换句话说,git 会将这些描述为“待提交”。)因此,当您要求它在安全模式下签出 HEAD 内容时,它拒绝丢弃您的更改。

同样,对于 f2,它似乎是新添加的文件,因此安全模式不会删除它。

我通过git_checkout_tree 首先使用使内容与new分支匹配来解决这些问题(因此 libgit2 可以看到内容与 HEAD 匹配,因此可以安全地吹走),然后更新 HEAD 指针。