Skip to main content
Commits are the building blocks of your Git history. This guide covers everything from basic commits to advanced operations like amending, fixups, and custom authorship.

Basic Commits

Simple Commit

Create a commit with staged changes:
import { add, commit } from 'usegit';

// Stage files
await add('.');

// Commit with a message
await commit('feat: add user profile page');

Commit with Description

Add a detailed description for context:
import { commit } from 'usegit';

await commit(
  'fix: resolve memory leak in event listeners',
  'The component was not properly cleaning up event listeners on unmount, causing memory to accumulate over time. This adds proper cleanup in the useEffect hook.'
);
Use descriptive commit messages that explain the “why” not just the “what”. Your future self (and teammates) will thank you!

Commit All Changes

Commit Tracked Files

Stage and commit all tracked files in one operation:
import { commitAll } from 'usegit';

// Stage and commit all modified tracked files
await commitAll('chore: update configuration files');

// With description
await commitAll(
  'refactor: simplify authentication flow',
  'Removes unnecessary abstraction layers and consolidates auth logic into a single service'
);
commitAll() only stages modified tracked files. It does not include new untracked files. Use add() first if you need to include new files.

Amending Commits

Amend Last Commit

Modify the most recent commit:
import { add, commitAmend } from 'usegit';

// Make additional changes
await add(['src/index.ts']);

// Amend the previous commit
await commitAmend('feat: add user profile page with avatar support');

Amend Without Changing Message

Add files to the last commit without changing the message:
import { add, commitAmend } from 'usegit';

// Stage forgotten files
await add(['tests/profile.test.ts']);

// Amend without providing a new message
await commitAmend();

Using Commit Flags

Amend using the base commit() function with flags:
import { commit } from 'usegit';

// Amend with no-edit flag to keep the message
await commit(undefined, {
  flags: ['--amend', '--no-edit']
});

Commit with Signoff

Add Signed-off-by Trailer

Create commits with a Signed-off-by trailer (common in open source):
import { commitSignoff } from 'usegit';

// Commit with automatic signoff
await commitSignoff('docs: update installation guide');

// With description
await commitSignoff(
  'feat: implement OAuth2 authentication',
  'Adds support for OAuth2 flow with Google and GitHub providers'
);
This produces a commit message like:
feat: implement OAuth2 authentication

Adds support for OAuth2 flow with Google and GitHub providers

Signed-off-by: Your Name <[email protected]>

Custom Author Commits

Commit with Different Author

Specify a different author for a commit:
import { commitWithAuthor } from 'usegit';

// Commit with custom author
await commitWithAuthor(
  'feat: initial code import',
  'Alice Johnson <[email protected]>'
);

// With description
await commitWithAuthor(
  'fix: resolve edge case in validation',
  'Bob Smith <[email protected]>',
  'This fix handles the case where input is an empty array'
);

Using Author Option

Alternatively, use the --author option:
import { commit } from 'usegit';

await commit(
  'docs: add API documentation',
  'Complete API reference with examples',
  {
    '--author': 'Jane Doe <[email protected]>'
  }
);

Fixup Commits

Create Fixup Commit

Create a commit marked for autosquashing during rebase:
import { commitFixup } from 'usegit';

// Create a fixup commit for a specific commit
await commitFixup('abc1234');
Fixup commits are designed to be automatically squashed during an interactive rebase with the --autosquash option. They’re useful for fixing up commits in a feature branch before merging.

Advanced Commit Options

Empty Commits

Create a commit without any changes:
import { commitEmpty } from 'usegit';

// Useful for triggering CI or marking milestones
await commitEmpty('chore: trigger CI rebuild');

Commit with GPG Signing

Sign commits with GPG:
import { commit } from 'usegit';

// Sign with default GPG key
await commit('feat: add encryption', {
  '--gpg-sign': true
});

// Sign with specific key
await commit('feat: secure payment flow', {
  '--gpg-sign': 'KEYID123456'
});

Commit with Custom Date

Override the commit date:
import { commit } from 'usegit';

await commit('feat: backdate commit', {
  '--date': '2024-01-01'
});

// Relative dates
await commit('fix: apply yesterday\'s fix', {
  '--date': 'yesterday'
});

Commit Message Patterns

Conventional Commits

Follow the Conventional Commits specification:
import { commit } from 'usegit';

// Feature
await commit('feat(auth): add password reset flow');

// Bug fix
await commit('fix(api): handle null response from server');

// Breaking change
await commit(
  'feat(api)!: redesign authentication API',
  'BREAKING CHANGE: The /auth endpoint now requires API version header'
);

// Other types
await commit('docs: update README with examples');
await commit('chore: upgrade dependencies');
await commit('refactor: simplify error handling');
await commit('test: add integration tests for checkout');
await commit('perf: optimize image loading');

Real-World Workflows

Interactive Commit Workflow

A complete workflow with user feedback:
1

Check what's changed

import { status, diff } from 'usegit';

const changes = await status();
console.log('Changed files:', changes);

const diffOutput = await diff();
console.log('Detailed changes:', diffOutput);
2

Stage selectively

import { add } from 'usegit';

// Stage related changes together
await add(['src/auth/', 'tests/auth/']);
3

Review staged changes

import { diffStaged } from 'usegit';

const staged = await diffStaged();
console.log('About to commit:', staged);
4

Create the commit

import { commit } from 'usegit';

await commit(
  'feat(auth): implement JWT token refresh',
  'Adds automatic token refresh when tokens are close to expiration. Includes retry logic and error handling.'
);

Fixing Mistakes

Common scenarios for fixing commit mistakes:
import { add, commit, commitAmend } from 'usegit';

// Scenario 1: Forgot to add a file
await commit('feat: add payment integration');
// Oops, forgot to add the test file!
await add(['tests/payment.test.ts']);
await commitAmend('feat: add payment integration'); // Same message, adds the file

// Scenario 2: Typo in commit message
await commit('feat: add paymet integration'); // Typo!
await commitAmend('feat: add payment integration'); // Fixed

// Scenario 3: Need to update the description
await commitAmend(
  'feat: add payment integration',
  'Integrates Stripe API for credit card processing. Includes webhook handling for payment events.'
);

Batch Commits

Commit multiple logical changes separately:
import { add, commit } from 'usegit';

async function commitChanges() {
  // Commit feature code
  await add(['src/features/']);
  await commit(
    'feat: add user notification system',
    'Implements real-time notifications using WebSockets'
  );

  // Commit tests separately
  await add(['tests/notifications/']);
  await commit('test: add notification system tests');

  // Commit documentation
  await add(['docs/notifications.md']);
  await commit('docs: document notification API');

  console.log('All changes committed in logical units');
}

commitChanges();

Commit with Options

No Verify (Skip Hooks)

Skip pre-commit and commit-msg hooks:
import { commit } from 'usegit';

// Bypass hooks (use cautiously!)
await commit('wip: work in progress', {
  flags: ['--no-verify']
});
Using --no-verify skips commit hooks that may enforce code quality standards. Use this sparingly and only when you have a good reason.

Quiet Mode

Suppress commit summary output:
import { commit } from 'usegit';

await commit('chore: routine update', {
  flags: ['--quiet']
});

Complete Example

Here’s a comprehensive example showing various commit operations:
import { 
  add,
  commit,
  commitAll,
  commitAmend,
  commitSignoff,
  commitWithAuthor,
  status,
  diffStaged,
  isCleanWorkingTree
} from 'usegit';

async function commitWorkflow() {
  // Check initial status
  console.log('Status:', await status());

  // Stage and commit feature work
  await add(['src/features/dashboard.ts']);
  await commit(
    'feat(dashboard): add analytics widgets',
    'Implements real-time analytics display with charts'
  );

  // Realize we need to add tests
  await add(['tests/dashboard.test.ts']);
  await commitAmend(
    'feat(dashboard): add analytics widgets with tests',
    'Implements real-time analytics display with charts. Includes comprehensive unit tests.'
  );

  // Quick doc update
  await add(['README.md']);
  await commit('docs: update dashboard documentation');

  // Import some code from a colleague
  await add(['src/utils/analytics.ts']);
  await commitWithAuthor(
    'feat(utils): add analytics helper functions',
    'Sarah Chen <[email protected]>',
    'Helper functions for processing analytics data'
  );

  // Commit everything else with signoff
  await add('.');
  const isClean = await isCleanWorkingTree();
  if (!isClean) {
    await commitSignoff(
      'chore: update configuration and dependencies',
      'Brings all configs up to date with latest standards'
    );
  }

  console.log('All commits created successfully!');
}

commitWorkflow();

Next Steps

Diff and Status

Learn to check status and view diffs

Basic Workflow

Review the fundamental Git workflow

Build docs developers (and LLMs) love