gitoxide icon indicating copy to clipboard operation
gitoxide copied to clipboard

checkout of a specific branch, tag or revision does not work

Open sassman opened this issue 8 months ago • 3 comments

Current behavior 😯

In https://github.com/cargo-generate/cargo-generate/pull/1460 we try to get away from git2 and migrate to gix. It looks all promising so far, only one thing does not work. It is checking out a specific branch, tag or revision.

What gix does, (see the code https://github.com/cargo-generate/cargo-generate/pull/1460/files#diff-dbcccd0cf247f619f177ddeb85fe8dfc4eb4c71c0de0bb47ec839764c7d4918dR82) it checks out the default branch (in our test case it is main).

Expected behavior 🤔

when we configure the prepare_clone with the refsepc like in https://github.com/cargo-generate/cargo-generate/pull/1460/files#diff-dbcccd0cf247f619f177ddeb85fe8dfc4eb4c71c0de0bb47ec839764c7d4918dR72

or here the excerpt:

        let (mut prepare_checkout, _) = if let Some(branch) = self.branch {
            let mut opts = Options::default();
            let ref_spec = gix::refspec::parse(branch.as_str().into(), Operation::Fetch).unwrap();
            dbg!(ref_spec);
            opts.extra_refspecs.push(ref_spec.to_owned());

            prepare_clone.with_fetch_options(opts)

Then I would expect that calling

        let (repo, _) = prepare_checkout
            .main_worktree(gix::progress::Discard, &gix::interrupt::IS_INTERRUPTED)?;

would check out the specific branch, tag or revision.

Git behavior

git2 has a .checkout_tree that does behave exactly as described above

here is some sample code: https://github.com/cargo-generate/cargo-generate/blob/0e9471d4991764270de8940c7695d13f932c086b/src/git/clone_tool.rs#L183

Steps to reproduce 🕹

  1. in cargo-generate you can checkout the PR #1460 (gh pr checkout 1460)
  2. let the tests run simply cargo test
  3. all failing tests (2) relate to this problem
  gix::tests::test_cloning_a_repo_at_revision
  gix::tests::test_cloning_a_repo_with_a_specific_branch

sassman avatar Apr 05 '25 11:04 sassman

Thanks for reporting.

gitoxide doesn't have a way to checkout a branch yet akin to git2_repo.checkout_*(), and the choice of ref to checkout after cloning is definitely specified differently.

gix clone --ref <name> … is able to clone and checkout a specific branch. I recommend looking at the source to see how this is specified - it should work for you.

Please do feel free to post your findings here, maybe they are useful for others as well.

Byron avatar Apr 05 '25 12:04 Byron

I'm migrating a project from go to rust which is supposed to fetch and checkout a single commit sha for a CI build.

Originally, I thought it would work after seeing https://github.com/GitoxideLabs/gitoxide/pull/1403, but I ran into this error

we map by name only and have no object-id in refspec

For now I'll continue to use the go code (example go usage and resolved issue), but looking forward to revisit this and migrate to Rust! 🦀

osoriano avatar Jun 08 '25 04:06 osoriano

It looks like this can easily be reproduced by providing an object hash as reference:

> gix clone --ref 4b7008c929494c7764f3ddffa998ca0c8cab9806 https://github.com/Byron/small

thread 'main' panicked at gix/src/clone/fetch/util.rs:217:18:
we map by name only and have no object-id in refspec
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

It looks like this should be prevented to not run into this assertion, or one could try to actually make this work. Then it feels like --ref should be renamed to something that more officially allows object hashes (both in the CLI and in the API).

Byron avatar Jun 09 '25 12:06 Byron