Home

Awesome

<h3 align="center">

bc-gradient

better commits is enabled downloads discord

</h3> <p align="center"> A CLI for writing better commits, following the conventional commits specification. </p>

https://github.com/Everduin94/better-commits/assets/14320878/8fb15d46-17c4-4e5d-80d9-79abe0a2a00a

โœจ Features

As a side-effect of formatting messages

๐Ÿ“ฆ Installation

npm install -g better-commits

๐Ÿš€ Usage

When you're ready to commit. To run the CLI in your terminal:

better-commits
# or
npx better-commits

It will prompt a series of questions. These prompts will build a commit message, which you can preview, before confirming the commit. Some of the values in these prompts will be infered by your branch name and auto populated. You can adjust this in your .better-commits.json configuration file.

To better understand these prompts and their intention, read Conventional Commits Summary

โš™๏ธ Configuration

Global

Your first time running better-commits, a default config will be generated in your $HOME directory, named .better-commits.json

Repository

To create a repository-specific config, navigate to the root of your project.

Options

Better-commits (& better-branch) are highly flexible with sane defaults. These options allow you specify whats best for your workflow.

[!NOTE]<br> All properties are optional and can be removed from the config. It will be replaced by the default at run-time.

๐Ÿ’ซ Default JSON Config

<details open> <summary>Expand / Collapse</summary>
{
  "check_status": true,
  "commit_type": {
    "enable": true,
    "initial_value": "feat",
    "max_items": Infinity,
    "infer_type_from_branch": true,
    "append_emoji_to_label": false,
    "append_emoji_to_commit": false,
    "options": [
      {
        "value": "feat",
        "label": "feat",
        "hint": "A new feature",
        "emoji": "โœจ",
        "trailer": "Changelog: feature"
      },
      {
        "value": "fix",
        "label": "fix",
        "hint": "A bug fix",
        "emoji": "๐Ÿ›",
        "trailer": "Changelog: fix"
      },
      {
        "value": "docs",
        "label": "docs",
        "hint": "Documentation only changes",
        "emoji": "๐Ÿ“š",
        "trailer": "Changelog: documentation"
      },
      {
        "value": "refactor",
        "label": "refactor",
        "hint": "A code change that neither fixes a bug nor adds a feature",
        "emoji": "๐Ÿ”จ",
        "trailer": "Changelog: refactor"
      },
      {
        "value": "perf",
        "label": "perf",
        "hint": "A code change that improves performance",
        "emoji": "๐Ÿš€",
        "trailer": "Changelog: performance"
      },
      {
        "value": "test",
        "label": "test",
        "hint": "Adding missing tests or correcting existing tests",
        "emoji": "๐Ÿšจ",
        "trailer": "Changelog: test"
      },
      {
        "value": "build",
        "label": "build",
        "hint": "Changes that affect the build system or external dependencies",
        "emoji": "๐Ÿšง",
        "trailer": "Changelog: build"
      },
      {
        "value": "ci",
        "label": "ci",
        "hint": "Changes to our CI configuration files and scripts",
        "emoji": "๐Ÿค–",
        "trailer": "Changelog: ci"
      },
      {
        "value": "chore",
        "label": "chore",
        "hint": "Other changes that do not modify src or test files",
        "emoji": "๐Ÿงน",
        "trailer": "Changelog: chore"
      },
      {
        "value": "",
        "label": "none"
      }
    ]
  },
  "commit_scope": {
    "enable": true,
    "custom_scope": false,
    "initial_value": "app",
    "max_items": Infinity
    "options": [
      {
        "value": "app",
        "label": "app"
      },
      {
        "value": "shared",
        "label": "shared"
      },
      {
        "value": "server",
        "label": "server"
      },
      {
        "value": "tools",
        "label": "tools"
      },
      {
        "value": "",
        "label": "none"
      }
    ]
  },
  "check_ticket": {
    "infer_ticket": true,
    "confirm_ticket": true,
    "add_to_title": true,
    "append_hashtag": false,
    "prepend_hashtag": "Never",
    "surround": "",
    "title_position": "start"
  },
  "commit_title": {
    "max_size": 70
  },
  "commit_body": {
    "enable": true,
    "required": false
  },
  "commit_footer": {
    "enable": true,
    "initial_value": [],
    "options": ["closes", "trailer", "breaking-change", "deprecated", "custom"]
  },
  "breaking_change": {
    "add_exclamation_to_title": true
  },
  "confirm_commit": true,
  "confirm_with_editor": false,
  "print_commit_output": true,
  "branch_pre_commands": [],
  "branch_post_commands": [],
  "worktree_pre_commands": [],
  "worktree_post_commands": [],
  "branch_user": {
    "enable": true,
    "required": false,
    "separator": "/"
  },
  "branch_type": {
    "enable": true,
    "separator": "/"
  },
  "branch_version": {
    "enable": false,
    "required": false,
    "separator": "/"
  },
  "branch_ticket": {
    "enable": true,
    "required": false,
    "separator": "-"
  },
  "branch_description": {
    "max_length": 70,
    "separator": ""
  },
  "branch_action_default": "branch",
  "branch_order": ["user", "version", "type", "ticket", "description"],
  "enable_worktrees": true,
  "overrides": {
    "shell": "/bin/sh"
  }
}
</details>

[!NOTE]<br> Some properties allow a set of specifc string values

๐Ÿ”ญ Config File Explanations

Expand to see explanations and possible values

<details> <summary>Expand / Collapse</summary>

. refers to nesting. i.e. if a property is commit_type.enable then expect in the config for it to be:

"commit_type": {
  "enable": true
}
PropertyDescription
check_statusIf true run interactive git status
commit_type.enableIf true include commit type
commit_type.initial_valueInitial selection of commit type
commit_type.max_itemsMaximum number of type displayed on the screen
commit_type.infer_type_from_branchIf true infer type from branch name
commit_type.append_emoji_to_labelIf true append emoji to prompt
commit_type.append_emoji_to_commitIf true append emoji to commit
commit_type.options.valueCommit type prompt value
commit_type.options.labelCommit type prompt label
commit_type.options.hintCommit type inline hint (like this)
commit_type.options.emojiCommit type emoji
commit_type.options.trailerCommit type trailer
commit_scope.enableIf true include commit scope
commit_scope.custom_scopeIf true allow custom scope at run-time
commit_scope.initial_valueDefault commit scope selected
commit_scope.max_itemsMaximum number of scope displayed on the screen
commit_scope.options.valueCommit scope value
commit_scope.options.labelCommit scope label
check_ticket.infer_ticketIf true infer ticket from branch name
check_ticket.confirm_ticketIf true manually confirm inference
check_ticket.add_to_titleIf true add ticket to title
check_ticket.append_hashtagDeprecated: see prepend_hashtag
check_ticket.prepend_hashtag"Never" (default), "Prompt", or "Always"
check_ticket.title_position"start" (of description) (default), "end", "before-colon", "beginning" (of the entire commit title)
check_ticket.surround"" (default), "[]", "()", "{}" - Wraps ticket in title
commit_title.max_sizeMax size of title including scope, type, etc...
commit_body.enableIf true include body
commit_body.requiredIf true body is required
commit_footer.enableIf true include footer
commit_footer.initial_valueInitial values selected in footer
commit_footer.optionsFooter options
breaking_change.add_exclamation_to_titleIf true adds exclamation mark to title for breaking changes
confirm_commitIf true manually confirm commit at end
confirm_with_editorConfirm / Edit commit with $GIT_EDITOR / $EDITOR
print_commit_outputIf true pretty print commit preview
overrides.shellOverride default shell, useful for windows users

Branch configuration (same config file, split for readability)

PropertyDescription
branch_pre_commandsArray of shell commands to run before branching
branch_post_commandsArray of shell commands to run after branching
worktree_pre_commandsArray of shell commands to run before creating worktree
worktree_post_commandsArray of shell commands to run after creating worktree
branch_user.enableIf enabled include user name
branch_user.requiredIf enabled require user name
branch_user.separatorBranch delimeter - "/" (default), "-", "_"
branch_type.enableIf enabled include type
branch_type.separatorBranch delimeter - "/" (default), "-", "_"
branch_ticket.enableIf enabled include ticket
branch_ticket.requiredIf enabled require ticket
branch_ticket.separatorBranch delimeter - "/", "-" (default), "_"
branch_description.max_lengthMax length branch name
branch_description.separatorBranch delimeter - "" (default), "/", "-", "_"
branch_version.enableIf enabled include version
branch_version.requiredIf enabled require version
branch_version.separatorBranch delimeter - "", "/" (default), "-", "_"
branch_orderOrder of branch name values (doesn't effect prompt order)
branch_action_default"branch" or "worktree"
enable_worktreesIf false, always default to branch action
</details>

๐Ÿ”Ž Inference

better-commits will attempt to infer the ticket/issue and the commit-type from your branch name. It will auto populate the corresponding field if found.

Ticket / Issue-Number

Commit Type

๐ŸŒณ Better Branch

[!NOTE]<br> Using better-branch with better-commits can supercharge your git workflow. Make sure to try it out!

Better branch is a secondary feature that works with better commits

To run the CLI in your terminal:

better-branch

Worktree Support

better-branch will prompt for Branch or Worktree. Creating a Worktree with better-branch is a great way to create worktrees while maintaining consistent branch naming conventions.

The worktree flow creates a folder/worktree with your branch description and a git branch inside with your full branch name.

[!NOTE]<br> Creating a worktree named everduin94/feat/TAC-123-add-worktrees with the native git command would create a nested folder for each /. better-branch removes the hassle by creating 1 folder while still using the full name for the branch.

Pre/Post Branch Checkout Hooks

Optionally configure pre and post checkout commands, for example:

See branch_pre_commands and branch_post_commands in default config. (or worktree_pre_commands and worktree_post_commands for creating worktrees)

๐ŸŒŒ Mildly Interesting

Building / Versioning

better-commits works with Semantic Release

Github

If you use better-commits to create your first commit on a new branch

If you're using Github issues to track your work, and select the closes footer option when writing your commit. Github will automatically link and close that issue when your pr is merged

Changelogs

better-commits can append a commit trailer per commit type. This allows you to automate change logs with tools like Gitlab.

Fun Facts

better-commits uses native git commands under the hood. So any hooks, tools, or staging should work as if it was a normal commit.

Setting confirm_with_editor=true will allow you to edit/confirm a commit with your editor.

[!NOTE]<br> Enjoy learning, open source technology, and note-taking? Join our Discord!

You can add this badge to your repository to display that you're using a better-commits repository config

MarkdownResult
[![better commits is enabled](https://img.shields.io/badge/better--commits-enabled?style=for-the-badge&logo=git&color=a6e3a1&logoColor=D9E0EE&labelColor=302D41)](https://github.com/Everduin94/better-commits)better commits is enabled

๐ŸชŸ Troubleshooting Windows

Git Bash

TTY initialization failed: uv_tty_init returned EBADF (bad file descriptor). This may happen because you're running something like git-bash on Windows. Try another terminal/command-prompt or winpty to see if its still an issue.

Multi-line

If your are having issues with multilines for commits on windows, you can override the shell via your .better-commits.json config.

Example

"overrides": {
   "shell": "c:\\Program Files\\Git\\bin\\bash.exe"
}
<h1 align="center">๐ŸŒŸ Sponsors</h1> <h3 align="center">

flotes-g-2

Markdown Notetaking - Built for Learning

</h3>