Chapter 45: Git Workflow
- How to structure branches and commits for a team project
- How to write good commit messages
- How to use feature branches and code review
- How to resolve merge conflicts
- The release and tagging strategy
- How to set up CI for the kernel
45.1 Branch Strategy
We follow a simplified trunk-based development model with short-lived feature branches:
| Branch | Purpose |
|---|---|
main | Stable, reviewed, tested. Protected branch. |
feature/<name> | Feature branches. One per developer per feature. Short-lived (1-3 days). |
fix/<name> | Bug fix branches. Same rules as feature branches. |
release/v* | Release branches. Created at each milestone (v0.1, v0.2, etc.). |
Rules:
- Never commit directly to
main - Feature branches are merged via pull request with at least one review
- Delete feature branches after merging
- Keep branches up to date with
main(rebase, not merge)
45.2 Commit Messages
Every commit message follows the conventional format:
component: short summary (50 chars or less)
Detailed explanation of what changed and why. Wrap at 72
characters. Explain the motivation, not just the change.
If the change fixes a bug, reference the issue number:
Fixes: #42
Signed-off-by: Your Name <email@example.com>
Examples of good commit messages:
uart: fix character drop on fast input
The UART RX interrupt handler was not reading the data register
fast enough when characters arrived back-to-back. The fix reads
all available characters in a loop before returning from the
handler, using the RX FIFO level status bit.
Fixes: #18
Signed-off-by: Alice <alice@example.com>
mm: add physical page allocator
Implements a buddy allocator for physical memory with orders
0 through 10. Supports allocation and freeing of individual
pages and contiguous ranges. No virtual memory mapping yet;
the allocator returns physical addresses only.
Signed-off-by: Bob <bob@example.com>
Commit message rules:
- First line must be 50 characters or fewer
- First line uses past tense ("added", "fixed", not "adds", "fixes")
- Include the subsystem prefix (e.g., "uart:", "mm:", "sched:")
- Blank line between subject and body
- Body wraps at 72 columns
- Explain WHY, not just WHAT
- Reference issue numbers when applicable
45.3 Feature Branch Workflow
# Start a new feature
git checkout main
git pull origin main
git checkout -b feature/page-cache
# Work on the feature
git add kernel/mm/page_cache.c kernel/include/mm/page_cache.h
git commit -m "mm: add page cache data structure"
git add kernel/mm/page_cache.c
git commit -m "mm: implement page cache lookup and insert"
# Keep branch up to date
git fetch origin
git rebase origin/main
# If conflicts occur:
# - Resolve them in your editor
# - git add <resolved files>
# - git rebase --continue
# Push and create a pull request
git push -u origin feature/page-cache
# On GitHub/GitLab: create PR, request review
45.4 Code Review Checklist
Before requesting review, verify:
- Code compiles without warnings (
-Wall -Wextra -Werror) - clang-format produces no diffs
- All existing tests pass
- New code has corresponding tests
- No dead code, commented-out code, or debugging prints left in
- Error paths are handled (no unchecked kmalloc return values)
- No magic numbers: use named constants or macros
- Memory allocations have matching frees (no leaks)
- Lock ordering is consistent (no deadlock risk)
45.5 Merging Strategy
We use squash merge for feature branches. All commits from the feature branch are combined into a single commit on main:
# Merge (via GitHub/GitLab UI, or command line):
git checkout main
git merge --squash feature/page-cache
git commit -m "mm: add page cache subsystem"
git push origin main
# Delete the feature branch (local and remote):
git branch -d feature/page-cache
git push origin --delete feature/page-cache
Squash merging keeps the main branch history clean and linear, while allowing detailed commits during development. Each commit on main represents a complete, reviewed feature.
45.6 Tagging and Releases
Releases are tagged with semantic versioning:
# Tag a release
git tag -a v0.1.0 -m "v0.1.0: Boots to shell with UART support"
git push origin v0.1.0
# Version format: vMAJOR.MINOR.PATCH
# MAJOR: breaking changes
# MINOR: new features (backward compatible)
# PATCH: bug fixes (backward compatible)
45.7 CI Pipeline
Our CI pipeline (GitHub Actions) runs on every push to a feature branch and on every PR:
# .github/workflows/kernel.yml
name: Kernel CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install toolchain
run: sudo apt install gcc-aarch64-linux-gnu qemu-system-arm
- name: Build kernel
run: make
- name: Run host tests
run: make test-host
- name: Run QEMU tests
run: make test-qemu
- name: Check formatting
run: clang-format --dry-run --Werror kernel/**/*.c kernel/**/*.h
45.8 Our Workflow Summary
| Step | Action |
|---|---|
| 1 | Create a feature branch from main |
| 2 | Commit changes with descriptive messages |
| 3 | Push branch and create a pull request |
| 4 | Request review from at least one teammate |
| 5 | Address review feedback in new commits |
| 6 | Squash merge to main after approval |
| 7 | Delete the feature branch |
| 8 | Tag releases at milestones |
45.9 Exercises
Exercise 1: Simulate a Merge Conflict
Create two branches that modify the same line in a file. Practice resolving the conflict manually and with a merge tool.
Exercise 2: Squash Commits
Make three related commits on a branch, then squash them into one using git rebase -i. Verify the commit history is clean.
Exercise 3: Set Up CI
Create a GitHub Actions workflow (or similar) for the kernel that builds and runs the host-based unit tests on every push.
45.10 Summary
A consistent git workflow keeps the team organized and the codebase stable. Feature branches isolate work in progress. Meaningful commit messages document the history. Code review ensures quality before merging. Squash merging keeps the main branch linear. CI automation catches regressions early. Following this workflow allows five developers to collaborate on the kernel without stepping on each other's work.