API Reference

Everything documented here is importable directly from giterator, except for Repo, which lives in giterator.testing so that test-only code is never pulled in by normal use.

giterator

class giterator.Git(path: Path | str)

Represents a local work tree and repo.

Parameters:

path – The path to an existing work tree or local repo.

path: Path

The path where this instance is located.

__call__(*command: str, env: dict[str, str] | None = None, cwd: Path | None = None) str

Run a git command in this repo. For example:

Git(...)('log', '-1')

env supplies additional environment variables, or overrides for existing ones; it is merged with the current process’s environment rather than replacing it.

git(*command: str, env: dict[str, str] | None = None, cwd: Path | None = None) str

Run a git command in this repo. For example:

Git(...)('log', '-1')

env supplies additional environment variables, or overrides for existing ones; it is merged with the current process’s environment rather than replacing it.

init(user: User | None = None, branch: str | None = None, bare: bool = False) None

Create an empty Git repository or reinitialize an existing one. If the path doesn’t exist, it will be created. This includes any missing parent directories.

Parameters:
  • user – The user to configure in the local repo.

  • branch – The name to use for the initial branch. If not specified, the machine’s git default is used.

  • bare – If True, create a bare repository. Worktrees of a bare repo share its config, so configuring user here is what makes commits in those worktrees work without depending on the git config of the machine the tests are running on.

classmethod clone(source: str | Path | Git, path: str | Path, user: User | None = None) Self

Clone the source repo to the path specified.

Parameters:
  • source – The repo to clone, either as a path or a Git instance.

  • path – Where to clone to. Relative paths are resolved relative to the parent of source.

  • user – The user to configure in the local clone. If not specified and source is a Git instance, the user from source, if any, is configured. Otherwise, no user is configured and commits in the clone will depend on git’s normal identity discovery.

commit(msg: str, author_date: date | datetime | str | None = None, commit_date: date | datetime | str | None = None, short: bool = True, allow_empty: bool = False) str

Commit changes in this repo, including and new or deleted files.

Parameters:
  • msg – The commit message.

  • author_date – The author date.

  • commit_date – The commit date. If not specified, git’s own default is used, which is the current time rather than author_date.

  • short – Return the short commit hash instead of the full 40-character hash.

  • allow_empty – Allow a commit to be made even when there are no changes.

rev_parse(label: str, short: bool = True) str

Return the commit hash that label refers to.

Parameters:
  • label – A branch, tag, or other revision that git rev-parse accepts.

  • short – Return the short commit hash instead of the full 40-character hash.

log(*options: str) list[Commit]

Return the commits in this repo as a list of Commit instances, most recent first.

Parameters:

options – Any options, revision ranges or paths that git log accepts.

tag(name: str) None

Create a tag with the specified name.

tags() list[str]

Return a list of tags in this repo.

tag_hashes() dict[str, str]

Return a mapping of tag name to commit hash.

branch(name: str) None

Create and checkout a branch with the specified name.

branches() list[str]

Return a list of branches in this repo.

branch_hashes() dict[str, str]

Return a mapping of branch name to commit hash.

class giterator.User(name: str, email: str)

Represents a git user, for configuring a repo.

name: str

The name of the user.

email: str

The email address of the user.

class giterator.Commit(rev: str, author: User, author_date: datetime, committer: User, committer_date: datetime, message: str)

A commit from the log of a repo.

rev: str

The short hash of the commit.

author: User

The author of the commit.

author_date: datetime

The author date of the commit.

committer: User

The committer of the commit.

committer_date: datetime

The committer date of the commit.

message: str

The full commit message, without any trailing newlines.

exception giterator.GitError

Something went wrong while running a git command.

class giterator.Every(period: timedelta, anchor: time | None = None)

A schedule of evenly spaced points in time.

Parameters:
  • period – The gap between points on the schedule.

  • anchor – An optional time of day to anchor points to.

at(hour: int, minute: int = 0) Every

Return a copy of this schedule anchored at the time of day specified.

ticks(start: datetime) Iterator[datetime]

Yield an unbounded sequence of points on this schedule, beginning with the first point at or after start.

class giterator.Giteration(path: Path | str, at: datetime | None = None, rev: str | None = None, message: str | None = None)

The content of a repo at a point in time.

Parameters:
  • path – The path of a directory containing the content.

  • at – When the content was current.

  • rev – The revision the content came from, filled in by read().

  • message – The commit message for write() to use, filled in from the source commit by read().

path: Path

The path of a directory containing the content.

at: datetime | None

When the content was current.

rev: str | None

The revision the content came from.

message: str | None

The commit message for write() to use. read() fills this in from the source commit.

giterator.read(repo: Git | Path | str, schedule: Every | timedelta | None = None, start: datetime | None = None, skip_unchanged: bool = True) Iterator[Giteration]

Iterate over the history of repo, yielding a Giteration for each commit. When a schedule is given, one is instead yielded for each point on it at which the repo had changed since the previous point, and iteration stops once the most recent commit has been yielded.

The repo is cloned into a temporary location and each revision is checked out there, so the repo itself is never modified. The path of each Giteration yielded is only valid until the next one is requested, and is removed when iteration finishes.

Parameters:
  • repo – The repo to read, either as a path or a Git instance.

  • schedule – The points in time at which to sample the repo’s history, either an Every instance such as daily or a timedelta giving the gap between points. When not given, every commit is yielded, with at set to its committer date.

  • start – Where the schedule starts. Defaults to the date of the repo’s first commit. When no schedule is given, commits before this point are skipped.

  • skip_unchanged – Only meaningful with a schedule. When False, points on the schedule at which the repo had not changed are yielded rather than skipped, giving exactly one Giteration per point.

giterator.write(repo: Git | Path | str, revs: Iterable[Giteration], user: User | None = None) Git

Write each Giteration in revs as a commit in repo, in the order given. The content of each one replaces the content of the repo’s work tree and is committed using its at date for both the author and committer dates.

Parameters:
  • repo – The repo to write to, either as a path or a Git instance. If the path is not already a repo, one is created.

  • revs – The Giteration instances to write.

  • user – The user to configure if a repo is created.

giterator.daily: Every

A daily schedule, for use with read().

giterator.testing

class giterator.testing.Repo(path: Path | str)

Bases: Git

A repo for making sample repositories in automated tests.

classmethod make(path: Path | str, user: User | None = None, branch: str = 'main') Self

Make a repo at the path specified and ensure a user and initial branch name are configured in the repo, so neither depends on the git config of the machine the tests are running on. Both can be specified.

classmethod clone(source: str | Path | Git, path: str | Path, user: User | None = None) Self

As Git.clone, but always ensures a user is configured in the clone, so commits made in it never depend on the machine’s global git config. The user can be specified, and is otherwise inherited from a Git source; failing both, the same default as make() is used.

commit(msg: str, author_date: date | datetime | str | None = None, commit_date: date | datetime | str | None = None, short: bool = True, allow_empty: bool = False) str

As Git.commit, but commit_date defaults to author_date when not given, so a single date is enough to pin both of a commit’s timestamps.

commit_content(name: str = 'sample.txt', dt: datetime | None = None, *, content: str | None = None, message: str = 'a commit', tag: str | None = None, branch: str | None = None, short: bool = True) str

Make a commit in a single call: write a file and commit it.

Parameters:
  • name – The name of the file to write.

  • dt – The datetime to use for both the author and commit dates. When not given, each commit uses the next point in a deterministic sequence of increasing datetimes, so tests never depend on the current time.

  • content – The content to write to the file. Defaults to content derived from name.

  • message – The commit message to use.

  • tag – A tag to create at the new commit.

  • branch – A branch to create and check out before committing.

  • short – Return the short commit hash instead of the full 40-character hash.