func NewReferenceFromStrings(name, target string) *Reference {
	n := ReferenceName(name)
	if strings.HasPrefix(target, symrefPrefix) {
		target := ReferenceName(target[len(symrefPrefix):])
		return NewSymbolicReference(n, target)
	}
	return NewHashReference(n, NewHash(target))
}
NewReferenceFromStrings creates a reference from name and target as string,
the resulting reference can be a SymbolicReference or a HashReference base
on the target provided
package plumbing
import (
	"errors"
	"fmt"
	"strings"
)
const (
	refPrefix       = "refs/"
	refHeadPrefix   = refPrefix + "heads/"
	refTagPrefix    = refPrefix + "tags/"
	refRemotePrefix = refPrefix + "remotes/"
	refNotePrefix   = refPrefix + "notes/"
	symrefPrefix    = "ref: "
)
var RefRevParseRules = []string{
	"refs/%s",
	"refs/tags/%s",
	"refs/heads/%s",
	"refs/remotes/%s",
	"refs/remotes/%s/HEAD",
}
var (
	ErrReferenceNotFound = errors.New("reference not found")
)
type ReferenceType int8
const (
	InvalidReference  ReferenceType = 0
	HashReference     ReferenceType = 1
	SymbolicReference ReferenceType = 2
)
func (r ReferenceType) String() string {
	switch r {
	case InvalidReference:
		return "invalid-reference"
	case HashReference:
		return "hash-reference"
	case SymbolicReference:
		return "symbolic-reference"
	}
	return ""
}
type ReferenceName string
func NewBranchReferenceName(name string) ReferenceName {
	return ReferenceName(refHeadPrefix + name)
}
func NewNoteReferenceName(name string) ReferenceName {
	return ReferenceName(refNotePrefix + name)
}
func NewRemoteReferenceName(remote, name string) ReferenceName {
	return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, name))
}
func NewRemoteHEADReferenceName(remote string) ReferenceName {
	return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, HEAD))
}
func NewTagReferenceName(name string) ReferenceName {
	return ReferenceName(refTagPrefix + name)
}
func (r ReferenceName) IsBranch() bool {
	return strings.HasPrefix(string(r), refHeadPrefix)
}
func (r ReferenceName) IsNote() bool {
	return strings.HasPrefix(string(r), refNotePrefix)
}
func (r ReferenceName) IsRemote() bool {
	return strings.HasPrefix(string(r), refRemotePrefix)
}
func (r ReferenceName) IsTag() bool {
	return strings.HasPrefix(string(r), refTagPrefix)
}
func (r ReferenceName) String() string {
	return string(r)
}
func (r ReferenceName) Short() string {
	s := string(r)
	res := s
	for _, format := range RefRevParseRules {
		_, err := fmt.Sscanf(s, format, &res)
		if err == nil {
			continue
		}
	}
	return res
}
const (
	HEAD   ReferenceName = "HEAD"
	Master ReferenceName = "refs/heads/master"
)
type Reference struct {
	t      ReferenceType
	n      ReferenceName
	h      Hash
	target ReferenceName
}