or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

config.mdindex.mdobjects.mdplumbing.mdreferences.mdremote-operations.mdrepository-operations.mdstorage.mdtransport.mdworktree-operations.md
tile.json

remote-operations.mddocs/

Remote Operations

This document covers all operations for interacting with remote repositories, including fetching, pushing, pulling, and authentication.

Overview

go-git provides comprehensive support for remote repository operations:

  • Fetch changes from remotes
  • Push commits to remotes
  • Pull and merge remote changes
  • List remote references
  • Manage remote configuration
  • Multiple authentication methods (HTTP, SSH, tokens)

Remote Type

type Remote struct {
    // contains filtered or unexported fields
}

func (r *Remote) Config() *config.RemoteConfig
func (r *Remote) Push(o *PushOptions) error
func (r *Remote) PushContext(ctx context.Context, o *PushOptions) error
func (r *Remote) Fetch(o *FetchOptions) error
func (r *Remote) FetchContext(ctx context.Context, o *FetchOptions) error
func (r *Remote) List(o *ListOptions) ([]*plumbing.Reference, error)
func (r *Remote) String() string

Getting Remotes

Get Single Remote

func (r *Repository) Remote(name string) (*Remote, error)

Example:

package main

import (
    "fmt"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Get origin remote
    remote, err := r.Remote("origin")
    if err != nil {
        panic(err)
    }

    fmt.Println("Remote name:", remote.Config().Name)
    fmt.Println("URLs:", remote.Config().URLs)
}

List All Remotes

func (r *Repository) Remotes() ([]*Remote, error)

Example:

package main

import (
    "fmt"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // List all remotes
    remotes, err := r.Remotes()
    if err != nil {
        panic(err)
    }

    for _, remote := range remotes {
        fmt.Printf("%s: %v\n", remote.Config().Name, remote.Config().URLs)
    }
}

Managing Remotes

Create Remote

func (r *Repository) CreateRemote(c *config.RemoteConfig) (*Remote, error)

Example:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/config"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Create new remote
    remote, err := r.CreateRemote(&config.RemoteConfig{
        Name: "upstream",
        URLs: []string{"https://github.com/upstream/repo"},
    })
    if err != nil {
        panic(err)
    }

    println("Created remote:", remote.Config().Name)
}

Delete Remote

func (r *Repository) DeleteRemote(name string) error

Example:

package main

import (
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Delete remote
    err = r.DeleteRemote("old-remote")
    if err != nil {
        panic(err)
    }
}

Fetch Operations

Fetch from Repository

func (r *Repository) Fetch(o *FetchOptions) error
func (r *Repository) FetchContext(ctx context.Context, o *FetchOptions) error

Example:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Fetch from default remote
    err = r.Fetch(&git.FetchOptions{
        RemoteName: "origin",
        Progress:   os.Stdout,
    })
    if err != nil && err != git.NoErrAlreadyUpToDate {
        panic(err)
    }

    if err == git.NoErrAlreadyUpToDate {
        println("Already up to date")
    }
}

Fetch from Remote Object

func (remote *Remote) Fetch(o *FetchOptions) error
func (remote *Remote) FetchContext(ctx context.Context, o *FetchOptions) error

Example:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    remote, err := r.Remote("origin")
    if err != nil {
        panic(err)
    }

    // Fetch from specific remote
    err = remote.Fetch(&git.FetchOptions{
        Progress: os.Stdout,
    })
    if err != nil && err != git.NoErrAlreadyUpToDate {
        panic(err)
    }
}

FetchOptions

type FetchOptions struct {
    RemoteName      string
    RemoteURL       string
    RefSpecs        []config.RefSpec
    Depth           int
    Auth            transport.AuthMethod
    Progress        sideband.Progress
    Tags            TagMode
    Force           bool
    InsecureSkipTLS bool
    ClientCert      []byte
    ClientKey       []byte
    CABundle        []byte
    ProxyOptions    transport.ProxyOptions
    Prune           bool
}

Key Fields:

  • RemoteName - Name of remote to fetch from (default: "origin")
  • RemoteURL - Override remote URL
  • RefSpecs - Specific refspecs to fetch
  • Depth - Shallow fetch depth (0 for full history)
  • Auth - Authentication method
  • Progress - Progress output writer
  • Tags - Tag fetching mode
  • Force - Force fetch (update local refs)
  • Prune - Remove deleted remote branches

Example with Options:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/config"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    err = r.Fetch(&git.FetchOptions{
        RemoteName: "origin",
        RefSpecs: []config.RefSpec{
            config.RefSpec("+refs/heads/main:refs/remotes/origin/main"),
        },
        Depth: 50,
        Auth: &http.BasicAuth{
            Username: "user",
            Password: "token",
        },
        Progress: os.Stdout,
        Prune:    true,
        Tags:     git.AllTags,
    })
    if err != nil && err != git.NoErrAlreadyUpToDate {
        panic(err)
    }
}

Push Operations

Push from Repository

func (r *Repository) Push(o *PushOptions) error
func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error

Example:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Push to default remote
    err = r.Push(&git.PushOptions{
        RemoteName: "origin",
        Progress:   os.Stdout,
    })
    if err != nil {
        panic(err)
    }
}

Push from Remote Object

func (remote *Remote) Push(o *PushOptions) error
func (remote *Remote) PushContext(ctx context.Context, o *PushOptions) error

Example:

package main

import (
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    remote, err := r.Remote("origin")
    if err != nil {
        panic(err)
    }

    // Push to specific remote
    err = remote.Push(&git.PushOptions{})
    if err != nil {
        panic(err)
    }
}

PushOptions

type PushOptions struct {
    RemoteName       string
    RemoteURL        string
    RefSpecs         []config.RefSpec
    Auth             transport.AuthMethod
    Progress         sideband.Progress
    Prune            bool
    Force            bool
    InsecureSkipTLS  bool
    ClientCert       []byte
    ClientKey        []byte
    CABundle         []byte
    RequireRemoteRefs []config.RefSpec
    FollowTags       bool
    ForceWithLease   *ForceWithLease
    Options          map[string]string
    Atomic           bool
    ProxyOptions     transport.ProxyOptions
}

Key Fields:

  • RemoteName - Name of remote to push to
  • RemoteURL - Override remote URL
  • RefSpecs - Specific refspecs to push
  • Auth - Authentication method
  • Progress - Progress output writer
  • Force - Force push (overwrite remote refs)
  • Prune - Delete remote refs
  • FollowTags - Push annotated tags
  • ForceWithLease - Safe force push
  • Atomic - Atomic push (all or nothing)
  • Options - Push options (server-specific)

Example - Push Specific Branch:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/config"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Push specific branch
    err = r.Push(&git.PushOptions{
        RemoteName: "origin",
        RefSpecs: []config.RefSpec{
            config.RefSpec("refs/heads/feature:refs/heads/feature"),
        },
    })
    if err != nil {
        panic(err)
    }
}

Example - Force Push (Carefully!):

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/config"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Force push - USE WITH CAUTION
    err = r.Push(&git.PushOptions{
        RemoteName: "origin",
        RefSpecs: []config.RefSpec{
            config.RefSpec("+refs/heads/branch:refs/heads/branch"),
        },
        Force: true,
    })
    if err != nil {
        panic(err)
    }
}

Example - Force with Lease (Safe Force Push):

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Get current remote branch state
    ref, err := r.Reference(plumbing.ReferenceName("refs/remotes/origin/main"), true)
    if err != nil {
        panic(err)
    }

    // Force push with lease - only succeeds if remote hasn't changed
    err = r.Push(&git.PushOptions{
        RemoteName: "origin",
        ForceWithLease: &git.ForceWithLease{
            RefName: plumbing.ReferenceName("refs/heads/main"),
            Hash:    ref.Hash(),
        },
    })
    if err != nil {
        panic(err)
    }
}

Example - Atomic Push:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/config"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    // Atomic push - all refs succeed or all fail
    err = r.Push(&git.PushOptions{
        RemoteName: "origin",
        RefSpecs: []config.RefSpec{
            config.RefSpec("refs/heads/main:refs/heads/main"),
            config.RefSpec("refs/heads/develop:refs/heads/develop"),
        },
        Atomic: true,
    })
    if err != nil {
        panic(err)
    }
}

Pull Operations

Pull from Worktree

func (w *Worktree) Pull(o *PullOptions) error
func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error

Example:

package main

import (
    "fmt"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    w, err := r.Worktree()
    if err != nil {
        panic(err)
    }

    // Pull from origin
    err = w.Pull(&git.PullOptions{RemoteName: "origin"})
    if err == git.NoErrAlreadyUpToDate {
        fmt.Println("Already up to date")
    } else if err != nil {
        panic(err)
    }

    // Print HEAD after pull
    ref, err := r.Head()
    if err != nil {
        panic(err)
    }
    fmt.Println("HEAD at:", ref.Hash())
}

PullOptions

type PullOptions struct {
    RemoteName        string
    RemoteURL         string
    ReferenceName     plumbing.ReferenceName
    SingleBranch      bool
    Depth             int
    Auth              transport.AuthMethod
    RecurseSubmodules SubmoduleRescursivity
    Progress          sideband.Progress
    Force             bool
    InsecureSkipTLS   bool
    ClientCert        []byte
    ClientKey         []byte
    CABundle          []byte
    ProxyOptions      transport.ProxyOptions
}

Example with Options:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    w, err := r.Worktree()
    if err != nil {
        panic(err)
    }

    err = w.Pull(&git.PullOptions{
        RemoteName:    "origin",
        ReferenceName: plumbing.ReferenceName("refs/heads/develop"),
        SingleBranch:  true,
        Depth:         10,
        Auth: &http.BasicAuth{
            Username: "user",
            Password: "token",
        },
        Progress: os.Stdout,
    })
    if err != nil && err != git.NoErrAlreadyUpToDate {
        panic(err)
    }
}

List Remote References

List References

func (remote *Remote) List(o *ListOptions) ([]*plumbing.Reference, error)

List references available on the remote without fetching.

Example:

package main

import (
    "fmt"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainOpen("/tmp/repo")
    if err != nil {
        panic(err)
    }

    remote, err := r.Remote("origin")
    if err != nil {
        panic(err)
    }

    // List remote references
    refs, err := remote.List(&git.ListOptions{})
    if err != nil {
        panic(err)
    }

    fmt.Println("Remote references:")
    for _, ref := range refs {
        fmt.Printf("  %s -> %s\n", ref.Name().Short(), ref.Hash())
    }
}

Authentication

HTTP Basic Authentication

import "github.com/go-git/go-git/v5/plumbing/transport/http"

type BasicAuth struct {
    Username string
    Password string
}

Example - Username and Password:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func main() {
    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL: "https://github.com/private/repo",
        Auth: &http.BasicAuth{
            Username: "username",
            Password: "password",
        },
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Example - Personal Access Token:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func main() {
    token := os.Getenv("GITHUB_TOKEN")

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL: "https://github.com/private/repo",
        Auth: &http.BasicAuth{
            Username: "abc123", // Can be anything except empty
            Password: token,
        },
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

HTTP Token Authentication

import "github.com/go-git/go-git/v5/plumbing/transport/http"

type TokenAuth struct {
    Token string
}

Example:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func main() {
    token := os.Getenv("GITHUB_TOKEN")

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL: "https://github.com/private/repo",
        Auth: &http.TokenAuth{
            Token: token,
        },
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

SSH Public Key Authentication

import "github.com/go-git/go-git/v5/plumbing/transport/ssh"

type PublicKeys struct {
    User   string
    Signer ssh.Signer
    // contains filtered or unexported fields
}

func NewPublicKeys(user string, pemBytes []byte, password string) (*PublicKeys, error)
func NewPublicKeysFromFile(user, pemFile, password string) (*PublicKeys, error)

Example - SSH Key from File:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/ssh"
)

func main() {
    // Load SSH key from file
    sshKey := os.Getenv("HOME") + "/.ssh/id_rsa"
    auth, err := ssh.NewPublicKeysFromFile("git", sshKey, "")
    if err != nil {
        panic(err)
    }

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:  "git@github.com:private/repo.git",
        Auth: auth,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Example - SSH Key from Memory:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/ssh"
)

func main() {
    // Read SSH key
    keyBytes, err := os.ReadFile(os.Getenv("HOME") + "/.ssh/id_rsa")
    if err != nil {
        panic(err)
    }

    // Create auth from key bytes
    auth, err := ssh.NewPublicKeys("git", keyBytes, "")
    if err != nil {
        panic(err)
    }

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:  "git@github.com:private/repo.git",
        Auth: auth,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Example - SSH Key with Passphrase:

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/ssh"
)

func main() {
    sshKey := os.Getenv("HOME") + "/.ssh/id_rsa"
    passphrase := os.Getenv("SSH_PASSPHRASE")

    auth, err := ssh.NewPublicKeysFromFile("git", sshKey, passphrase)
    if err != nil {
        panic(err)
    }

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:  "git@github.com:private/repo.git",
        Auth: auth,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

SSH Password Authentication

import "github.com/go-git/go-git/v5/plumbing/transport/ssh"

type Password struct {
    User     string
    Password string
}

Example:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/ssh"
)

func main() {
    auth := &ssh.Password{
        User:     "git",
        Password: "password",
    }

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:  "ssh://git@example.com/repo.git",
        Auth: auth,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

TLS Configuration

Skip TLS Verification

Use with caution - only for testing or self-signed certificates:

package main

import (
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:             "https://self-signed.example.com/repo.git",
        InsecureSkipTLS: true,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Custom CA Bundle

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
)

func main() {
    // Load custom CA certificate
    caBundle, err := os.ReadFile("/path/to/ca-cert.pem")
    if err != nil {
        panic(err)
    }

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:      "https://example.com/repo.git",
        CABundle: caBundle,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Client Certificates

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
)

func main() {
    // Load client certificate and key
    clientCert, err := os.ReadFile("/path/to/client-cert.pem")
    if err != nil {
        panic(err)
    }

    clientKey, err := os.ReadFile("/path/to/client-key.pem")
    if err != nil {
        panic(err)
    }

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:        "https://example.com/repo.git",
        ClientCert: clientCert,
        ClientKey:  clientKey,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Proxy Configuration

type ProxyOptions struct {
    URL      string
    Username string
    Password string
}

Example:

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport"
)

func main() {
    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL: "https://github.com/repo/repo",
        ProxyOptions: transport.ProxyOptions{
            URL:      "http://proxy.example.com:8080",
            Username: "proxy-user",
            Password: "proxy-pass",
        },
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Progress Reporting

Progress to Stdout

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:      "https://github.com/large/repo",
        Progress: os.Stdout,
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Custom Progress Handler

package main

import (
    "fmt"
    "io"
    "github.com/go-git/go-git/v5"
)

type progressWriter struct{}

func (pw *progressWriter) Write(p []byte) (n int, err error) {
    fmt.Print(string(p))
    return len(p), nil
}

func main() {
    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL:      "https://github.com/repo/repo",
        Progress: &progressWriter{},
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

Common Errors

var (
    ErrRemoteNotFound       = errors.New("remote not found")
    ErrRemoteExists         = errors.New("remote already exists")
    ErrAnonymousRemoteName  = errors.New("anonymous remote name not allowed")
    ErrFetching             = errors.New("error fetching")
    ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
    NoErrAlreadyUpToDate    = errors.New("already up-to-date")
)

From transport package:

var (
    ErrRepositoryNotFound    = errors.New("repository not found")
    ErrEmptyRemoteRepository = errors.New("remote repository is empty")
    ErrAuthenticationRequired = errors.New("authentication required")
    ErrAuthorizationFailed   = errors.New("authorization failed")
    ErrInvalidAuthMethod     = errors.New("invalid auth method")
)

Best Practices

1. Always Check for NoErrAlreadyUpToDate

package main

import (
    "github.com/go-git/go-git/v5"
)

func main() {
    r, _ := git.PlainOpen("/tmp/repo")

    err := r.Fetch(&git.FetchOptions{RemoteName: "origin"})
    if err == git.NoErrAlreadyUpToDate {
        println("Repository is up to date")
    } else if err != nil {
        panic(err)
    } else {
        println("Fetched new changes")
    }
}

2. Use Context for Timeout Control

package main

import (
    "context"
    "time"
    "github.com/go-git/go-git/v5"
)

func main() {
    r, _ := git.PlainOpen("/tmp/repo")

    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    err := r.FetchContext(ctx, &git.FetchOptions{
        RemoteName: "origin",
    })
    if err != nil && err != git.NoErrAlreadyUpToDate {
        panic(err)
    }
}

3. Store Credentials Securely

package main

import (
    "os"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func main() {
    // Load from environment variable, not hardcoded
    token := os.Getenv("GITHUB_TOKEN")
    if token == "" {
        panic("GITHUB_TOKEN not set")
    }

    r, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
        URL: "https://github.com/private/repo",
        Auth: &http.BasicAuth{
            Username: "token",
            Password: token,
        },
    })
    if err != nil {
        panic(err)
    }

    _ = r
}

4. Use Force with Lease for Safer Force Pushes

package main

import (
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing"
)

func main() {
    r, _ := git.PlainOpen("/tmp/repo")

    // Get current remote state
    ref, _ := r.Reference(plumbing.ReferenceName("refs/remotes/origin/main"), true)

    // Force with lease - safer than force push
    err := r.Push(&git.PushOptions{
        RemoteName: "origin",
        ForceWithLease: &git.ForceWithLease{
            RefName: plumbing.ReferenceName("refs/heads/main"),
            Hash:    ref.Hash(),
        },
    })
    if err != nil {
        panic(err)
    }
}

5. Handle Authentication Errors Gracefully

package main

import (
    "errors"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func main() {
    r, _ := git.PlainOpen("/tmp/repo")

    err := r.Push(&git.PushOptions{
        RemoteName: "origin",
        Auth: &http.BasicAuth{
            Username: "user",
            Password: "wrong-password",
        },
    })

    if err != nil {
        if errors.Is(err, transport.ErrAuthenticationRequired) {
            println("Authentication required")
        } else if errors.Is(err, transport.ErrAuthorizationFailed) {
            println("Authorization failed - check credentials")
        } else {
            panic(err)
        }
    }
}

See Also

  • Repository Operations - Creating and opening repositories
  • Worktree Operations - Working with files and commits
  • Transport - Detailed transport protocol information
  • Configuration - Remote configuration management