Stop parsing commit history manually. Get structured commit data, generate changelogs automatically, and analyze code evolution with one clean API.
Turn weeks of git archaeology into minutes. Purpose-built for changelog generation, audit trails, and release automation.
You need to:
- Generate changelogs from commit history
- Track code changes for compliance audits
- Analyze contribution patterns across teams
- Build release notes automatically
- Monitor file evolution over time
But you're stuck running shell commands, parsing output, and maintaining fragile scripts.
composer require conduit-ui/commituse ConduitUI\Commits\Facades\Commits;
// Get all commits since last release
$commits = Commits::query()
->repository('your-org/your-repo')
->since('2025-01-01')
->until('2025-02-01')
->get();
// Group by type (feat, fix, docs, etc.)
$changelog = $commits->groupBy(function ($commit) {
preg_match('/^(\w+)(\(.+\))?:/', $commit->message, $matches);
return $matches[1] ?? 'other';
});// Track who touched sensitive files
$commits = Commits::query()
->repository('your-org/your-repo')
->path('config/production.php')
->since('2025-01-01')
->get();
foreach ($commits as $commit) {
echo "{$commit->author->name} modified config on {$commit->author->date->format('Y-m-d')}\n";
echo "SHA: {$commit->shortSha()}\n\n";
}// See what your team shipped this month
$commits = Commits::query()
->repository('your-org/your-repo')
->author('jane@company.com')
->since('2025-12-01')
->get();
$stats = [
'total_commits' => $commits->count(),
'lines_added' => $commits->sum(fn($c) => $c->stats?->additions ?? 0),
'lines_deleted' => $commits->sum(fn($c) => $c->stats?->deletions ?? 0),
'files_changed' => $commits->flatMap(fn($c) => $c->files)->unique('filename')->count(),
];// See what's changed before the merge
$comparison = Commits::compare('your-org/your-repo', 'main', 'feature-branch');
echo "Commits ahead: {$comparison->aheadBy}\n";
echo "Files changed: {$comparison->totalChangedFiles()}\n";
echo "Status: {$comparison->status}\n";
if ($comparison->isDiverged()) {
echo "Warning: Branch has diverged from main\n";
}// See every change to a critical file
$commits = Commits::query()
->repository('your-org/your-repo')
->path('src/Payment/PaymentProcessor.php')
->get();
foreach ($commits as $commit) {
echo "[{$commit->shortSha()}] {$commit->message}\n";
echo "Author: {$commit->author->name}\n";
echo "Date: {$commit->author->date->format('Y-m-d H:i')}\n\n";
}Commits::query()
->repository('owner/repo') // Required
->branch('main') // Filter by branch
->path('src/file.php') // Filter by file path
->author('user@email.com') // Filter by author
->committer('bot@github.com') // Filter by committer
->since('2025-01-01') // Start date
->until('2025-12-31') // End date
->take(100) // Limit results
->page(2) // Pagination
->get(); // ExecuteEvery response is a clean, typed object:
// Commit
$commit->sha // Full SHA
$commit->shortSha(7) // Short SHA
$commit->message // Commit message
$commit->author // CommitAuthor DTO
$commit->committer // CommitAuthor DTO
$commit->stats // CommitStats DTO
$commit->files // Collection<CommitFile>
$commit->htmlUrl // GitHub URL
// CommitAuthor
$author->name // Author name
$author->email // Author email
$author->date // DateTimeImmutable
// CommitFile
$file->filename // File path
$file->status // added|modified|removed|renamed
$file->additions // Lines added
$file->deletions // Lines deleted
$file->patch // Git patch
$file->isModified() // Status helpers
// CommitComparison
$comparison->aheadBy // Commits ahead
$comparison->behindBy // Commits behind
$comparison->status // ahead|behind|diverged|identical
$comparison->commits // Collection<Commit>
$comparison->files // Collection<CommitFile>
$comparison->isDiverged() // Status helpers$commits = Commits::query()
->repository('your-org/your-repo')
->since($lastReleaseDate)
->get();
$notes = [
'features' => $commits->filter(fn($c) => str_starts_with($c->message, 'feat:')),
'fixes' => $commits->filter(fn($c) => str_starts_with($c->message, 'fix:')),
'breaking' => $commits->filter(fn($c) => str_contains($c->message, 'BREAKING CHANGE')),
];$sensitiveFiles = [
'config/database.php',
'config/services.php',
'.env.production',
];
foreach ($sensitiveFiles as $file) {
$commits = Commits::query()
->repository('your-org/your-repo')
->path($file)
->since('2025-01-01')
->get();
// Generate audit report
}$team = ['dev1@company.com', 'dev2@company.com', 'dev3@company.com'];
$metrics = collect($team)->mapWithKeys(function ($email) {
$commits = Commits::query()
->repository('your-org/your-repo')
->author($email)
->since('2025-12-01')
->get();
return [$email => [
'commits' => $commits->count(),
'additions' => $commits->sum(fn($c) => $c->stats?->additions ?? 0),
'deletions' => $commits->sum(fn($c) => $c->stats?->deletions ?? 0),
]];
});Part of the Conduit UI ecosystem:
- conduit-ui/action - GitHub Actions management
- conduit-ui/pr - Pull request automation
- conduit-ui/issue - Issue tracking
- conduit-ui/connector - GitHub API client
Building automation workflows at scale? We provide custom integrations, dedicated support, and SLA guarantees.
Contact: Conduit UI
composer test
composer analyse
composer formatMIT License - see LICENSE