简体   繁体   中英

git2go's CheckoutHead() not updating the index

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:

git init .
git add remote origin 'https://domain/repo.git'
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:

# (init repo, add the 'origin' remote and fetch it...)
repo.SetHead("refs/remotes/origin/master")
repo.CheckoutHead(&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).

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:

repo.SetHead("refs/remotes/origin/master")
# get the index and the HEAD tree...
index.ReadTree(headTree)
index.Write()
repo.CheckoutHead(&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.

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, &git.CheckoutOpts{Strategy: git.CheckoutSafe})
_, err = repo.References.Create("refs/heads/master", commitId, true, "master")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM