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

Checkout remote branch to a local (tracked banch) #241

Closed
EugenMayer opened this issue Jan 10, 2021 · 3 comments
Closed

Checkout remote branch to a local (tracked banch) #241

EugenMayer opened this issue Jan 10, 2021 · 3 comments

Comments

@EugenMayer
Copy link

Looked through the issues and seen some similar questions, but iam not sure i found the right one.

If found:

What i want is, i want to checkout a branch i know exists, but it could be, that it is yet not a local branch. Checking out local branches is easy ( so basically rather git switch ) but checking out remote branches seems to not work:

branch not found
  func CheckoutBranch(repository *gitlib.Repository, branchName string) error {
	localBranchLookup, err := repository.Branch(branchName)
	var branchRef plumbing.ReferenceName
	if err != nil {
		fmt.Print("Branch is not yet local, trying to fetch from remote")
		branchRef = plumbing.NewBranchReferenceName(branchName)
	} else {
		branchRef = localBranchLookup.Merge
	}

	worktree, err := repository.Worktree()
	if err != nil {
		return err
	}

	// Keep: true is important for performance reasons, to avoid vendor/github.com/go-git/go-git/v5/worktree.go:409
	// being called by reset, taking 10 seconds and more
	return worktree.Checkout(&gitlib.CheckoutOptions{Branch: branchRef, Keep: true})
}

worktree.Checkout fails with

reference not found

According to the issue i found i changed it to

func CheckoutBranch(repository *gitlib.Repository, branchName string) error {
	//
	//err = fetch(repository)
	//if err != nil {
	//	return err
	//}

	localBranchLookup, err := repository.Branch(branchName)
	if err != nil {
		fmt.Println("Branch is not yet local, trying to fetch from remoteName")
		remoteName := "origin"
		var remoteRef = plumbing.NewRemoteReferenceName(remoteName, branchName)
		var ref, err = repository.Reference(remoteRef, true)
		if err != nil {
			return err
		}

		var mergeRef = plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branchName))
		err = repository.CreateBranch(&config.Branch{Name: branchName, Remote: remoteName, Merge: mergeRef})
		if err != nil {
			return err
		}
		var localRef = plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branchName))
		return repository.Storer.SetReference(plumbing.NewHashReference(localRef, ref.Hash()))
	} else {
		localBranchRef := localBranchLookup.Merge
		worktree, err := repository.Worktree()
		if err != nil {
			return err
		}

		// Keep: true is important for performance reasons, to avoid vendor/github.com/go-git/go-git/v5/worktree.go:409
		// being called by reset, taking 10 seconds and more
		return worktree.Checkout(&gitlib.CheckoutOptions{Branch: localBranchRef, Keep: true})
	}
}

But got the same issue, just it happens at

var ref, err = repository.Reference(remoteRef, true)
if err != nil {
  return err
}

Wit again, reference not found.

What is the right way to do this? I cannot implement fetch due to #240, but if i do a manual git fetch -a on the repo beforehand, it should be the same result. Still it fails with reference not found

Thankful for any help

@dc-wc-2017
Copy link

my code is like this :

repo, err := git.PlainClone(repoDir, false, &git.CloneOptions{
    Auth: &githttp.BasicAuth{
        Username: authenticateUser,
        Password: authenticateToken,
    },
    URL: repoUrl,
})

if err != nil {
    if err != git.ErrRepositoryAlreadyExists {
        mylog.LogFatalExitByCheckingError(err)
    }
    fmt.Printf("Checked error: %v\n", err)
    // open this repository instead
    repo, err = git.PlainOpen(repoDir)
    mylog.LogFatalExitByCheckingError(err)
}

// refs/heads/<localBranchName>
localBranchReferenceName := plumbing.NewBranchReferenceName(branchName)
// refs/remotes/origin/<remoteBranchName>
remoteReferenceName := plumbing.NewRemoteReferenceName("origin", branchName)

err := repo.CreateBranch(&config.Branch{Name: branchName, Remote: "origin", Merge: localBranchReferenceName })
newReference := plumbing.NewSymbolicReference(localBranchReferenceName , remoteReferenceName)
err = repo.Storer.SetReference(newReference)
mylog.LogPanicByCheckingError(err)

@EugenMayer
Copy link
Author

Thank you, this worked! Even though i fall back to checking out the branch on using the cli due to #238 creating a remote tracking branch this way works out fairly well.

@Ileriayo
Copy link

Ileriayo commented Sep 12, 2022

Tried this, and

  1. It moves folders from one branch to the other, howbeit empty. This is not exactly the same effect as git checkout <branch-name> which just switches to a branch and sets it to track from origin (no extra folders).
  2. Setting keep: true on checkout shows un-committed changes (i.e., on checkout to another branch, it shows the files from the other branch as deleted when you do a git status). Is there a way to keep ONLY changes made on local files?

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

No branches or pull requests

3 participants