GitRepository
The GitRepository class provides access to Git repository data.
Constructor
GitRepository(path: Path)
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]
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 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
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" )
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" )
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.
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 } " )
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