Git mode builds documentation from Git branches or tags instead of folder copies. This is ideal for projects that already use release branches or release tags.
When to Use Git Mode
✅ Use Git Mode if:
- You already have release branches (e.g.,
release/1.0,release/2.0) - You publish stable release tags (e.g.,
v1.0.0,v1.1.0,v2.0.0) - You want versions tied to Git history
- You prefer not to duplicate content in folders
- Your CI/CD pipeline builds from branches
❌ Use Folder Mode if:
- You want simple, visible version directories
- You don't use release branches
- You're new to versioning
How It Works
┌─────────────────────────────────────────────────────────┐
│ Your Repo │
├─────────────────────────────────────────────────────────┤
│ main ──────────────────────────────► v3.0 (latest) │
│ │ │
│ └─ release/2.0 ──────────────────► v2.0 │
│ │ │
│ └─ release/1.0 ─────────────► v1.0 │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Bengal Build │
├─────────────────────────────────────────────────────────┤
│ 1. Discover branches/tags matching configuration │
│ 2. Create worktrees for each version │
│ 3. Build each version into a staging output │
│ 4. Merge outputs into single site │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Output Site │
├─────────────────────────────────────────────────────────┤
│ /docs/ ← from main (latest) │
│ /docs/2.0/ ← from release/2.0 │
│ /docs/1.0/ ← from release/1.0 │
└─────────────────────────────────────────────────────────┘
Bengal uses Git worktrees to check out each branch without affecting your working directory.
Configuration
Configuration works in bothbengal.yaml and bengal.tomlformats.
Basic Setup
# bengal.yaml (or bengal.toml)
versioning:
enabled: true
mode: git
git:
branches:
# Explicit branch
- name: main
latest: true
# Pattern matching
- pattern: "release/*"
strip_prefix: "release/"
default_branch: main
parallel_builds: 4
Pattern Matching
Match multiple branches with glob patterns:
git:
branches:
# Match release/1.0, release/2.0, etc.
- pattern: "release/*"
strip_prefix: "release/" # release/2.0 → version "2.0"
# Match v1.0.0, v2.0.0, etc.
- pattern: "v*"
# No strip_prefix → version "v1.0.0"
Using Tags
Build from Git tags instead of (or in addition to) branches:
git:
branches:
- name: main
latest: true
tags:
- pattern: "v*"
strip_prefix: "v" # v1.0.0 → version "1.0.0"
Latest + Previous Tags
Use this whenmainshould be the unversioned latest docs and the older docs
should come from the newest release tags:
versioning:
enabled: true
mode: git
sections:
- docs
git:
latest:
branch: main
id: main
label: Latest
previous:
source: tags
count: 3
pattern: "v*"
strip_prefix: "v"
sort: semver-desc
include_prereleases: false
cache_worktrees: true
aliases:
latest: main
If the repository has v0.3.2, v0.3.1, v0.3.0, and v0.4.0-rc.1,
Bengal buildsmain as /docs/and the three stable tags as
/docs/0.3.2/, /docs/0.3.1/, and /docs/0.3.0/. The prerelease tag is
skipped unlessinclude_prereleases: true.
source: tags, source: git-tags, and source: releases/tagsare equivalent.
They all select Git tags from the repository. Bengal does not call the GitHub
Releases API, so this mode also works for projects that tag releases without
creating GitHub release objects.
The current checkout's versioning config controls the whole build. Older tags can disable versioning or use older settings; Bengal overlays the current version list onto each worktree so old docs still build into the selected URL layout.
If your docs live in a subdirectory such assite/, run bengal build --all-versions from the repository root or pass --sourceto the repository
root. Bengal discovers the site subdirectory for each worktree and writes output
under that site's configuredoutput_dir.
Bengal's own docs site uses this mode: the live docs are built frommain, and
the previous docs are selected automatically from the newest stable release
tags.
Full Configuration Reference
versioning:
enabled: true
mode: git
git:
# Latest branch selector (optional shorthand for the latest branch)
latest:
branch: main
id: main
label: Latest
# Automatic previous-version selector (optional)
previous:
source: tags # Supports tags, git-tags, or releases/tags
count: 3 # Number of previous tags to include
pattern: "v*" # Glob for candidate tags
strip_prefix: "v" # v1.2.3 → version "1.2.3"
sort: semver-desc # or: name-desc
include_prereleases: false
# Branch patterns
branches:
- name: main # Explicit branch name
latest: true # This is the latest version
- pattern: "release/*" # Glob pattern
version_from: branch # How to extract version ID (see below)
strip_prefix: "release/"
latest: false
# version_from options:
# branch - Use branch name (default)
# tag - Use tag name
# <regex> - Custom regex pattern
# Tag patterns (optional)
tags:
- pattern: "v*"
strip_prefix: "v"
# Settings
default_branch: main # Fallback if no latest specified (default: "main")
cache_worktrees: true # Keep worktrees for faster rebuilds (default: true)
parallel_builds: 4 # Reserved for concurrent version builds
# Standard versioning options still apply
sections:
- docs
aliases:
latest: main
stable: "2.0"
Building
Build All Versions
# Discover and build all matching branches/tags
bengal build --all-versions
Output:
🔍 Discovering versions from git...
Found 3 versions to build
• main
• 2.0
• 1.0
📦 Building version main...
✅ Built 45 pages
📦 Building version 2.0...
✅ Built 42 pages
📦 Building version 1.0...
✅ Built 38 pages
✅ Built 3 versions
Build Specific Version
# Build only version 2.0
bengal build --build-version 2.0
Regular Build (Current Branch Only)
# Build current branch only
bengal build
Comparing Versions
Compare content between Git refs:
# Compare branches
bengal version diff --old-version main --new-version release/2.0 --git
# Output as markdown (for release notes)
bengal version diff --old-version main --new-version release/2.0 --git --output markdown
# Output as JSON (for automation)
bengal version diff --old-version main --new-version release/2.0 --git --output json
Example output:
📊 Version Diff: release/2.0 → main
Version diff: release/2.0 → main
Added: 3 pages
Removed: 1 pages
Modified: 12 pages
Unchanged: 28 pages
✨ Added pages:
+ docs/new-feature.md
+ docs/api/webhooks.md
+ docs/guide/advanced.md
🗑️ Removed pages:
- docs/deprecated-guide.md
📝 Modified pages:
~ docs/installation.md (45.2% changed)
~ docs/configuration.md (12.8% changed)
CI/CD Integration
GitHub Actions Example
# .github/workflows/docs.yml
name: Build Docs
on:
push:
branches:
- main
- 'release/*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for branches
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install Bengal
run: pip install bengal
- name: Build All Versions
run: bengal build --all-versions
- name: Deploy
# Pin to SHA for supply chain security (v3.9.3)
uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
GitLab CI Example
# .gitlab-ci.yml
build-docs:
image: python:3.14
script:
- pip install bengal
- bengal build --all-versions
artifacts:
paths:
- public/
Worktrees
Bengal uses Git worktrees to check out multiple branches simultaneously:
.bengal/
└── worktrees/
├── 2.0/ # Checked out from release/2.0
└── 1.0/ # Checked out from release/1.0
Caching Worktrees
By default, worktrees are cached for faster rebuilds:
git:
cache_worktrees: true # Reuse matching worktrees between builds
When a cached worktree already points at the expected commit, Bengal reuses it.
If the ref moved, Bengal refreshes that worktree before building.
Setcache_worktrees: falseto remove worktrees after the build.
Output Cleanup
bengal build --all-versionsalso tracks the version directories it manages.
When a later build selects fewer tags, Bengal removes stale version directories
from configured versioned sections before writing the new output. Cleanup is
conservative: it only removes version IDs from Bengal's previous version build
manifest or the generatedversions.json.
Manual Cleanup
# Remove cached worktrees
rm -rf .bengal/worktrees
git worktree prune
Troubleshooting
Branch Not Found
❌ Version 2.0 not found
Check that the branch exists:
git branch -a | grep release
Verify your pattern matches:
branches:
- pattern: "release/*" # Must match exactly
Worktree Errors
Failed to create worktree
Clean up stale worktrees:
git worktree prune
rm -rf .bengal/worktrees
Permission Errors
error: unable to create file: Permission denied
Ensure write access to the.bengal/directory:
chmod -R u+w .bengal/
If running in CI, ensure the checkout step has write permissions.
Slow Builds
Keep cached worktrees enabled so unchanged refs do not need a fresh checkout:
git:
cache_worktrees: true
An all-version build still runs the build once per selected version, so wall time scales with the number of versions and the size of the docs. Worktree caching avoids repeated checkouts, but it does not skip rendering a version once it is selected.
Next Steps
- Cross-Version Links — Link between versions
- Version Directives — Mark version-specific content
- Folder Mode — Alternative: folder-based versioning