Lint your commit messages with configurable rules and conventional commit support
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Git integration for reading commit messages from various sources including history ranges, edit files, and environment variables.
Main function for reading commit messages from Git repository or files.
/**
* Read commit messages from various sources
* @param options - Configuration for specifying source and range
* @returns Promise resolving to array of commit message strings
*/
function read(options: GetCommitMessageOptions): Promise<string[]>;Configuration options for specifying how and which commit messages to read.
interface GetCommitMessageOptions {
/** Working directory containing .git folder (default: process.cwd()) */
cwd?: string;
/** Start commit hash/reference for range reading */
from?: string;
/** Use last git tag as the start of the range */
fromLastTag?: boolean;
/** End commit hash/reference for range reading (default: HEAD) */
to?: string;
/** Read only the last commit */
last?: boolean;
/** Read from edit file (true for .git/COMMIT_EDITMSG, string for custom path) */
edit?: boolean | string;
/** Additional arguments to pass to git log command */
gitLogArgs?: string;
}Read individual commits using various methods.
// Last commit only
const messages = await read({ last: true });
// From edit file (Git hooks)
const messages = await read({ edit: true });
// From specific file path
const messages = await read({ edit: "/path/to/commit-msg" });Read multiple commits within a specified range.
// Commit range by hash/reference
const messages = await read({
from: "HEAD~5",
to: "HEAD"
});
// From last tag to HEAD
const messages = await read({
fromLastTag: true
});
// Custom range with additional git log arguments
const messages = await read({
from: "origin/main",
to: "HEAD",
gitLogArgs: "--first-parent --no-merges"
});Specify different Git repositories or working directories.
// Read from specific repository
const messages = await read({
cwd: "/path/to/git/repository",
last: true
});
// Read with relative paths
const messages = await read({
cwd: "../other-project",
from: "HEAD~3"
});import read from "@commitlint/read";
// Read last commit message
const messages = await read({ last: true });
console.log(messages[0]); // "feat: add user authentication"
// Read from commit edit file (useful in Git hooks)
const editMessages = await read({ edit: true });
console.log(editMessages[0]); // Content of .git/COMMIT_EDITMSGimport read from "@commitlint/read";
// Read commits in a range
const rangeMessages = await read({
from: "HEAD~10",
to: "HEAD"
});
console.log(`Found ${rangeMessages.length} commits`);
rangeMessages.forEach((msg, index) => {
console.log(`Commit ${index + 1}: ${msg.split('\n')[0]}`);
});import read from "@commitlint/read";
// Read all commits since last tag
const tagMessages = await read({
fromLastTag: true
});
console.log(`Commits since last tag: ${tagMessages.length}`);import read from "@commitlint/read";
// Use custom git log arguments
const messages = await read({
from: "origin/main",
gitLogArgs: "--first-parent --cherry-pick --no-merges"
});
// Read from feature branch
const featureMessages = await read({
from: "main",
to: "feature/new-api"
});import read from "@commitlint/read";
// Read from specific commit message file
const fileMessages = await read({
edit: "/tmp/commit-message.txt"
});
// Read from environment-specified file
const envFile = process.env.COMMIT_MSG_FILE;
if (envFile) {
const envMessages = await read({
edit: envFile
});
}import read from "@commitlint/read";
import lint from "@commitlint/lint";
import { load } from "@commitlint/load";
// Complete workflow: read, configure, and lint
async function lintCommits() {
// Load configuration
const config = await load();
// Read commit messages
const messages = await read({
from: "HEAD~5",
to: "HEAD"
});
// Lint each message
const results = await Promise.all(
messages.map(message =>
lint(message, config.rules, {
parserOpts: config.parserPreset?.parserOpts,
plugins: config.plugins
})
)
);
// Process results
results.forEach((result, index) => {
if (!result.valid) {
console.log(`Commit ${index + 1} failed validation:`);
console.log(`Message: ${result.input}`);
result.errors.forEach(error => {
console.log(` ❌ ${error.name}: ${error.message}`);
});
}
});
}
await lintCommits();import read from "@commitlint/read";
// Pre-commit hook example
async function preCommitHook() {
try {
// Read the commit message being created
const messages = await read({ edit: true });
if (messages.length === 0) {
console.log("No commit message found");
process.exit(1);
}
// Further processing...
return messages[0];
} catch (error) {
console.error("Failed to read commit message:", error);
process.exit(1);
}
}import read from "@commitlint/read";
// Validate commits in CI pipeline
async function validatePullRequest() {
const baseBranch = process.env.GITHUB_BASE_REF || "main";
const headBranch = process.env.GITHUB_HEAD_REF || "HEAD";
const messages = await read({
from: `origin/${baseBranch}`,
to: headBranch,
gitLogArgs: "--no-merges" // Skip merge commits
});
if (messages.length === 0) {
console.log("No commits to validate");
return;
}
console.log(`Validating ${messages.length} commits...`);
// Continue with validation logic...
}import read from "@commitlint/read";
async function safeRead(options) {
try {
const messages = await read(options);
return messages;
} catch (error) {
if (error.message.includes("not a git repository")) {
console.error("Current directory is not a Git repository");
} else if (error.message.includes("bad revision")) {
console.error("Invalid commit reference provided");
} else {
console.error("Failed to read commits:", error.message);
}
return [];
}
}
// Usage with error handling
const messages = await safeRead({
from: "invalid-ref",
to: "HEAD"
});