Skip to main content

GitRepository

The GitRepository class provides access to Git repository data.

Constructor

GitRepository(path: Path)
path
Path
required
Path to the Git repository directory.
from pathlib import Path
from helixcommit.git_client import GitRepository

# Current directory
repo = GitRepository(Path("."))

# Specific path
repo = GitRepository(Path("/path/to/repository"))

# Using string (converted to Path internally)
repo = GitRepository(Path("~/projects/myrepo").expanduser())

Methods

iter_commits()

Iterate over commits in a specified range.
iter_commits(commit_range: CommitRange) -> Iterator[CommitInfo]
commit_range
CommitRange
required
Range specification for commits to fetch.
Returns: Iterator of CommitInfo objects Example:
from helixcommit.git_client import CommitRange

commit_range = CommitRange(since="v1.0.0", until="v2.0.0")
commits = list(repo.iter_commits(commit_range))

for commit in commits:
    print(f"{commit.sha[:7]}: {commit.subject}")

list_tags()

List all tags in the repository, sorted by date (newest first).
list_tags() -> List[TagInfo]
Returns: List of TagInfo objects Example:
tags = repo.list_tags()

# Get latest tag
latest = tags[0] if tags else None
if latest:
    print(f"Latest tag: {latest.name} on {latest.date}")

# Get all version tags
version_tags = [tag for tag in tags if tag.name.startswith("v")]

get_github_slug()

Extract GitHub owner/repo from remote URL.
get_github_slug() -> Optional[Tuple[str, str]]
Returns: Tuple of (owner, repo) or None if not a GitHub repository Example:
slug = repo.get_github_slug()

if slug:
    owner, repo_name = slug
    print(f"GitHub repository: {owner}/{repo_name}")
else:
    print("Not a GitHub repository")

CommitRange

Specification for a range of commits to process.

Constructor

CommitRange(
    since: Optional[str] = None,
    until: Optional[str] = None,
    include_merges: bool = True,
    max_count: Optional[int] = None
)

Parameters

since
str
Starting ref (tag, commit SHA, branch, or date expression).Commits after this ref are included.
# From a tag
CommitRange(since="v1.0.0")

# From a commit SHA
CommitRange(since="abc123def")

# From a branch
CommitRange(since="main")

# From a date
CommitRange(since="2024-01-01")
CommitRange(since="7 days ago")
until
str
default:"HEAD"
Ending ref. Commits up to and including this ref are included.
# To HEAD (default)
CommitRange(since="v1.0.0")

# To a specific tag
CommitRange(since="v1.0.0", until="v2.0.0")

# To a branch
CommitRange(since="main", until="develop")
include_merges
bool
default:"true"
Whether to include merge commits.
# Include merge commits (default)
CommitRange(since="v1.0.0", include_merges=True)

# Exclude merge commits
CommitRange(since="v1.0.0", include_merges=False)
Excluding merge commits often produces cleaner release notes.
max_count
int
Maximum number of commits to process.
# Limit to 100 commits
CommitRange(since="v1.0.0", max_count=100)

# Process all commits (default)
CommitRange(since="v1.0.0")
Useful for testing or when you only need recent changes.

Data models

CommitInfo

@dataclass
class CommitInfo:
    sha: str
    subject: str
    body: str
    message: str
    author_name: str
    author_email: str
    date: datetime
    commit_type: Optional[str] = None
    scope: Optional[str] = None
    breaking: bool = False
    pr_number: Optional[int] = None
Example:
commit: CommitInfo = commits[0]

print(f"SHA: {commit.sha}")
print(f"Subject: {commit.subject}")
print(f"Author: {commit.author_name} <{commit.author_email}>")
print(f"Date: {commit.date}")
print(f"Type: {commit.commit_type}")
print(f"Scope: {commit.scope}")
print(f"Breaking: {commit.breaking}")
print(f"PR: #{commit.pr_number}" if commit.pr_number else "No PR")

TagInfo

@dataclass
class TagInfo:
    name: str
    sha: str
    date: datetime
Example:
tag: TagInfo = tags[0]

print(f"Tag: {tag.name}")
print(f"Commit: {tag.sha}")
print(f"Date: {tag.date.strftime('%Y-%m-%d')}")

Complete examples

Basic commit fetching

from pathlib import Path
from helixcommit.git_client import GitRepository, CommitRange

# Initialize repository
repo = GitRepository(Path("."))

# Get commits between tags
commit_range = CommitRange(
    since="v1.0.0",
    until="v2.0.0",
    include_merges=False
)

commits = list(repo.iter_commits(commit_range))

# Display commits
for commit in commits:
    prefix = "⚠️ " if commit.breaking else ""
    print(f"{prefix}{commit.commit_type}: {commit.subject}")

Working with tags

from pathlib import Path
from helixcommit.git_client import GitRepository, CommitRange

repo = GitRepository(Path("."))

# Get all tags
tags = repo.list_tags()

if len(tags) >= 2:
    # Get commits between last two tags
    latest = tags[0]
    previous = tags[1]
    
    print(f"Changes from {previous.name} to {latest.name}")
    
    commit_range = CommitRange(since=previous.name, until=latest.name)
    commits = list(repo.iter_commits(commit_range))
    
    print(f"Found {len(commits)} commits")

Unreleased changes

from pathlib import Path
from helixcommit.git_client import GitRepository, CommitRange

repo = GitRepository(Path("."))

# Get latest tag
tags = repo.list_tags()
latest_tag = tags[0] if tags else None

if latest_tag:
    # Get unreleased commits
    commit_range = CommitRange(since=latest_tag.name, until="HEAD")
    unreleased = list(repo.iter_commits(commit_range))
    
    print(f"Unreleased changes since {latest_tag.name}:")
    for commit in unreleased:
        print(f"  - {commit.subject}")
else:
    print("No tags found")

Filtering by commit type

from pathlib import Path
from helixcommit.git_client import GitRepository, CommitRange

repo = GitRepository(Path("."))
commits = list(repo.iter_commits(CommitRange(since="v1.0.0")))

# Filter by type
features = [c for c in commits if c.commit_type == "feat"]
fixes = [c for c in commits if c.commit_type == "fix"]
breaking = [c for c in commits if c.breaking]

print(f"Features: {len(features)}")
print(f"Fixes: {len(fixes)}")
print(f"Breaking changes: {len(breaking)}")

GitHub integration

from pathlib import Path
from helixcommit.git_client import GitRepository

repo = GitRepository(Path("."))

# Get GitHub info
slug = repo.get_github_slug()

if slug:
    owner, repo_name = slug
    print(f"Repository: https://github.com/{owner}/{repo_name}")
    
    # Use with GitHub client
    from helixcommit.github_client import GitHubClient, GitHubSettings
    
    settings = GitHubSettings(owner=owner, repo=repo_name, token="ghp_...")
    client = GitHubClient(settings)
    # ... use client
else:
    print("Not a GitHub repository")

Error handling

from pathlib import Path
from helixcommit.git_client import GitRepository, CommitRange

try:
    repo = GitRepository(Path("/nonexistent/path"))
except FileNotFoundError:
    print("Repository not found")
except Exception as e:
    print(f"Error: {e}")

try:
    commits = list(repo.iter_commits(CommitRange(since="invalid-ref")))
except Exception as e:
    print(f"Invalid ref: {e}")

Next steps

Changelog builder

Build changelogs from commits

Python API

Complete API reference

Examples

See practical examples

Conventional Commits

Learn about commit parsing