Skip to content

Atoms Overview

Every registered scenario is built from small, single-purpose atoms — functions that take a TempGitRepo and apply one side-effect. The atom signature is uniform:

type Step = (repo: TempGitRepo) => Promise<void>

Atoms compose via chain(...):

import { chain, addCommit, switchToBranch, startMerge } from '@gfargo/git-scenarios'
const setup = chain(
addCommit({ message: 'base', files: { 'x.ts': 'base\n' } }),
switchToBranch('feat/theirs'),
addCommit({ message: 'theirs', files: { 'x.ts': 'theirs\n' } }),
switchToBranch('main'),
addCommit({ message: 'ours', files: { 'x.ts': 'ours\n' } }),
startMerge('feat/theirs'),
)
// Use it:
const repo = await createTempGitRepo()
await setup(repo)

Atom categories

CategoryAtoms
Control Flowchain, repeat, conditionally
Working TreewriteFiles, deleteFiles, renameFile, seededFiles
Commits & StagingstageFiles, unstageFiles, commit, addCommit, emptyCommit, amendCommit, bulkCommits
Branches & TagsswitchToBranch, checkoutBranch, createBranch, deleteBranch, createTag, deleteTag
Remotes & TrackingaddRemote, removeRemote, renameRemote, setUpstream, setRemoteRef
OperationsstartMerge, cherryPick, revert, startRebase, startBisect, resetTo, … + lifecycle continue/abort atoms
ScopingonBranch, insideSubmodule, withAuthor, withRemoteTracking
UtilitiesgitClean, writeGitignore, writeGitattributes, enableSparseCheckout, shallowAt, addNote, installHook, setConfig, daysAgo

Writing custom atoms

Any function that returns a Step is an atom:

import type { Step } from '@gfargo/git-scenarios'
function myCustomAtom(arg: string): Step {
return async (repo) => {
await repo.git.raw(['some-command', arg])
}
}
// Use it alongside built-in atoms:
await chain(
addCommit({ message: 'init', files: { 'README.md': '# repo' } }),
myCustomAtom('value'),
)(repo)

TempGitRepo helpers

Atoms receive a TempGitRepo handle with a few convenience methods on top of the simple-git instance:

type TempGitRepo = {
path: string // absolute fs path
git: SimpleGit // simple-git instance
writeFile: (path: string, content: string) => Promise<void>
readFile: (path: string) => Promise<string> // utf-8
exists: (path: string) => Promise<boolean> // file or dir
commitAll: (message: string) => Promise<void>
snapshot: () => Promise<RepoSnapshot> // structured state
cleanup: () => Promise<void>
}

Use repo.readFile(...) and repo.exists(...) in tests instead of importing fs — they’re scoped to the repo path automatically.