This document covers repository configuration management in go-git, including remotes, branches, and Git config files.
go-git supports full Git configuration management:
type Config struct {
Core CoreConfig
User User
Author Author
Committer Committer
Pack PackConfig
Init InitConfig
Extensions Extensions
Remotes map[string]*RemoteConfig
Submodules map[string]*Submodule
Branches map[string]*Branch
URLs map[string]*URL
Raw *format.Config
}
func NewConfig() *Config
func ReadConfig(r io.Reader) (*Config, error)
func LoadConfig(scope Scope) (*Config, error)
func (c *Config) Validate() error
func (c *Config) Unmarshal(data []byte) error
func (c *Config) Marshal() ([]byte, error)type Scope int
const (
LocalScope Scope = iota // Repository-local (.git/config)
GlobalScope // User global (~/.gitconfig)
SystemScope // System-wide (/etc/gitconfig)
)
func Paths(scope Scope) ([]string, error)type CoreConfig struct {
IsBare bool
Worktree string
CommentChar string
RepositoryFormatVersion string
}Example:
package main
import (
"fmt"
"github.com/go-git/go-git/v5"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
cfg, err := r.Config()
if err != nil {
panic(err)
}
fmt.Println("Bare:", cfg.Core.IsBare)
fmt.Println("Worktree:", cfg.Core.Worktree)
}type User struct {
Name string
Email string
}Example:
package main
import (
"fmt"
"github.com/go-git/go-git/v5"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
cfg, _ := r.Config()
// Set user
cfg.User.Name = "John Doe"
cfg.User.Email = "john@example.com"
err := r.SetConfig(cfg)
if err != nil {
panic(err)
}
fmt.Println("User configured")
}type RemoteConfig struct {
Name string
URLs []string
Mirror bool
Fetch []RefSpec
}
func (c *RemoteConfig) Validate() error
func (c *RemoteConfig) IsFirstURLLocal() bool
func (c *RemoteConfig) Marshal() ([]byte, error)
func (c *RemoteConfig) Unmarshal(data []byte) errorExample:
package main
import (
"fmt"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
cfg, _ := r.Config()
// Add remote
cfg.Remotes["upstream"] = &config.RemoteConfig{
Name: "upstream",
URLs: []string{"https://github.com/upstream/repo"},
Fetch: []config.RefSpec{
"+refs/heads/*:refs/remotes/upstream/*",
},
}
err := r.SetConfig(cfg)
if err != nil {
panic(err)
}
fmt.Println("Remote added")
}type Branch struct {
Name string
Remote string
Merge plumbing.ReferenceName
Rebase string
Description string
}
func (b *Branch) Validate() error
func (b *Branch) Marshal() ([]byte, error)
func (b *Branch) Unmarshal(data []byte) errorExample:
package main
import (
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
// Configure branch tracking
err := r.CreateBranch(&config.Branch{
Name: "feature",
Remote: "origin",
Merge: plumbing.NewBranchReferenceName("feature"),
})
if err != nil {
panic(err)
}
}type RefSpec string
func (r RefSpec) Validate() error
func (r RefSpec) IsForceUpdate() bool
func (r RefSpec) IsDelete() bool
func (r RefSpec) IsExactSHA1() bool
func (r RefSpec) IsWildcard() bool
func (r RefSpec) Src() string
func (r RefSpec) Dst(src plumbing.ReferenceName) plumbing.ReferenceName
func (r RefSpec) Match(name plumbing.ReferenceName) bool
func (r RefSpec) Reverse() RefSpec
func (r RefSpec) String() stringConstants:
const (
DefaultFetchRefSpec = "+refs/heads/*:refs/remotes/%s/*"
DefaultPushRefSpec = "refs/heads/*:refs/heads/*"
)Example:
package main
import (
"fmt"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
)
func main() {
// Parse refspec
refSpec := config.RefSpec("+refs/heads/*:refs/remotes/origin/*")
fmt.Println("Force:", refSpec.IsForceUpdate())
fmt.Println("Wildcard:", refSpec.IsWildcard())
fmt.Println("Source:", refSpec.Src())
// Check if matches
ref := plumbing.NewBranchReferenceName("main")
if refSpec.Match(ref) {
dst := refSpec.Dst(ref)
fmt.Println("Maps to:", dst)
}
}type Submodule struct {
Name string
Path string
URL string
Branch string
}
func (s *Submodule) Validate() error
func (s *Submodule) Marshal() ([]byte, error)
func (s *Submodule) Unmarshal(data []byte) errorExample:
package main
import (
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
cfg, _ := r.Config()
// Add submodule
cfg.Submodules["lib"] = &config.Submodule{
Name: "lib",
Path: "lib",
URL: "https://github.com/user/lib",
Branch: "main",
}
r.SetConfig(cfg)
}type URL struct {
Name string
InsteadOf string
PushInsteadOf string
}
func (u *URL) Validate() error
func (u *URL) Apply(url string) stringExample:
package main
import (
"fmt"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
cfg, _ := r.Config()
// Add URL rewrite rule
cfg.URLs["github"] = &config.URL{
Name: "github",
InsteadOf: "https://github.com/",
}
r.SetConfig(cfg)
// Apply rewrite
url := cfg.URLs["github"].Apply("gh:user/repo")
fmt.Println(url) // https://github.com/user/repo
}func (r *Repository) Config() (*config.Config, error)
func (r *Repository) ConfigScoped(scope config.Scope) (*config.Config, error)Example:
package main
import (
"fmt"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
// Get local config
localCfg, _ := r.Config()
fmt.Println("User:", localCfg.User.Name)
// Get global config
globalCfg, _ := r.ConfigScoped(config.GlobalScope)
fmt.Println("Global user:", globalCfg.User.Name)
}func (r *Repository) SetConfig(cfg *config.Config) errorExample:
package main
import (
"github.com/go-git/go-git/v5"
)
func main() {
r, _ := git.PlainOpen("/tmp/repo")
cfg, _ := r.Config()
// Modify configuration
cfg.User.Name = "Jane Doe"
cfg.User.Email = "jane@example.com"
// Save configuration
err := r.SetConfig(cfg)
if err != nil {
panic(err)
}
}var (
ErrInvalid = errors.New("invalid configuration")
ErrRemoteConfigNotFound = errors.New("remote config not found")
ErrRemoteConfigEmptyURL = errors.New("remote URL is empty")
ErrRemoteConfigEmptyName = errors.New("remote name is empty")
ErrModuleEmptyURL = errors.New("submodule URL is empty")
ErrModuleEmptyPath = errors.New("submodule path is empty")
ErrModuleBadPath = errors.New("submodule path is invalid")
ErrRefSpecMalformed = errors.New("refspec is malformed")
)