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>")
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 <branch>` defaulting to `git checkout -b <branch> --track <remote>/<branch>`")
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
}