list_commits
Retrieve recent commits from an Azure DevOps branch, with file-level diff content per commit. Specify repository and branch; use top to limit results and skip for pagination.
Instructions
List recent commits on a branch including file-level diff content for each commit
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectId | No | The ID or name of the project (Default: MyProject) | |
| organizationId | No | The ID or name of the organization (Default: mycompany) | |
| repositoryId | Yes | The ID or name of the repository | |
| branchName | Yes | Branch name to list commits from | |
| top | No | Maximum number of commits to return (Default: 10) | |
| skip | No | Number of commits to skip from the newest |
Implementation Reference
- The main handler function that lists commits on a branch including file-level diffs. Uses Azure DevOps Git API to fetch commits, retrieves file changes for each commit, generates unified diffs, and returns commits with content.
export async function listCommits( connection: WebApi, options: ListCommitsOptions, ): Promise<ListCommitsResponse> { try { const gitApi = await connection.getGitApi(); const commits = await gitApi.getCommits( options.repositoryId, { itemVersion: { version: options.branchName, versionType: GitVersionType.Branch, }, $top: options.top ?? 10, $skip: options.skip, }, options.projectId, ); if (!commits || commits.length === 0) { return { commits: [] }; } const getBlobText = async (objId?: string): Promise<string> => { if (!objId) { return ''; } const stream = await gitApi.getBlobContent( options.repositoryId, objId, options.projectId, ); return stream ? await streamToString(stream) : ''; }; const commitsWithContent: CommitWithContent[] = []; for (const commit of commits) { const commitId = commit.commitId; if (!commitId) { continue; } const commitChanges = await gitApi.getChanges( commitId, options.repositoryId, options.projectId, ); const changeEntries = commitChanges?.changes ?? []; const files = await Promise.all( changeEntries.map(async (entry: GitChange) => { const path = entry.item?.path || entry.originalPath || ''; const [oldContent, newContent] = await Promise.all([ getBlobText(entry.item?.originalObjectId), getBlobText(entry.item?.objectId), ]); const patch = createTwoFilesPatch( entry.originalPath || path, path, oldContent, newContent, ); return { path, patch }; }), ); commitsWithContent.push({ commitId, comment: commit.comment, author: commit.author, committer: commit.committer, url: commit.url, parents: commit.parents, files, }); } return { commits: commitsWithContent }; } catch (error) { if (error instanceof AzureDevOpsError) { throw error; } throw new Error( `Failed to list commits: ${error instanceof Error ? error.message : String(error)}`, ); } } - Zod schema for validating list_commits input: projectId, organizationId, repositoryId, branchName, top (1-100, default 10), skip.
export const ListCommitsSchema = z.object({ projectId: z .string() .optional() .describe(`The ID or name of the project (Default: ${defaultProject})`), organizationId: z .string() .optional() .describe(`The ID or name of the organization (Default: ${defaultOrg})`), repositoryId: z.string().describe('The ID or name of the repository'), branchName: z.string().describe('Branch name to list commits from'), top: z .number() .int() .min(1) .max(100) .optional() .describe('Maximum number of commits to return (Default: 10)'), skip: z .number() .int() .min(0) .optional() .describe('Number of commits to skip from the newest'), }); - TypeScript interfaces: ListCommitsOptions (input), CommitWithContent (per-commit structure with files containing path/patch), and ListCommitsResponse (output).
export interface ListCommitsOptions { projectId: string; repositoryId: string; branchName: string; top?: number; skip?: number; } /** * Representation of a commit along with the file diffs it touches */ export interface CommitWithContent { commitId: string; comment?: string; author?: { name?: string; email?: string; date?: Date; }; committer?: { name?: string; email?: string; date?: Date; }; url?: string; parents?: string[]; files: Array<{ path: string; patch: string }>; } /** * Response for listing commits with their associated content */ export interface ListCommitsResponse { commits: CommitWithContent[]; } - src/features/repositories/tool-definitions.ts:100-106 (registration)Tool definition registration with name 'list_commits', description, and inputSchema derived from ListCommitsSchema.
{ name: 'list_commits', description: 'List recent commits on a branch including file-level diff content for each commit', inputSchema: zodToJsonSchema(ListCommitsSchema), }, ]; - Helper function streamToString used to convert a Node.js ReadableStream to a string (for reading blob content).
async function streamToString(stream: NodeJS.ReadableStream): Promise<string> { const chunks: Buffer[] = []; return await new Promise<string>((resolve, reject) => { stream.on('data', (c) => chunks.push(Buffer.from(c))); stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8'))); stream.on('error', (err) => reject(err)); }); }