I'm trying to implement a simple checkout operation between 2 branches. The code executes without errors.
git_libgit2_init();
git_object *treeish = NULL;
git_checkout_options opts;
opts.checkout_strategy = GIT_CHECKOUT_SAFE;
/* branchName in this case is "master" */
handleError(git_revparse_single(&treeish, repo, branchName));
handleError(git_checkout_tree(repo, treeish, &opts));
git_object_free(treeish);
git_libgit2_shutdown();
However, the branch does not change when I check it using git status
.
I've checked the 101 examples of libgit2 and it says:
git_checkout_options
isn’t actually very optional. The defaults won’t be useful outside of a small number of cases. The best example of this is checkout_strategy; the default value does nothing to the work tree. So if you want your checkout to check files out, choose an appropriate strategy.
NONE
is the equivalent of a dry run; no files will be checked out.
SAFE
is similar togit checkout
; unmodified files are updated, and modified files are left alone. If a file was present in the old HEAD but is missing, it’s considered deleted, and won’t be created.
RECREATE_MISSING
is similar togit checkout-index
, or what happens after a clone. Unmodified files are updated, and missing files are created, but files with modifications are left alone.
FORCE
is similar togit checkout --force
; all modifications are overwritten, and all missing files are created.
In my case I'm testing it with a very small repo without uncommited changes and without any conflicts between these 2 branches.
What am I doing wrong? I expected this code to do something like git checkout master
The git checkout
command is exceptionally overloaded. It deals with both putting files on disk (checking out) and switching branches. In particular, git checkout <branch>
will update the working directory to match the contents of the given branch and switch to it.
The libgit2 APIs do not conflate these two operations. git_checkout_*
functions will only check files out on disk.
The documentation should clarify this:
In libgit2, checkout is used to update the working directory and index to match a target tree. Unlike git checkout, it does not move the HEAD commit for you - use
git_repository_set_head
or the like to do that.
So what you have written (above) will update the working directory to match the contents of the branch. After that, you will need to update your branch to the branch you want to switch to.
You can do this with git_repository_set_head
to update HEAD
to point to the given branch, once the files have been checked out. Be sure to specify the fully-qualified branch name (eg, refs/heads/master
).
git_object *treeish = NULL;
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
opts.checkout_strategy = GIT_CHECKOUT_SAFE;
git_libgit2_init();
handleError(git_revparse_single(&treeish, repo, "master"));
handleError(git_checkout_tree(repo, treeish, &opts));
handleError(git_repository_set_head(g_repo, "refs/heads/master"));
git_object_free(treeish);
git_libgit2_shutdown();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With