Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to checkout by tag commit id. #959

Closed
alee-r7 opened this issue Dec 9, 2023 · 2 comments · Fixed by #966
Closed

Unable to checkout by tag commit id. #959

alee-r7 opened this issue Dec 9, 2023 · 2 comments · Fixed by #966

Comments

@alee-r7
Copy link

alee-r7 commented Dec 9, 2023

So I'm trying to checkout by the tag commit id. Basically I get the tag, its hash then do a checkout. Like this.

err = w.Checkout(&git.CheckoutOptions{
		Hash: commitHash,
		Force: true,
	})

I've verified the working directory has the commit, even checked objects folder by unpacking the repo I'm working with. I'm also able to checkout using the command line.

I tracked down the issue to this here. Here is the order

  1. Checkout will call Reset which calls ResetSparsely.
  2. ResetSparsely will then call getTreeFromCommitHash.
    t, err := w.r.getTreeFromCommitHash(opts.Commit)
  3. getTreeFromCommitHash will call r.CommitObject which then calls object.GetCommit.
    https://github.com/go-git/go-git/blob/master/repository.go#L1424
  4. GetCommit will then call s.EncodedObject. https://github.com/go-git/go-git/blob/master/plumbing/object/commit.go#L70
  5. This is where it fails. It seems based off the hash, the object that is retrieved from the pack or objects folder is a TabObject. However, it will fail on the last "IF" check because it expects a commit object. Due to the two types be different it returns an error.
func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) {
	var obj plumbing.EncodedObject
	var err error

	if s.index != nil {
		obj, err = s.getFromPackfile(h, false)
		if err == plumbing.ErrObjectNotFound {
			obj, err = s.getFromUnpacked(h)
		}
	} else {
		obj, err = s.getFromUnpacked(h)
		if err == plumbing.ErrObjectNotFound {
			obj, err = s.getFromPackfile(h, false)
		}
	}

	// If the error is still object not found, check if it's a shared object
	// repository.
	if err == plumbing.ErrObjectNotFound {
		dotgits, e := s.dir.Alternates()
		if e == nil {
			// Create a new object storage with the DotGit(s) and check for the
			// required hash object. Skip when not found.
			for _, dg := range dotgits {
				o := NewObjectStorage(dg, s.objectCache)
				enobj, enerr := o.EncodedObject(t, h)
				if enerr != nil {
					continue
				}
				return enobj, nil
			}
		}
	}

	if err != nil {
		return nil, err
	}

	if plumbing.AnyObject != t && obj.Type() != t {
		return nil, plumbing.ErrObjectNotFound
	}

	return obj, nil
}

I'm wondering if this is a bug or if I'm going about the wrong way to checkout by tag.

@alee-r7
Copy link
Author

alee-r7 commented Dec 11, 2023

I've submitted a PR related to this issue.

#964

@AriehSchneier
Copy link
Contributor

AriehSchneier commented Dec 11, 2023

Documentation for Hash in CheckoutOptions:

type CheckoutOptions struct {
	// Hash is the hash of the commit to be checked out. If used, HEAD will be
	// in detached mode. If Create is not used, Branch and Hash are mutually
	// exclusive.
	Hash plumbing.Hash

Is the problem that you are passing a tag hash rather than the commit hash? Would the correct procedure be to get the commit from the tag first and then pass that to CheckoutOptions?

You could call: tag, err := r.TagObject(hash) to get the tag object and then use tag.Hash

aymanbagabas added a commit to aymanbagabas/go-git that referenced this issue Dec 12, 2023
Allow checking out a worktree using a tag hash id.

Fixes: go-git#959
Supersedes: go-git#964
aymanbagabas added a commit to aymanbagabas/go-git that referenced this issue Dec 12, 2023
Allow checking out a worktree using a tag hash id.

Fixes: go-git#959
Supersedes: go-git#964
aymanbagabas added a commit to aymanbagabas/go-git that referenced this issue Dec 12, 2023
Allow checking out a worktree using a tag hash id.

Fixes: go-git#959
Supersedes: go-git#964
aymanbagabas added a commit to aymanbagabas/go-git that referenced this issue Dec 12, 2023
Allow checking out a worktree using a tag hash id.

Fixes: go-git#959
Supersedes: go-git#964
pjbgf added a commit that referenced this issue Dec 14, 2023
git: worktree checkout tag hash id (#959)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants