# How Version Control is Managed in the Brush Project: A Complete Guide

> Discover how the Brush project manages version control using Git, semantic versioning in Cargo.toml, branches, and CI/CD for quality releases.

- Repository: [Arthur Brussee/brush](https://github.com/ArthurBrussee/brush)
- Tags: how-to-guide
- Published: 2026-05-14

---

**The Brush project uses a Git-centric workflow hosted on GitHub that combines semantic versioning in [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml), branch-based development, and automated CI/CD pipelines to ensure code quality and reproducible releases.**

Brush is an open-source Rust project developed by Arthur Brussee that follows modern version control best practices. Its workflow integrates Git tags, GitHub Actions, and the Rust ecosystem's tooling to maintain a clean commit history while automating builds and releases across multiple platforms.

## Repository Structure and Versioning Strategy

The foundation of Brush's version control system rests on the relationship between Git tags and the workspace configuration defined in [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml).

### Cargo.toml as the Source of Truth

In the root [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml) file, the `version` field serves as the canonical reference for the current release. As of the latest commit, the workspace version is set to `0.3.0`:

```toml
[workspace]
version = "0.3.0"

```

This version must match the Git tag created during the release process. When the maintainer updates this field and pushes a corresponding tag, the release automation triggers automatically.

### Git Tag Conventions

Brush follows strict **semantic versioning** for its tags. The release workflow in [`.github/workflows/release.yml`](https://github.com/ArthurBrussee/brush/blob/main/.github/workflows/release.yml) specifically looks for tags matching the pattern `v<MAJOR>.<MINOR>.<PATCH>` (for example, `v0.3.0` or `v0.4.0`). Any tag not conforming to this format will not trigger the release pipeline, ensuring that only properly versioned commits become official releases.

## Continuous Integration Workflow

Every code contribution undergoes rigorous validation through the CI pipeline defined in [`.github/workflows/ci.yml`](https://github.com/ArthurBrussee/brush/blob/main/.github/workflows/ci.yml).

### CI Pipeline Details

The workflow runs on every push and pull request across Ubuntu, macOS, and Windows runners. According to the source code, the validation suite includes:

- **Formatting checks** via `cargo fmt`
- **Linting** via `cargo clippy`
- **Dependency auditing** via `cargo deny`
- **Documentation builds** to ensure examples compile
- **Compilation checks** via `cargo check`

This multi-platform approach guarantees that code merges only occur after passing all quality gates, preventing platform-specific regressions from entering the main branch.

## Automated Release Process

When a version tag is pushed, the [`.github/workflows/release.yml`](https://github.com/ArthurBrussee/brush/blob/main/.github/workflows/release.yml) workflow executes `cargo-dist` to handle the entire release process without manual intervention.

### How Releases Are Triggered

The automation activates when a tag matching the semantic version pattern arrives at the repository. The workflow then performs the following actions:

1. Builds binaries for every supported target platform
2. Packages artifacts according to the configuration in [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml)
3. Uploads build artifacts to GitHub
4. Creates a GitHub Release with automatically generated release notes

This ensures that every release is **reproducible** and **auditable**, with a direct one-to-one mapping between a Git commit (identified by its tag) and the published binaries.

## Developer Workflow

Contributors follow a straightforward branching model that keeps the main branch stable while allowing parallel feature development.

### Branching Strategy

Feature work occurs on short-lived branches prefixed according to convention:

```bash
git checkout -b feature/fast-rasterizer

```

Or for bug fixes:

```bash
git checkout -b bugfix/memory-leak

```

Once the work is complete, developers open pull requests through the GitHub interface. The CI workflow runs automatically on these PRs, providing immediate feedback on code quality before human review.

### Making Releases

Maintainers follow a specific sequence to publish new versions. First, update the version in [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml):

```bash
sed -i 's/version = "0.3.0"/version = "0.4.0"/' Cargo.toml

```

Then commit the change, create an annotated tag matching the new version, and push:

```bash
git commit -am "Bump version to 0.4.0"
git tag -a v0.4.0 -m "Release 0.4.0"
git push origin main --tags

```

Once the `v0.4.0` tag reaches GitHub, the release workflow automatically builds and publishes all platform binaries.

### Verifying Tags Locally

To inspect the version history, fetch the latest tags from the remote and list them in version-sorted order:

```bash
git fetch --tags
git tag -l --sort=-v:refname | head -n5

```

## Summary

- **Git tags drive releases**: The [`.github/workflows/release.yml`](https://github.com/ArthurBrussee/brush/blob/main/.github/workflows/release.yml) file listens for semantic version tags (`vX.Y.Z`) to trigger automated builds.
- **Cargo.toml is the version source**: The workspace version in [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml) (currently `0.3.0`) must match the Git tag for consistency.
- **CI runs on every change**: The [`.github/workflows/ci.yml`](https://github.com/ArthurBrussee/brush/blob/main/.github/workflows/ci.yml) workflow enforces code quality through `cargo fmt`, `cargo clippy`, and `cargo deny` on every push and pull request.
- **Feature branches isolate work**: Development occurs on prefixed branches (`feature/`, `bugfix/`) that merge via GitHub pull requests.
- **cargo-dist handles distribution**: Release automation uses `cargo-dist` to generate cross-platform binaries and create GitHub Releases.

## Frequently Asked Questions

### How does Brush determine when to create a new release?

A new release triggers when a maintainer pushes a Git tag matching the semantic versioning pattern `v<MAJOR>.<MINOR>.<PATCH>`. The tag must correspond to the version declared in the root [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml) file. This push event activates the release workflow in [`.github/workflows/release.yml`](https://github.com/ArthurBrussee/brush/blob/main/.github/workflows/release.yml), which then builds binaries and publishes the release.

### What checks must pass before code can be merged into the main branch?

Every pull request must pass the full CI suite defined in [`.github/workflows/ci.yml`](https://github.com/ArthurBrussee/brush/blob/main/.github/workflows/ci.yml). This includes formatting validation with `cargo fmt`, linting with `cargo clippy`, dependency auditing with `cargo deny`, and successful compilation checks. The workflow runs on Ubuntu, macOS, and Windows runners to ensure cross-platform compatibility.

### Why does the project use cargo-dist for releases instead of manual builds?

The `cargo-dist` tool automates the complex process of building binaries for multiple target platforms, packaging them, and creating consistent GitHub Releases. This eliminates human error in the build process, ensures reproducible artifacts from the tagged commit, and handles platform-specific packaging requirements automatically as configured in the release workflow.

### Where is the current version number stored in the Brush repository?

The canonical version number resides in the `[workspace]` section of the root [`Cargo.toml`](https://github.com/ArthurBrussee/brush/blob/main/Cargo.toml) file. Currently set to `0.3.0`, this value serves as the source of truth for the release automation. When preparing a release, maintainers update this field before creating the matching Git tag, ensuring the package metadata and version control tags remain synchronized.