Git Workflow and Versioning
Core Principle
Treat commits as verified save points with communicative messages - history
is for future readers (review, bisect, release). Shared refs are append-only.
Each repository has exactly one release authority.
When to Use / NOT
- Use when: preparing a release; choosing which semver digit moves;
creating, moving, or deleting tags; writing release notes or changelog
entries; commit, branch, merge, or recovery hygiene for shared history.
- NOT when: GitHub repository settings or remote configuration
(
github-repo-setup); workflow files and release CI implementation
(github-actions-engineering); the PR lifecycle itself (push-pr).
Release strategy (adaptive; preserve what exists)
If the project already has a release process, preserve it. Otherwise pick one
authority and keep it:
- Tag + GitHub generated notes (default for GitHub-native projects).
Choose the version, push the
vX.Y.Z tag, and let release CI verify the
tree and publish with generated notes (categories driven by labels in
.github/release.yml). No manual changelog to drift.
- Curated CHANGELOG. When the project intentionally maintains one: move
[Unreleased] to [x.y.z] - date, list Deprecated before Removed, tag
after the changelog lands.
- Release automation (Release Please, semantic-release, ecosystem
tooling). Only when the project already runs one; never add a second
authority beside an existing one.
Version class: breaking behavior change moves the major digit, new capability
the minor, a fix the patch; pre-releases use x.y.z-rc.N precedence. For
catalog and tooling repositories without a published API, bump by intent: a
change users must react to is at least minor.
Process
- Worktree -
git status --short; never git add . in a mixed tree;
stage by path.
- Branch - short lowercase hyphenated name; project caps live in
AGENTS.md.
- Commit unit - one logical change; feature + tests together;
git add -p
to split.
- Message - editor commit for non-trivial work: imperative subject
(
type(scope): desc), blank line, body ~72 cols with the why; run the
repository's title or commit protocol when one exists.
- Before push - gates pass; fixup/squash/rebase -i on private branches
only; never force-push shared branches without explicit approval.
- Merge - per project policy;
--no-ff when branch topology matters.
- Release - follow the project's release authority above; annotated tags
unless the project chooses lightweight deliberately; read the release back
after publishing.
- Evidence - status, diff summary, gates run, version/tag/release action
or explicit skip.
Recovery & non-interactive continuation
- Lost work or history:
git reflog -> identify the pre-damage commit ->
restore additively (git branch rescue <sha>, cherry-pick, or a new commit
of the recovered tree). Recover without destroying more history; reflog is a
recovery mechanism, not a license for destructive operations.
- Ceremonial editors: when the message/content is already decided, suppress
only the editor -
GIT_EDITOR=true git rebase --continue,
GIT_SEQUENCE_EDITOR=true ..., git commit --no-edit. Never override a
prompt that represents a real decision (interactive-rebase TODO, conflict
resolution choice, credential or confirmation prompt).
- Generated or multi-line commit messages: write to a securely created
temporary file (
mktemp) and commit with git commit -F <file> - never
interpolate generated text into the command line. Short, simple subjects may
pass as ordinary quoted arguments.
Common Rationalizations
| Rationalization |
Rebuttal |
| "I'll clean up the commit later." |
Intent lost; rebase cost rises. |
| "git log is our changelog." |
Users cannot scan merges and WIP; use the project's release authority (generated notes or a curated changelog). |
| "PATCH bump for a breaking change." |
Destroys semver trust - MAJOR. |
| "Force-push main to fix." |
Breaks the team - new forward commit instead. |
Red Flags
- Subject with no blank line before body (breaks rebase/format-patch).
- Version tag does not match the published release notes (or the changelog
header, when the project keeps one).
- Two release authorities running at once (tag + tool + manual changelog).
Deprecated missing before Removed in a major release.
- Breaking change shipped as PATCH.
- Force-push of shared history without explicit approval.
Verification
git status --short and the diff/staged summary cited.
git log --format=%s origin/main..HEAD matches the repository's documented commit convention when one applies.
- Release: the tag points at the intended commit;
gh release view shows the
published release with generated notes present.
References
Prior-art capsules (optional reading, when the why matters):
awesome-guidelines/references/semver-public-api-and-bumps.md
awesome-guidelines/references/semver-precedence-and-prerelease.md
awesome-guidelines/references/git-style-branches.md
awesome-guidelines/references/git-style-commit-messages.md
awesome-guidelines/references/git-style-history-and-merge.md
awesome-guidelines/references/changelog-style-learning-note.md
1---2name: git-workflow-and-versioning3description: Use when preparing a release, choosing a version bump, creating or moving tags, writing changelog or release-note content, or when git hygiene for shared history is in question: commits, branches, recovery, non-interactive continuation.4---56# Git Workflow and Versioning78## Core Principle910Treat commits as verified save points with **communicative messages** - history11is for future readers (review, bisect, release). Shared refs are append-only.12Each repository has exactly one release authority.1314## When to Use / NOT1516- **Use when:** preparing a release; choosing which semver digit moves;17 creating, moving, or deleting tags; writing release notes or changelog18 entries; commit, branch, merge, or recovery hygiene for shared history.19- **NOT when:** GitHub repository settings or remote configuration20 (`github-repo-setup`); workflow files and release CI implementation21 (`github-actions-engineering`); the PR lifecycle itself (`push-pr`).2223## Release strategy (adaptive; preserve what exists)2425If the project already has a release process, preserve it. Otherwise pick one26authority and keep it:27281. **Tag + GitHub generated notes (default for GitHub-native projects).**29 Choose the version, push the `vX.Y.Z` tag, and let release CI verify the30 tree and publish with generated notes (categories driven by labels in31 `.github/release.yml`). No manual changelog to drift.322. **Curated CHANGELOG.** When the project intentionally maintains one: move33 `[Unreleased]` to `[x.y.z] - date`, list `Deprecated` before `Removed`, tag34 after the changelog lands.353. **Release automation (Release Please, semantic-release, ecosystem36 tooling).** Only when the project already runs one; never add a second37 authority beside an existing one.3839Version class: breaking behavior change moves the major digit, new capability40the minor, a fix the patch; pre-releases use `x.y.z-rc.N` precedence. For41catalog and tooling repositories without a published API, bump by intent: a42change users must react to is at least minor.4344## Process45461. **Worktree** - `git status --short`; never `git add .` in a mixed tree;47 stage by path.482. **Branch** - short lowercase hyphenated name; project caps live in49 `AGENTS.md`.503. **Commit unit** - one logical change; feature + tests together; `git add -p`51 to split.524. **Message** - editor commit for non-trivial work: imperative subject53 (`type(scope): desc`), blank line, body ~72 cols with the **why**; run the54 repository's title or commit protocol when one exists.555. **Before push** - gates pass; fixup/squash/rebase -i on private branches56 only; **never** force-push shared branches without explicit approval.576. **Merge** - per project policy; `--no-ff` when branch topology matters.587. **Release** - follow the project's release authority above; annotated tags59 unless the project chooses lightweight deliberately; read the release back60 after publishing.618. **Evidence** - status, diff summary, gates run, version/tag/release action62 or explicit skip.6364## Recovery & non-interactive continuation6566- **Lost work or history:** `git reflog` -> identify the pre-damage commit ->67 restore additively (`git branch rescue <sha>`, cherry-pick, or a new commit68 of the recovered tree). Recover without destroying more history; reflog is a69 recovery mechanism, not a license for destructive operations.70- **Ceremonial editors:** when the message/content is already decided, suppress71 only the editor - `GIT_EDITOR=true git rebase --continue`,72 `GIT_SEQUENCE_EDITOR=true ...`, `git commit --no-edit`. Never override a73 prompt that represents a real decision (interactive-rebase TODO, conflict74 resolution choice, credential or confirmation prompt).75- **Generated or multi-line commit messages:** write to a securely created76 temporary file (`mktemp`) and commit with `git commit -F <file>` - never77 interpolate generated text into the command line. Short, simple subjects may78 pass as ordinary quoted arguments.7980## Common Rationalizations8182| Rationalization | Rebuttal |83|---|---|84| "I'll clean up the commit later." | Intent lost; rebase cost rises. |85| "git log is our changelog." | Users cannot scan merges and WIP; use the project's release authority (generated notes or a curated changelog). |86| "PATCH bump for a breaking change." | Destroys semver trust - MAJOR. |87| "Force-push main to fix." | Breaks the team - new forward commit instead. |8889## Red Flags9091- Subject with no blank line before body (breaks rebase/format-patch).92- Version tag does not match the published release notes (or the changelog93 header, when the project keeps one).94- Two release authorities running at once (tag + tool + manual changelog).95- `Deprecated` missing before `Removed` in a major release.96- Breaking change shipped as PATCH.97- Force-push of shared history without explicit approval.9899## Verification100101- `git status --short` and the diff/staged summary cited.102- `git log --format=%s origin/main..HEAD` matches the repository's documented commit convention when one applies.103- Release: the tag points at the intended commit; `gh release view` shows the104 published release with generated notes present.105106## References107108Prior-art capsules (optional reading, when the why matters):109110- `awesome-guidelines/references/semver-public-api-and-bumps.md`111- `awesome-guidelines/references/semver-precedence-and-prerelease.md`112- `awesome-guidelines/references/git-style-branches.md`113- `awesome-guidelines/references/git-style-commit-messages.md`114- `awesome-guidelines/references/git-style-history-and-merge.md`115- `awesome-guidelines/references/changelog-style-learning-note.md`