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
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
type AuthorInfo structAuthorInfo holds the name, email, and raw git date for an author or committer.
#CommitInfo
type CommitInfo structCommitInfo holds the parsed contents of a git commit object.
#TreeEntry
type TreeEntry structTreeEntry represents an entry from git ls-tree (blob, tree, or other object).
#ObjectEntry
type ObjectEntry structObjectEntry holds one object read from a git cat-file --batch stream.
#ObjectIterator
type ObjectIterator structObjectIterator streams objects from a long-running git cat-file process.
#WithDir
func WithDir(ctx context.Context, gitDir, workTree string) context.ContextWithDir 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
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
func RunWithEnv(ctx context.Context, env []string, args ...string) (stdout, stderr string, err error)RunWithEnv executes a git command with additional environment variables.
#RunWithEnvStdin
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
func RepoRoot(ctx context.Context) (string, error)RepoRoot returns the absolute path to the repository root.
#GitDir
func GitDir(ctx context.Context) (string, error)GitDir returns the path to the .git directory.
#HeadRef
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
func RevParse(ctx context.Context, rev string) (string, error)RevParse resolves a revision to a full SHA.
#ReadTree
func ReadTree(ctx context.Context, indexPath, treeish string) errorReadTree populates a temporary index from a treeish (commit/tree SHA or ref).
#WriteTree
func WriteTree(ctx context.Context, indexPath string) (string, error)WriteTree writes the index content as a tree object, returns the tree SHA.
#CommitTree
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
func UpdateRef(ctx context.Context, ref, newSHA, oldSHA string) errorUpdateRef atomically updates a ref using compare-and-swap. oldSHA is the expected current value; if empty, the ref must not exist.
#DeleteRef
func DeleteRef(ctx context.Context, ref, oldSHA string) errorDeleteRef atomically deletes a ref using compare-and-swap. oldSHA is the expected current value of the ref.
#AddFile
func AddFile(ctx context.Context, indexPath, filePath string) errorAddFile stages a file into a custom index.
#RmCached
func RmCached(ctx context.Context, indexPath, filePath string) errorRmCached removes a file or directory from a custom index without touching the working tree.
#IsTracked
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
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
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
func SyncMainIndex(ctx context.Context, treeish string) errorSyncMainIndex 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
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
func RunPassthrough(ctx context.Context, args ...string) errorRunPassthrough 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
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
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
func IsIgnored(ctx context.Context, filePath string) (bool, error)IsIgnored checks whether a file matches a gitignore rule.
#IsAncestorOf
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
func CommitMessage(ctx context.Context, rev string) (string, error)CommitMessage returns the full commit message of the given revision.
#ParseCommit
func ParseCommit(ctx context.Context, sha string) (CommitInfo, error)ParseCommit reads and parses a commit object by SHA using git cat-file.
#CommitTreeWithAuthor
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
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
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
func HashObject(ctx context.Context, path string) (string, error)HashObject returns the blob SHA for a file without writing to the object store.
#HashObjectWrite
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
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
func CatFileBlob(ctx context.Context, sha string) ([]byte, error)CatFileBlob reads blob content by SHA via git cat-file -p.
#MkTree
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 "
#CatFileBatchAll
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
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
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
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
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
func SplitNonEmpty(s string) []stringSplitNonEmpty splits s by newlines and returns only non-empty lines.
#ForEachRef
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
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 "
#ObjectIterator.Next
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
func (it *ObjectIterator) Close() errorClose kills the subprocess if it is still running and waits for it to exit.