Skip to main content
Glama

commit

Stage and commit changes to a Git repository with customized options like message reuse, amend, GPG signing, and path-specific commits using the MCP Git server.

Instructions

Commit staged changes to the git repository.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
allNoAutomatically stage modified and deleted files (-a, --all)
allowEmptyNoAllow empty commits (--allow-empty)
allowEmptyMessageNoAllow empty commit messages (--allow-empty-message)
amendNoAmend the previous commit (--amend)
authorNoOverride author (--author)
cleanupNoCleanup mode (--cleanup)
dateNoOverride author date (--date)
dryRunNoShow what would be committed (--dry-run)
fileNoRead commit message from file (-F, --file)
fixupNoCreate fixup commit for specified commit (--fixup)
gpgSignNoGPG sign commit (-S, --gpg-sign)
includeNoInclude given paths in addition to index (-i, --include)
messageYesCommit message (-m, --message)
noGpgSignNoDo not GPG sign commit (--no-gpg-sign)
noStatusNoDo not include status in commit message template (--no-status)
noVerifyNoBypass pre-commit and commit-msg hooks (-n, --no-verify)
onlyNoCommit only specified paths (-o, --only)
pathspecNoLimit commit to specified paths
quietNoSuppress commit summary message (-q, --quiet)
reeditMessageNoLike reuseMessage but invoke editor (-c, --reedit-message)
repoPathYesAbsolute path to the git repository
reuseMessageNoReuse message from existing commit (-C, --reuse-message)
squashNoCreate squash commit for specified commit (--squash)
trailersNoAdd trailers to commit message (--trailer)
verboseNoShow unified diff of changes (-v, --verbose)

Implementation Reference

  • The tool handler function that performs the git commit using simpleGit, checks if it's a repo, and returns success or error.
    readonly #handle: ToolCallback<typeof GIT_COMMIT_INPUT_SCHEMA> = async (input) => {
    	const sg = simpleGit(input.repoPath);
    
    	const isRepo = await sg.checkIsRepo();
    	if (!isRepo) {
    		return {
    			isError: true,
    			content: [
    				{
    					type: 'text',
    					text: 'Not a git repository',
    				},
    			],
    		};
    	}
    
    	const result = await sg.commit(input.message, input.pathspec, this.inputToOptions(input));
    
    	return {
    		content: [
    			{
    				type: 'text',
    				text: `Changes committed successfully.`,
    			},
    			{
    				type: 'text',
    				text: JSON.stringify(result),
    			},
    		],
    	};
    };
  • Zod input schema defining all parameters for the git commit tool.
    export const GIT_COMMIT_INPUT_SCHEMA = {
    	repoPath: z.string().describe('Absolute path to the git repository'),
    	message: z.string().describe('Commit message (-m, --message)'),
    	all: z.boolean().optional().describe('Automatically stage modified and deleted files (-a, --all)'),
    	reuseMessage: z.string().optional().describe('Reuse message from existing commit (-C, --reuse-message)'),
    	reeditMessage: z.string().optional().describe('Like reuseMessage but invoke editor (-c, --reedit-message)'),
    	fixup: z.string().optional().describe('Create fixup commit for specified commit (--fixup)'),
    	squash: z.string().optional().describe('Create squash commit for specified commit (--squash)'),
    	file: z.string().optional().describe('Read commit message from file (-F, --file)'),
    	author: z.string().optional().describe('Override author (--author)'),
    	date: z.string().optional().describe('Override author date (--date)'),
    	amend: z.boolean().optional().describe('Amend the previous commit (--amend)'),
    	allowEmpty: z.boolean().optional().describe('Allow empty commits (--allow-empty)'),
    	allowEmptyMessage: z.boolean().optional().describe('Allow empty commit messages (--allow-empty-message)'),
    	noVerify: z.boolean().optional().describe('Bypass pre-commit and commit-msg hooks (-n, --no-verify)'),
    	verbose: z.boolean().optional().describe('Show unified diff of changes (-v, --verbose)'),
    	quiet: z.boolean().optional().describe('Suppress commit summary message (-q, --quiet)'),
    	dryRun: z.boolean().optional().describe('Show what would be committed (--dry-run)'),
    	cleanup: z
    		.enum(['strip', 'whitespace', 'verbatim', 'scissors', 'default'])
    		.optional()
    		.describe('Cleanup mode (--cleanup)'),
    	noStatus: z.boolean().optional().describe('Do not include status in commit message template (--no-status)'),
    	include: z.boolean().optional().describe('Include given paths in addition to index (-i, --include)'),
    	only: z.boolean().optional().describe('Commit only specified paths (-o, --only)'),
    	pathspec: z.array(z.string()).optional().describe('Limit commit to specified paths'),
    	gpgSign: z.union([z.boolean(), z.string()]).optional().describe('GPG sign commit (-S, --gpg-sign)'),
    	noGpgSign: z.boolean().optional().describe('Do not GPG sign commit (--no-gpg-sign)'),
    	trailers: z.array(z.string()).optional().describe('Add trailers to commit message (--trailer)'),
    };
  • Register method of GitCommitTool class that registers the 'commit' tool with the MCP server.
    register(srv: McpServer) {
    	srv.registerTool(this.name, this.config, this.#handle);
    }
  • Instantiation of GitCommitTool and call to its register method in the main server setup.
    new GitCommitTool().register(server);
  • Helper method that transforms validated input parameters into simple-git Options object.
    public inputToOptions(input: z.infer<z.ZodObject<typeof GIT_COMMIT_INPUT_SCHEMA>>) {
    	const options: Options = {};
    
    	if (input.all) {
    		options['--all'] = null;
    	}
    
    	if (input.reuseMessage) {
    		options['--reuse-message'] = input.reuseMessage;
    	}
    
    	if (input.reeditMessage) {
    		options['--reedit-message'] = input.reeditMessage;
    	}
    
    	if (input.fixup) {
    		options['--fixup'] = input.fixup;
    	}
    
    	if (input.squash) {
    		options['--squash'] = input.squash;
    	}
    
    	if (input.file) {
    		options['--file'] = input.file;
    	}
    
    	if (input.author) {
    		options['--author'] = input.author;
    	}
    
    	if (input.date) {
    		options['--date'] = input.date;
    	}
    
    	if (input.amend) {
    		options['--amend'] = null;
    	}
    
    	if (input.allowEmpty) {
    		options['--allow-empty'] = null;
    	}
    
    	if (input.allowEmptyMessage) {
    		options['--allow-empty-message'] = null;
    	}
    
    	if (input.noVerify) {
    		options['--no-verify'] = null;
    	}
    
    	if (input.verbose) {
    		options['--verbose'] = null;
    	}
    
    	if (input.quiet) {
    		options['--quiet'] = null;
    	}
    
    	if (input.dryRun) {
    		options['--dry-run'] = null;
    	}
    
    	if (input.cleanup) {
    		options['--cleanup'] = input.cleanup;
    	}
    
    	if (input.noStatus) {
    		options['--no-status'] = null;
    	}
    
    	if (input.include) {
    		options['--include'] = null;
    	}
    
    	if (input.only) {
    		options['--only'] = null;
    	}
    
    	if (input.gpgSign !== undefined) {
    		if (typeof input.gpgSign === 'boolean') {
    			if (input.gpgSign) {
    				options['--gpg-sign'] = null;
    			} else {
    				options['--no-gpg-sign'] = null;
    			}
    		} else {
    			options['--gpg-sign'] = input.gpgSign;
    		}
    	}
    
    	if (input.noGpgSign) {
    		options['--no-gpg-sign'] = null;
    	}
    
    	if (input.trailers && input.trailers.length > 0) {
    		// For multiple trailers, we can use an array of values
    		options['--trailer'] = input.trailers;
    	}
    
    	return options;
    }
Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ver0-project/mcps'

If you have feedback or need assistance with the MCP directory API, please join our Discord server