package main import ( "fmt" "os" "github.com/go-git/go-git/v5" . "github.com/go-git/go-git/v5/_examples" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" ) // Checkout a branch func main() { CheckArgs("", "", "") url, directory, branch := os.Args[1], os.Args[2], os.Args[3] // Clone the given repository to the given directory Info("git clone %s %s", url, directory) r, err := git.PlainClone(directory, false, &git.CloneOptions{ URL: url, }) CheckIfError(err) // ... retrieving the commit being pointed by HEAD Info("git show-ref --head HEAD") ref, err := r.Head() CheckIfError(err) fmt.Println(ref.Hash()) w, err := r.Worktree() CheckIfError(err) // ... checking out branch Info("git checkout %s", branch) branchRefName := plumbing.NewBranchReferenceName(branch) branchCoOpts := git.CheckoutOptions{ Branch: plumbing.ReferenceName(branchRefName), Force: true, } if err := w.Checkout(&branchCoOpts); err != nil { Warning("local checkout of branch '%s' failed, will attempt to fetch remote branch of same name.", branch) Warning("like `git checkout ` defaulting to `git checkout -b --track /`") mirrorRemoteBranchRefSpec := fmt.Sprintf("refs/heads/%s:refs/heads/%s", branch, branch) err = fetchOrigin(r, mirrorRemoteBranchRefSpec) CheckIfError(err) err = w.Checkout(&branchCoOpts) CheckIfError(err) } CheckIfError(err) Info("checked out branch: %s", branch) // ... retrieving the commit being pointed by HEAD (branch now) Info("git show-ref --head HEAD") ref, err = r.Head() CheckIfError(err) fmt.Println(ref.Hash()) } func fetchOrigin(repo *git.Repository, refSpecStr string) error { remote, err := repo.Remote("origin") CheckIfError(err) var refSpecs []config.RefSpec if refSpecStr != "" { refSpecs = []config.RefSpec{config.RefSpec(refSpecStr)} } if err = remote.Fetch(&git.FetchOptions{ RefSpecs: refSpecs, }); err != nil { if err == git.NoErrAlreadyUpToDate { fmt.Print("refs already up to date") } else { return fmt.Errorf("fetch origin failed: %v", err) } } return nil }