@@ -161,19 +161,44 @@ func (c *CheckoutBranch) Checkout(ctx context.Context, path, url string, opts *g
161
161
}
162
162
defer upstreamCommit .Free ()
163
163
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.
167
186
Strategy : git2go .CheckoutForce ,
168
187
})
169
188
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 )
171
196
}
172
197
173
198
// Use the current worktree's head as reference for the commit to be returned.
174
199
head , err := repo .Head ()
175
200
if err != nil {
176
- return nil , fmt .Errorf ("git resolve HEAD error : %w" , err )
201
+ return nil , fmt .Errorf ("cannot resolve HEAD: %w" , err )
177
202
}
178
203
defer head .Free ()
179
204
0 commit comments