safegit v0.26.0 /internal/git
On this page

Package git wraps os/exec calls to the git binary and is the sole interface through which safegit interacts with git plumbing commands.

#internal/git

#internal/git

Package git wraps os/exec calls to the git binary and is the sole interface through which safegit interacts with git plumbing commands. All functions shell out to git and return structured results; no other package may invoke git directly.

#ErrDetachedHead

Go go
var ErrDetachedHead = fmt.Errorf("HEAD is detached (not on a branch); check out a branch first or use --branch")

ErrDetachedHead is returned when HEAD is not on a branch.

#AuthorInfo

Go go
type AuthorInfo struct

AuthorInfo holds the name, email, and raw git date for an author or committer.

#CommitInfo

Go go
type CommitInfo struct

CommitInfo holds the parsed contents of a git commit object.

#TreeEntry

Go go
type TreeEntry struct

TreeEntry represents an entry from git ls-tree (blob, tree, or other object).

#ObjectEntry

Go go
type ObjectEntry struct

ObjectEntry holds one object read from a git cat-file --batch stream.

#ObjectIterator

Go go
type ObjectIterator struct

ObjectIterator streams objects from a long-running git cat-file process.

#WithDir

Go go
func WithDir(ctx context.Context, gitDir, workTree string) context.Context

WithDir returns a context that carries git directory overrides. All git functions that receive this context will automatically set GIT_DIR, GIT_WORK_TREE, and cmd.Dir on the subprocess, targeting the specified repo regardless of the process's current working directory.

#Run

Go go
func Run(ctx context.Context, args ...string) (stdout, stderr string, err error)

Run executes a git command and returns stdout, stderr, and any error.

#RunWithEnv

Go go
func RunWithEnv(ctx context.Context, env []string, args ...string) (stdout, stderr string, err error)

RunWithEnv executes a git command with additional environment variables.

#RunWithEnvStdin

Go go
func RunWithEnvStdin(ctx context.Context, env []string, stdin []byte, args ...string) (stdout, stderr string, err error)

RunWithEnvStdin executes a git command with environment variables and stdin data.

#RepoRoot

Go go
func RepoRoot(ctx context.Context) (string, error)

RepoRoot returns the absolute path to the repository root.

#GitDir

Go go
func GitDir(ctx context.Context) (string, error)

GitDir returns the path to the .git directory.

#HeadRef

Go go
func HeadRef(ctx context.Context) (string, error)

HeadRef returns the current branch ref (e.g. "refs/heads/main"). Returns ErrDetachedHead if HEAD is not on a branch.

#RevParse

Go go
func RevParse(ctx context.Context, rev string) (string, error)

RevParse resolves a revision to a full SHA.

#ReadTree

Go go
func ReadTree(ctx context.Context, indexPath, treeish string) error

ReadTree populates a temporary index from a treeish (commit/tree SHA or ref).

#WriteTree

Go go
func WriteTree(ctx context.Context, indexPath string) (string, error)

WriteTree writes the index content as a tree object, returns the tree SHA.

#CommitTree

Go go
func CommitTree(ctx context.Context, treeSHA, parentSHA, message string) (string, error)

CommitTree creates a commit object from a tree SHA and parent, returns commit SHA. If parentSHA is empty, creates a root commit.

#UpdateRef

Go go
func UpdateRef(ctx context.Context, ref, newSHA, oldSHA string) error

UpdateRef atomically updates a ref using compare-and-swap. oldSHA is the expected current value; if empty, the ref must not exist.

#DeleteRef

Go go
func DeleteRef(ctx context.Context, ref, oldSHA string) error

DeleteRef atomically deletes a ref using compare-and-swap. oldSHA is the expected current value of the ref.

#AddFile

Go go
func AddFile(ctx context.Context, indexPath, filePath string) error

AddFile stages a file into a custom index.

#RmCached

Go go
func RmCached(ctx context.Context, indexPath, filePath string) error

RmCached removes a file or directory from a custom index without touching the working tree.

#IsTracked

Go go
func IsTracked(ctx context.Context, filePath string) (bool, error)

IsTracked checks whether a file is tracked by git (present in HEAD tree). Uses cat-file instead of ls-files because safegit never writes to the main index -- files committed via safegit exist in HEAD but not in .git/index.

#ListSkipWorktreeFiles

Go go
func ListSkipWorktreeFiles(ctx context.Context) ([]string, error)

ListSkipWorktreeFiles returns the paths of all files with the skip-worktree flag set in the main index. It parses git ls-files -v output, selecting lines that start with "S " (the skip-worktree indicator).

#ListTrackedIgnoredFiles

Go go
func ListTrackedIgnoredFiles(ctx context.Context) ([]string, error)

ListTrackedIgnoredFiles returns the paths of all files that are tracked in the index but ignored by .gitignore rules. These are files that were once committed and later gitignored -- read-tree --reset -u would overwrite them, destroying local modifications (e.g., config files with secrets).

#SyncMainIndex

Go go
func SyncMainIndex(ctx context.Context, treeish string) error

SyncMainIndex updates the main .git/index to match the given treeish. This makes git status/diff reflect the committed state after safegit commits. Skip-worktree flags are preserved across the read-tree rebuild.

#SyncMainIndexWithWorktree

Go go
func SyncMainIndexWithWorktree(ctx context.Context, treeish string) ([]string, error)

SyncMainIndexWithWorktree updates the main .git/index AND the working tree to match the given treeish. Uses --reset -u, so the working tree must be clean before calling. Needed after history rewrites (scrub) where committed blobs have changed and the working tree must reflect the new content.

Tracked+gitignored files (committed then later gitignored, e.g., config files with secrets) are protected: skip-worktree is set before read-tree so --reset -u does not overwrite them. Pre-existing skip-worktree flags are also preserved.

Returns the list of protected tracked+gitignored paths (empty if none).

#RunPassthrough

Go go
func RunPassthrough(ctx context.Context, args ...string) error

RunPassthrough executes a git command with stdin/stdout/stderr wired to the terminal (os.Stdin, os.Stdout, os.Stderr). It prepends --no-optional-locks like Run, but does not capture output -- suitable for interactive/pager commands.

#CommonGitDir

Go go
func CommonGitDir(ctx context.Context) (string, error)

CommonGitDir returns the path to the shared .git directory. For normal repos this equals GitDir(); for worktrees it returns the main .git dir that is shared across all worktrees. Lock files should live here so that worktrees committing to the same branch serialize correctly.

#CommonGitDirOf

Go go
func CommonGitDirOf(ctx context.Context, gitDir string) (string, error)

CommonGitDirOf returns the common git directory for a given gitDir. Unlike CommonGitDir, this does not depend on the process working directory; it sets GIT_DIR explicitly so the result is always relative to gitDir.

#IsIgnored

Go go
func IsIgnored(ctx context.Context, filePath string) (bool, error)

IsIgnored checks whether a file matches a gitignore rule.

#IsAncestorOf

Go go
func IsAncestorOf(ctx context.Context, commitSHA, descendantSHA string) (bool, error)

IsAncestorOf checks whether commitSHA is an ancestor of (or equal to) descendantSHA. Uses git merge-base --is-ancestor which exits 0 if true, 1 if false, and other codes on error.

#CommitMessage

Go go
func CommitMessage(ctx context.Context, rev string) (string, error)

CommitMessage returns the full commit message of the given revision.

#ParseCommit

Go go
func ParseCommit(ctx context.Context, sha string) (CommitInfo, error)

ParseCommit reads and parses a commit object by SHA using git cat-file.

#CommitTreeWithAuthor

Go go
func CommitTreeWithAuthor(ctx context.Context, treeSHA string, parentSHAs []string, message string, author, committer AuthorInfo) (string, error)

CommitTreeWithAuthor creates a commit object with explicit author and committer identity, returning the new commit SHA.

#LsTreeAll

Go go
func LsTreeAll(ctx context.Context, treeish string) ([]TreeEntry, error)

LsTreeAll returns all blob entries in the given treeish, recursively. Empty trees return an empty slice, not an error.

#LsTree

Go go
func LsTree(ctx context.Context, treeish string) ([]TreeEntry, error)

LsTree returns all entries (blobs and subtrees) at one level of the given treeish, without recursing into subtrees. Each entry includes Mode and ObjectType so callers can distinguish blobs from trees.

#HashObject

Go go
func HashObject(ctx context.Context, path string) (string, error)

HashObject returns the blob SHA for a file without writing to the object store.

#HashObjectWrite

Go go
func HashObjectWrite(ctx context.Context, path string) (string, error)

HashObjectWrite hashes a file and writes the blob to the object store, returning the blob SHA.

#HashObjectWriteBytes

Go go
func HashObjectWriteBytes(ctx context.Context, data []byte) (string, error)

HashObjectWriteBytes writes in-memory bytes as a blob to the object store via git hash-object -w --stdin, returning the blob SHA.

#CatFileBlob

Go go
func CatFileBlob(ctx context.Context, sha string) ([]byte, error)

CatFileBlob reads blob content by SHA via git cat-file -p.

#MkTree

Go go
func MkTree(ctx context.Context, entries []TreeEntry) (string, error)

MkTree creates a tree object from a slice of TreeEntry values and returns the tree SHA. Each entry must have Mode, ObjectType, SHA, and Path populated. Input is piped to git mktree as " \t\n".

#CatFileBatchAll

Go go
func CatFileBatchAll(ctx context.Context) (*ObjectIterator, error)

CatFileBatchAll starts a git cat-file --batch-all-objects --batch subprocess and returns an ObjectIterator for streaming the results. The caller must call Close() when done. Respects WithDir context overrides.

#CatFileBatchSHAs

Go go
func CatFileBatchSHAs(ctx context.Context, shas []string) (*ObjectIterator, error)

CatFileBatchSHAs starts a git cat-file --batch subprocess that reads only the specified SHAs, and returns an ObjectIterator for streaming the results. Unlike CatFileBatchAll (which enumerates all objects), this feeds specific SHAs via stdin using bytes.NewReader to avoid pipe deadlock: if output exceeds the OS pipe buffer (~64KB), git blocks on stdout write while the caller is still writing to stdin. With bytes.NewReader, git reads stdin from memory at its own pace. The caller must call Close() when done.

#RunWithGitDir

Go go
func RunWithGitDir(ctx context.Context, gitDir string, workTree string, args ...string) (stdout, stderr string, err error)

RunWithGitDir executes a git command against a specific git directory and work tree, rather than relying on cwd-based discovery. Sets GIT_DIR, GIT_WORK_TREE, and cmd.Dir so both git and cwd-relative paths resolve against the target repo.

#CatFileBatchAllWithDir

Go go
func CatFileBatchAllWithDir(ctx context.Context, gitDir string) (*ObjectIterator, error)

CatFileBatchAllWithDir starts a git cat-file --batch-all-objects --batch subprocess targeting a specific git directory. Returns an ObjectIterator for streaming the results. The caller must call Close() when done.

#CatFileBatchSHAsWithDir

Go go
func CatFileBatchSHAsWithDir(ctx context.Context, gitDir string, shas []string) (*ObjectIterator, error)

CatFileBatchSHAsWithDir starts a git cat-file --batch subprocess targeting a specific git directory, reading only the specified SHAs. Sets GIT_DIR so git resolves objects from the target repo rather than the cwd repo. The caller must call Close() when done.

#SplitNonEmpty

Go go
func SplitNonEmpty(s string) []string

SplitNonEmpty splits s by newlines and returns only non-empty lines.

#ForEachRef

Go go
func ForEachRef(ctx context.Context, format string, prefixes ...string) ([]string, error)

ForEachRef runs git for-each-ref with the given format and optional ref prefixes (e.g. "refs/heads/", "refs/tags/"). Returns one line per ref.

#LsRemoteBulk

Go go
func LsRemoteBulk(ctx context.Context, remote, pattern string) (map[string]string, error)

LsRemoteBulk runs git ls-remote against a remote with a pattern and returns a map of refname to SHA. The output format of git ls-remote is "\t" per line; the map key is the refname.

#ObjectIterator.Next

Go go
func (it *ObjectIterator) Next() (*ObjectEntry, error)

Next reads the next non-tree object from the stream. Trees are silently skipped. Returns io.EOF when the stream ends.

#ObjectIterator.Close

Go go
func (it *ObjectIterator) Close() error

Close kills the subprocess if it is still running and waits for it to exit.

Search