Skip to content

Commit f6a2024

Browse files
committed
libgit2: fix checkout logic for CheckoutBranch
Use the target commit, to checkout tree and set the head to the desired branch instead of doing a hard reset to the target commit. Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
1 parent fe31ff9 commit f6a2024

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

pkg/git/libgit2/checkout.go

+30-5
Original file line numberDiff line numberDiff line change
@@ -161,19 +161,44 @@ func (c *CheckoutBranch) Checkout(ctx context.Context, path, url string, opts *g
161161
}
162162
defer upstreamCommit.Free()
163163

164-
// Once the index has been updated with Fetch, and we know the tip commit,
165-
// a hard reset can be used to align the local worktree with the remote branch's.
166-
err = repo.ResetToCommit(upstreamCommit, git2go.ResetHard, &git2go.CheckoutOptions{
164+
localBranch, err := repo.LookupBranch(c.Branch, git2go.BranchLocal)
165+
if err != nil {
166+
// We ignore the error if the branch is not found since we are going to
167+
// create it ourselves.
168+
if !git2go.IsErrorCode(err, git2go.ErrorCodeNotFound) {
169+
return nil, fmt.Errorf("cannot lookup branch '%s': %w", c.Branch, err)
170+
}
171+
localBranch, err = repo.CreateBranch(c.Branch, upstreamCommit, false)
172+
if err != nil {
173+
return nil, fmt.Errorf("cannot create local branch '%s': %w", c.Branch, err)
174+
}
175+
}
176+
defer localBranch.Free()
177+
178+
tree, err := repo.LookupTree(upstreamCommit.TreeId())
179+
if err != nil {
180+
return nil, fmt.Errorf("cannot lookup tree for branch '%s': %w", c.Branch, err)
181+
}
182+
defer tree.Free()
183+
184+
err = repo.CheckoutTree(tree, &git2go.CheckoutOpts{
185+
// the remote branch should take precedence if it exists at this point in time.
167186
Strategy: git2go.CheckoutForce,
168187
})
169188
if err != nil {
170-
return nil, fmt.Errorf("unable to hard reset to commit for '%s': %w", managed.EffectiveURL(url), gitutil.LibGit2Error(err))
189+
return nil, fmt.Errorf("cannot checkout tree for branch '%s': %w", c.Branch, err)
190+
}
191+
192+
// Set the current head to point to the requested branch.
193+
err = repo.SetHead("refs/heads/" + c.Branch)
194+
if err != nil {
195+
return nil, fmt.Errorf("cannot set HEAD to branch '%s':%w", c.Branch, err)
171196
}
172197

173198
// Use the current worktree's head as reference for the commit to be returned.
174199
head, err := repo.Head()
175200
if err != nil {
176-
return nil, fmt.Errorf("git resolve HEAD error: %w", err)
201+
return nil, fmt.Errorf("cannot resolve HEAD: %w", err)
177202
}
178203
defer head.Free()
179204

0 commit comments

Comments
 (0)