git2go的CheckoutHead()没有更新索引。

huangapple go评论109阅读模式
英文:

git2go's CheckoutHead() not updating the index

问题

我正在尝试在现有目录上初始化一个仓库,添加一个远程仓库,并强制检出远程仓库的主分支覆盖现有文件。相应的命令行命令如下:

git init .
git remote add origin 'https://domain/repo.git'
git fetch
git checkout -f origin/master

一切都正常工作,但是检出后索引似乎没有发生变化。相关的代码如下:

//(初始化仓库,添加 'origin' 远程仓库并获取它...)
repo.SetHead("refs/remotes/origin/master")
repo.CheckoutHead(&git.CheckoutOpts{Strategy: git.CheckoutForce})

当我运行 git status 时,我看到相同的文件在索引中被标记为已删除(D),同时也被标记为未跟踪(是的,同一个文件同时出现在这两个状态),而工作目录中包含了正确的文件。由于看起来索引没有从内存中写入磁盘,或者存在一些奇怪的缓存问题,我尝试在检出后运行 index.Write(),但是没有任何变化。

如果我在仓库中运行 git reset HEAD,然后运行 git status,就会返回一个干净的状态,因为索引会更新为当前的 HEAD 树,并且现在反映了工作目录的状态。

更新

我注意到,只有当现有目录中的文件与源仓库中的文件相同时(文件模式不重要),才会出现这种情况。在这种情况下,这些文件会被标记为已删除(D)和未跟踪(??)。

当文件存在但内容不同时,就不会出现这种情况。在这种情况下,文件会正确地被标记为已修改(M)。

英文:

I'm trying to initialize a repository over an existing directory, add a remote and force checkout the remote's master branch over the existing files. The cli commands for this would be:

<!-- language: sh -->

git init .
git add remote origin &#39;https://domain/repo.git&#39;
git fetch
git checkout -f origin/master

Everything works fine but the index doesn't appear to change after the checkout. The relevant code is:

<!-- language: go -->

# (init repo, add the &#39;origin&#39; remote and fetch it...)
repo.SetHead(&quot;refs/remotes/origin/master&quot;)
repo.CheckoutHead(&amp;git.CheckoutOpts{Strategy: git.CheckoutForce})

When I do a git status, I see the same files appearing as deleted (D) in the index and also as untracked (yes, the same file appears as both), while the workdir does contain the correct files. Since this looks like the index wasn't written to disk from memory, or has some weird cache, I also tried index.Write() after the checkout but that didn't make any change.

If I run git reset HEAD in the repo, then git status returns a clean state, since the index gets updated to the current HEAD tree and it now reflects the workdir.

Update

I noticed this only happens when the files in the existing directory are the same as in the origin repo (file mode isn't important). In this case those files appear as deleted (D) and untracked (??).

It doesn't happen when the file exists but has a different content. In this case the file correctly appears as modified (M).

答案1

得分: 1

我通过将树读入索引并在检出之前将索引写入磁盘来解决了这个问题。代码大致如下:

repo.SetHead("refs/remotes/origin/master")
# 获取索引和HEAD树...
index.ReadTree(headTree)
index.Write()
repo.CheckoutHead(&git.CheckoutOpts{Strategy: git.CheckoutForce})

这似乎具有与运行git checkout -f origin/master相同的效果。但我不知道为什么ReadTree()是必需的,因为根据文档,CheckoutHead() 应该更新索引和工作树:

git_checkout_head
更新索引和工作树中的文件,使其与HEAD指向的提交内容相匹配。

我最好的猜测是,检出操作之所以无法正常工作,是因为索引最初指向一个空树。但我不确定这是否是libgit2的一个错误。

英文:

I managed to solve it by reading the tree into the index and writing the index to disk before the checkout. The code looks something like this:

<!-- language: go -->

repo.SetHead(&quot;refs/remotes/origin/master&quot;)
# get the index and the HEAD tree...
index.ReadTree(headTree)
index.Write()
repo.CheckoutHead(&amp;git.CheckoutOpts{Strategy: git.CheckoutForce})

This appears to have the same effect as running git checkout -f origin/master. But I don't know why the ReadTree() is necessary, since CheckoutHead() should update the index and the working tree, per the docs:

> git_checkout_head
> Updates files in the index and the working tree to match the content of the commit pointed at by HEAD.

My best guess is that the checkout doesn't work correctly because the index points to an empty tree initially. However I'm not sure if it's a libgit2 bug or not.

答案2

得分: 1

在检查之前不要更新HEAD,否则你的工作目录将变得脏乱,检出操作可能无法继续进行。相反,先检出你想要的内容,然后如果检出成功,再更新HEAD

类似这样的代码:

target, err := repo.LookupCommit(newHeadId)
repo.CheckoutTree(target, &git.CheckoutOpts{Strategy: git.CheckoutSafe})
_, err = repo.References.Create("refs/heads/master", commitId, true, "master")
英文:

Don't update HEAD before checking our or your working directory will be dirty and checkout will (likely) not be able to proceed. Instead checkout to what you want, and then update HEAD if checkout succeeds:

Something like:

target, err := repo.LookupCommit(newHeadId)
repo.CheckoutTree(target, &amp;git.CheckoutOpts{Strategy: git.CheckoutSafe})
_, err = repo.References.Create(&quot;refs/heads/master&quot;, commitId, true, &quot;master&quot;)

huangapple
  • 本文由 发表于 2016年1月5日 04:14:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/34599073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定