Compare commits
32 Commits
main
...
05c8fc4aee
| Author | SHA1 | Date | |
|---|---|---|---|
|
05c8fc4aee
|
|||
|
8ed4e2df44
|
|||
|
9774d59aef
|
|||
|
9a2ae93ccf
|
|||
|
164729b57e
|
|||
|
1eab53b7ba
|
|||
|
4ff9b012ad
|
|||
|
8205cb3690
|
|||
|
d2efcb01ba
|
|||
|
9f1af55602
|
|||
|
88a8ba2f28
|
|||
|
e86b0de9fa
|
|||
|
230e76b2d5
|
|||
|
a7325d2331
|
|||
|
20b1507c2b
|
|||
|
da9171686d
|
|||
|
8c91e2028a
|
|||
|
f47ea792aa
|
|||
|
d55ead82d7
|
|||
|
7d06d18ccb
|
|||
|
4722094f0c
|
|||
|
b22cf35953
|
|||
|
1828ae6353
|
|||
|
7c5c7691c3
|
|||
|
208219ca2c
|
|||
|
f1fa264ed7
|
|||
|
4fadbd111a
|
|||
|
de472c82a2
|
|||
|
f5818933c7
|
|||
|
69ea77d236
|
|||
|
0a74d4eacd
|
|||
|
a0359ef376
|
@@ -1,22 +1,10 @@
|
|||||||
{
|
{
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"allow": [
|
"allow": [
|
||||||
"Bash(cat:*)",
|
"Bash(bun install:*)",
|
||||||
"Bash(git add:*)",
|
"Bash(bun run build:*)",
|
||||||
"Bash(git commit:*)",
|
"Bash(bun run update:*)",
|
||||||
"Bash(git diff:*)",
|
"Bash(bun update:*)"
|
||||||
"Bash(ls:*)",
|
|
||||||
"Bash(npm install:*)",
|
|
||||||
"Bash(npm run astro:*)",
|
|
||||||
"Bash(npm run build:*)",
|
|
||||||
"Bash(npm run check:*)",
|
|
||||||
"Bash(npm run dev:*)",
|
|
||||||
"Bash(npm run format:*)",
|
|
||||||
"Bash(npm run format:check:*)",
|
|
||||||
"Bash(npm run lint:*)",
|
|
||||||
"Bash(npm run preview:*)",
|
|
||||||
"Bash(npm run update-specs:*)",
|
|
||||||
"mcp__deepwiki__ask_question"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
.github/dependabot.yml
vendored
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: monthly
|
|
||||||
- package-ecosystem: npm
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: monthly
|
|
||||||
groups:
|
|
||||||
npm-development:
|
|
||||||
dependency-type: development
|
|
||||||
update-types:
|
|
||||||
- major
|
|
||||||
- minor
|
|
||||||
- patch
|
|
||||||
npm-production:
|
|
||||||
dependency-type: production
|
|
||||||
update-types:
|
|
||||||
- major
|
|
||||||
- minor
|
|
||||||
- patch
|
|
||||||
47
.github/workflows/update-specs.yml
vendored
@@ -1,47 +0,0 @@
|
|||||||
name: Update Specs
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-specs:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Generate GitHub App Token
|
|
||||||
id: app-token
|
|
||||||
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.BOT_APP_ID }}
|
|
||||||
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
token: ${{ steps.app-token.outputs.token }}
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
|
||||||
with:
|
|
||||||
node-version-file: ".node-version"
|
|
||||||
cache: "npm"
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Update specs
|
|
||||||
run: npm run update-specs
|
|
||||||
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
|
||||||
with:
|
|
||||||
token: ${{ steps.app-token.outputs.token }}
|
|
||||||
commit-message: "chore: update spec versions"
|
|
||||||
title: "chore: update spec versions"
|
|
||||||
body: |
|
|
||||||
Automated update of spec versions from upstream repository.
|
|
||||||
|
|
||||||
This PR was created by the update-specs workflow.
|
|
||||||
branch: update-specs
|
|
||||||
delete-branch: true
|
|
||||||
add-paths: |
|
|
||||||
src/content/spec/*
|
|
||||||
3
.gitignore
vendored
@@ -2,9 +2,6 @@
|
|||||||
dist/
|
dist/
|
||||||
.astro/
|
.astro/
|
||||||
|
|
||||||
# Claude
|
|
||||||
.claude/settings.local.json
|
|
||||||
|
|
||||||
# Node
|
# Node
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
[settings]
|
[tools]
|
||||||
idiomatic_version_file_enable_tools = ["node"]
|
bun = "1"
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
24
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
|
docs/
|
||||||
.astro/
|
.astro/
|
||||||
dist/
|
|
||||||
node_modules/
|
node_modules/
|
||||||
package-lock.json
|
bun.lock
|
||||||
src/content/spec/
|
|
||||||
|
|||||||
2
.vscode/launch.json
vendored
@@ -2,7 +2,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"command": "npm run dev",
|
"command": "bun run dev",
|
||||||
"name": "dev server",
|
"name": "dev server",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "node-terminal"
|
"type": "node-terminal"
|
||||||
|
|||||||
47
CLAUDE.md
@@ -12,51 +12,50 @@ that combines GitHub Flow with versioned releases.
|
|||||||
## Build Commands
|
## Build Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install tooling (node) via mise
|
# Install tooling (bun) via mise
|
||||||
mise install
|
mise install
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
npm install
|
bun install
|
||||||
|
|
||||||
# Development server
|
# Development server
|
||||||
npm run dev
|
bun run dev
|
||||||
|
|
||||||
# Build site (outputs to dist/ directory)
|
# Build site (outputs to docs/ directory)
|
||||||
npm run build
|
bun run build
|
||||||
|
|
||||||
# Preview built site
|
# Preview built site
|
||||||
npm run preview
|
bun run preview
|
||||||
|
|
||||||
# Type checking
|
# Type checking
|
||||||
npm run check
|
bun run check
|
||||||
|
|
||||||
# Linting
|
# Linting
|
||||||
npm run lint
|
bun run lint
|
||||||
|
|
||||||
# Formatting
|
# Formatting
|
||||||
npm run format
|
bun run format
|
||||||
npm run format:check
|
bun run format:check
|
||||||
|
|
||||||
# Update specs from upstream (fetches from github.com/jimeh/common-flow)
|
# Update specs from upstream (fetches from github.com/jimeh/common-flow)
|
||||||
npm run update-specs
|
bun run update-specs
|
||||||
```
|
```
|
||||||
|
|
||||||
The site is built to `dist/` and deployed to Cloudflare Workers.
|
The site is built to `docs/` for GitHub Pages hosting.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
- **Astro 5.x** static site generator
|
- **Astro 5.x** static site generator
|
||||||
- **Tailwind CSS 4.x** for styling with dark mode support
|
- **Tailwind CSS 4.x** for styling with dark mode support
|
||||||
- **astro-icon** with Heroicons, Simple Icons, and custom local SVGs (`src/icons/`)
|
- **astro-icon** with Heroicons and Simple Icons for icons
|
||||||
- **Content Collections** for spec markdown files
|
- **Content Collections** for spec markdown files
|
||||||
- **TypeScript** throughout
|
- **TypeScript** throughout
|
||||||
- **Node.js** as JavaScript runtime (managed via mise)
|
- **Bun** as JavaScript runtime and package manager (managed via mise)
|
||||||
|
|
||||||
### Key Files
|
### Key Files
|
||||||
|
|
||||||
- `src/config.ts` - Site configuration (metadata, update settings)
|
- `src/config.ts` - Site configuration with version list
|
||||||
- `src/content.config.ts` - Astro content collection definition
|
- `src/content.config.ts` - Astro content collection definition
|
||||||
- `src/styles/global.css` - Global Tailwind styles
|
|
||||||
- `src/layouts/BaseLayout.astro` - Base layout with head, meta tags, theme scripts
|
- `src/layouts/BaseLayout.astro` - Base layout with head, meta tags, theme scripts
|
||||||
- `src/layouts/SpecLayout.astro` - Spec page layout composing all sections
|
- `src/layouts/SpecLayout.astro` - Spec page layout composing all sections
|
||||||
- `src/components/` - UI components:
|
- `src/components/` - UI components:
|
||||||
@@ -71,22 +70,18 @@ The site is built to `dist/` and deployed to Cloudflare Workers.
|
|||||||
- `TocLink.astro` - Reusable TOC link component
|
- `TocLink.astro` - Reusable TOC link component
|
||||||
- `ThemeToggle.astro` - Dark/light mode toggle
|
- `ThemeToggle.astro` - Dark/light mode toggle
|
||||||
- `VersionSelector.astro` - Spec version dropdown
|
- `VersionSelector.astro` - Spec version dropdown
|
||||||
- `src/scripts/` - Client-side TypeScript:
|
- `src/scripts/activeSectionTracker.ts` - Shared scroll-based active section tracking
|
||||||
- `activeSectionTracker.ts` - Scroll-based active section tracking
|
|
||||||
- `clauseHighlight.ts` - Clause highlight on anchor navigation
|
|
||||||
- `src/pages/index.astro` - Landing page
|
- `src/pages/index.astro` - Landing page
|
||||||
- `src/pages/404.astro` - 404 error page
|
- `src/pages/404.astro` - 404 error page
|
||||||
- `src/pages/spec/[version].astro` - Dynamic route for spec versions
|
- `src/pages/spec/[version].astro` - Dynamic route for spec versions
|
||||||
- `src/pages/spec/[version]/raw.astro` - Raw markdown spec page
|
- `src/utils/parseSpecContent.ts` - Markdown parsing utilities
|
||||||
- `src/utils/` - Utility functions:
|
|
||||||
- `parseSpecContent.ts` - Markdown parsing utilities
|
|
||||||
- `versions.ts` - Version info helper (derives current version from specs)
|
|
||||||
- `src/content/spec/*.md` - Versioned spec documents
|
- `src/content/spec/*.md` - Versioned spec documents
|
||||||
- `public/spec/*.svg` - SVG diagrams for each version
|
- `public/spec/*.svg` - SVG diagrams for each version
|
||||||
- `scripts/update-specs.ts` - Fetches specs from GitHub
|
- `scripts/update-specs.ts` - Fetches specs from GitHub
|
||||||
- `wrangler.jsonc` - Cloudflare Workers deployment config
|
|
||||||
|
|
||||||
### Updating Spec Versions
|
### Updating Spec Versions
|
||||||
|
|
||||||
1. Run `npm run update-specs` to fetch specs from GitHub
|
1. Add new version to `versions` array in `src/config.ts`
|
||||||
2. Run `npm run build` to rebuild the site
|
2. Update `currentVersion` if this is the new default
|
||||||
|
3. Run `bun run update` to fetch specs from GitHub
|
||||||
|
4. Run `bun run build` to rebuild the site
|
||||||
|
|||||||
@@ -1,38 +1,13 @@
|
|||||||
import { defineConfig, fontProviders } from "astro/config";
|
import { defineConfig } from "astro/config";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import sitemap from "@astrojs/sitemap";
|
import sitemap from "@astrojs/sitemap";
|
||||||
import icon from "astro-icon";
|
import icon from "astro-icon";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: "https://commonflow.org",
|
site: "https://commonflow.org",
|
||||||
outDir: "./dist",
|
outDir: "./docs",
|
||||||
integrations: [sitemap(), icon()],
|
integrations: [sitemap(), icon()],
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [tailwindcss()],
|
plugins: [tailwindcss()],
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
fonts: [
|
|
||||||
{
|
|
||||||
provider: fontProviders.fontsource(),
|
|
||||||
name: "Bricolage Grotesque",
|
|
||||||
cssVariable: "--font-bricolage",
|
|
||||||
weights: ["200 800"],
|
|
||||||
fallbacks: ["system-ui", "sans-serif"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provider: fontProviders.fontsource(),
|
|
||||||
name: "DM Sans",
|
|
||||||
cssVariable: "--font-dm-sans",
|
|
||||||
weights: ["100 1000"],
|
|
||||||
fallbacks: ["system-ui", "sans-serif"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provider: fontProviders.fontsource(),
|
|
||||||
name: "JetBrains Mono",
|
|
||||||
cssVariable: "--font-jetbrains",
|
|
||||||
weights: ["100 800"],
|
|
||||||
fallbacks: ["SF Mono", "Consolas", "monospace"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|||||||
0
docs/.nojekyll
Normal file
24
docs/404.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html><html lang="en"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="canonical" href="https://commonflow.org/404/"><title>Page Not Found | Git Common-Flow</title><meta name="description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta name="author" content="Jim Myhrberg"><!-- Open Graph --><meta property="og:title" content="Page Not Found | Git Common-Flow"><meta property="og:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta property="og:type" content="website"><meta property="og:url" content="https://commonflow.org/404/"><!-- Twitter --><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Page Not Found | Git Common-Flow"><meta name="twitter:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><!-- Favicon --><link rel="icon" href="/favicon.ico" sizes="32x32"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- Prevent flash of wrong theme --><script>
|
||||||
|
(function () {
|
||||||
|
const mode = localStorage.getItem("theme");
|
||||||
|
const prefersDark = window.matchMedia(
|
||||||
|
"(prefers-color-scheme: dark)",
|
||||||
|
).matches;
|
||||||
|
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
||||||
|
document.documentElement.classList.add("dark");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script><link rel="stylesheet" href="/_astro/index.qe8PXlQZ.css"></head> <body class="min-h-screen"> <div class="flex flex-col items-center justify-center min-h-screen p-8"> <div class="text-center"> <h1 class="text-[8rem] sm:text-[12rem] font-display font-bold leading-none
|
||||||
|
text-gray-300 dark:text-neutral-700">
|
||||||
|
404
|
||||||
|
</h1> <p class="text-xl mb-2 text-gray-600 dark:text-neutral-400">
|
||||||
|
Page not found
|
||||||
|
</p> <p class="text-gray-500 dark:text-neutral-500">
|
||||||
|
The page you're looking for doesn't exist.
|
||||||
|
</p> <a href="/" class="inline-flex items-center justify-center gap-2 mt-8
|
||||||
|
px-5 py-2.5 text-sm font-medium rounded-lg
|
||||||
|
transition-all cursor-pointer
|
||||||
|
bg-sky-600 text-white
|
||||||
|
hover:bg-sky-500 hover:-translate-y-0.5 hover:shadow-md">
|
||||||
|
Go to homepage
|
||||||
|
</a> </div> </div> <!-- Re-init theme on Astro page transitions --> <script type="module">document.addEventListener("astro:after-swap",()=>{const e=localStorage.getItem("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches;e==="dark"||e!=="light"&&t?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")});</script> </body> </html>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{i as o}from"./activeSectionTracker.CGlk-3e6.js";function a(){const e=document.getElementById("site-header"),d=document.getElementById("hero"),r=document.getElementById("mobile-menu-btn"),t=document.getElementById("mobile-nav");if(!e||!d)return;const i=64;function n(){e&&(window.scrollY>=i?(e.classList.remove("translate-y-[-100%]","border-transparent"),e.classList.add("border-gray-200","dark:border-neutral-800")):(e.classList.add("translate-y-[-100%]","border-transparent"),e.classList.remove("border-gray-200","dark:border-neutral-800")))}window.addEventListener("scroll",n,{passive:!0}),n(),r&&t&&(r.addEventListener("click",()=>{t.classList.toggle("hidden")}),t.querySelectorAll("a").forEach(s=>{s.addEventListener("click",()=>{t.classList.add("hidden")})})),o({linkSelector:"[data-nav-link]",defaultToFirst:!1})}a();document.addEventListener("astro:after-swap",a);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{i as v}from"./activeSectionTracker.CGlk-3e6.js";function s(){v({linkSelector:"[data-sidebar-link]"});const t=document.getElementById("spec-toc-toggle"),e=document.getElementById("spec-toc-drawer"),r=e?.querySelector("[data-toc-backdrop]"),d=e?.querySelector("[data-toc-close]"),i=e?.querySelectorAll("[data-toc-link]");function a(){e?.classList.remove("hidden"),document.body.style.overflow="hidden"}function c(){e?.classList.add("hidden"),document.body.style.overflow=""}t?.addEventListener("click",a),r?.addEventListener("click",c),d?.addEventListener("click",c),i?.forEach(o=>{o.addEventListener("click",c)});const n=document.getElementById("spec");n&&t&&new IntersectionObserver(([l])=>{t.classList.toggle("hidden",!l.isIntersecting)},{threshold:0}).observe(n)}s();document.addEventListener("astro:after-swap",s);
|
||||||
1
docs/_astro/activeSectionTracker.CGlk-3e6.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
function m(l){const{linkSelector:a,sectionIdAttr:o="data-section-id",headerOffset:f=100,defaultToFirst:u=!0}=l,s=document.querySelectorAll(a),i=[],r=new Set;s.forEach(n=>{const t=n.getAttribute(o);if(t&&!r.has(t)){r.add(t);const e=document.getElementById(t);e&&i.push({id:t,element:e})}});function d(){let n=u?i[0]?.id:null;for(const{id:t,element:e}of i)e.getBoundingClientRect().top<=f&&(n=t);s.forEach(t=>{const e=t.getAttribute(o);t.classList.toggle("active",e===n)})}let c=!1;window.addEventListener("scroll",()=>{c||(requestAnimationFrame(()=>{d(),c=!1}),c=!0)}),d()}export{m as i};
|
||||||
BIN
docs/_astro/bricolage-grotesque-latin-wght-normal.DLoelf7F.woff2
Normal file
BIN
docs/_astro/dm-sans-latin-ext-wght-normal.BOFOeGcA.woff2
Normal file
BIN
docs/_astro/dm-sans-latin-wght-normal.Xz1IZZA0.woff2
Normal file
1
docs/_astro/index.qe8PXlQZ.css
Normal file
BIN
docs/_astro/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2
Normal file
BIN
docs/_astro/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2
Normal file
BIN
docs/_astro/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2
Normal file
BIN
docs/_astro/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2
Normal file
BIN
docs/_astro/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2
Normal file
BIN
docs/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
docs/favicon.ico
Normal file
|
After Width: | Height: | Size: 14 KiB |
17
docs/favicon.svg
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||||
|
<!-- Main horizontal line -->
|
||||||
|
<path d="M 4 10 L 28 10" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Branch line: down from left, curve, up to right -->
|
||||||
|
<path d="M 8 10 L 8 16 Q 8 22 16 22 Q 24 22 24 16 L 24 10"
|
||||||
|
fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Left dot on main line -->
|
||||||
|
<circle cx="8" cy="10" r="3" fill="currentColor"/>
|
||||||
|
|
||||||
|
<!-- Right dot on main line -->
|
||||||
|
<circle cx="24" cy="10" r="3" fill="currentColor"/>
|
||||||
|
|
||||||
|
<!-- Middle dot on branch -->
|
||||||
|
<circle cx="16" cy="22" r="3" fill="currentColor"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 625 B |
522
docs/index.html
Normal file
1
docs/sitemap-0.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://commonflow.org/</loc></url><url><loc>https://commonflow.org/spec/1.0.0-rc.1/</loc></url><url><loc>https://commonflow.org/spec/1.0.0-rc.2/</loc></url><url><loc>https://commonflow.org/spec/1.0.0-rc.3/</loc></url><url><loc>https://commonflow.org/spec/1.0.0-rc.4/</loc></url><url><loc>https://commonflow.org/spec/1.0.0-rc.5/</loc></url></urlset>
|
||||||
1
docs/sitemap-index.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>https://commonflow.org/sitemap-0.xml</loc></sitemap></sitemapindex>
|
||||||
2
docs/spec/1.0.0-rc.1.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
343
docs/spec/1.0.0-rc.1/index.html
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
<!DOCTYPE html><html lang="en"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="canonical" href="https://commonflow.org/spec/1.0.0-rc.1/"><title>Git Common-Flow 1.0.0-rc.1 | Git Common-Flow</title><meta name="description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta name="author" content="Jim Myhrberg"><!-- Open Graph --><meta property="og:title" content="Git Common-Flow 1.0.0-rc.1 | Git Common-Flow"><meta property="og:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta property="og:type" content="website"><meta property="og:url" content="https://commonflow.org/spec/1.0.0-rc.1/"><!-- Twitter --><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Git Common-Flow 1.0.0-rc.1 | Git Common-Flow"><meta name="twitter:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><!-- Favicon --><link rel="icon" href="/favicon.ico" sizes="32x32"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- Prevent flash of wrong theme --><script>
|
||||||
|
(function () {
|
||||||
|
const mode = localStorage.getItem("theme");
|
||||||
|
const prefersDark = window.matchMedia(
|
||||||
|
"(prefers-color-scheme: dark)",
|
||||||
|
).matches;
|
||||||
|
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
||||||
|
document.documentElement.classList.add("dark");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script><link rel="stylesheet" href="/_astro/index.qe8PXlQZ.css"></head> <body class="min-h-screen"> <header id="site-header" class="fixed top-0 inset-x-0 z-50 border-b border-transparent
|
||||||
|
translate-y-[-100%] transition-transform duration-300
|
||||||
|
backdrop-blur-xl bg-gray-50/85 dark:bg-neutral-950/85"> <div class="max-w-6xl mx-auto px-4 sm:px-6 h-16 flex items-center justify-between"> <!-- Logo / Title + Version --> <div class="flex items-center gap-3"> <a href="#hero" class="flex items-center gap-3 no-underline
|
||||||
|
text-gray-950 dark:text-neutral-50
|
||||||
|
hover:text-sky-600 transition-colors"> <span class="font-display font-bold text-lg tracking-tight">
|
||||||
|
Git Common-Flow
|
||||||
|
</span> </a> <div class="hidden md:block"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.1</span> <svg width="1em" height="1em" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <symbol id="ai:heroicons:chevron-down" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m19.5 8.25l-7.5 7.5l-7.5-7.5"/></symbol><use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> <script type="module">function c(){document.querySelectorAll("[data-version-selector]").forEach(e=>{if(e.dataset.initialized)return;e.dataset.initialized="true";const t=e.querySelector("[data-version-trigger]"),a=e.querySelector("[data-version-dropdown]"),n=e.querySelector("[data-arrow-icon]");if(!t||!a)return;const l=()=>{a.dataset.open="true",t.setAttribute("aria-expanded","true"),n&&(n.style.transform="rotate(180deg)")},o=()=>{delete a.dataset.open,t.setAttribute("aria-expanded","false"),n&&(n.style.transform="")};t.addEventListener("click",r=>{r.stopPropagation();const u=a.dataset.open==="true";document.querySelectorAll("[data-version-dropdown][data-open]").forEach(s=>{delete s.dataset.open;const i=s.previousElementSibling;i?.setAttribute("aria-expanded","false");const d=i?.querySelector("[data-arrow-icon]");d&&(d.style.transform="")}),u?o():l()}),document.addEventListener("click",r=>{e.contains(r.target)||o()}),document.addEventListener("keydown",r=>{r.key==="Escape"&&a.dataset.open==="true"&&(o(),t.focus())})})}c();document.addEventListener("astro:after-swap",c);</script> </div> </div> <!-- Desktop Navigation --> <nav class="hidden md:flex items-center gap-1"> <a href="#about" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="about"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:information-circle"> <symbol id="ai:heroicons:information-circle" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/></symbol><use href="#ai:heroicons:information-circle"></use> </svg> About </a><a href="#spec" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="spec"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:document-text"> <symbol id="ai:heroicons:document-text" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9"/></symbol><use href="#ai:heroicons:document-text"></use> </svg> Spec </a><a href="#faq" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="faq"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:question-mark-circle"> <symbol id="ai:heroicons:question-mark-circle" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.879 7.519c1.172-1.025 3.071-1.025 4.243 0c1.171 1.025 1.171 2.687 0 3.712q-.308.268-.67.442c-.746.361-1.452.999-1.452 1.827v.75M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9 5.25h.008v.008H12z"/></symbol><use href="#ai:heroicons:question-mark-circle"></use> </svg> FAQ </a> </nav> <!-- Right side: Theme, GitHub --> <div class="flex items-center gap-3"> <div class="relative group"> <button data-theme-toggle type="button" class="p-2 rounded-lg cursor-pointer transition-colors duration-200
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle theme"> <svg width="1em" height="1em" data-theme-icon="light" class="hidden w-5 h-5" data-icon="heroicons:sun"> <symbol id="ai:heroicons:sun" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0a3.75 3.75 0 0 1 7.5 0"/></symbol><use href="#ai:heroicons:sun"></use> </svg> <svg width="1em" height="1em" data-theme-icon="dark" class="hidden w-5 h-5" data-icon="heroicons:moon"> <symbol id="ai:heroicons:moon" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M21.752 15.002A9.7 9.7 0 0 1 18 15.75A9.75 9.75 0 0 1 8.25 6c0-1.33.266-2.597.748-3.752A9.75 9.75 0 0 0 3 11.25A9.75 9.75 0 0 0 12.75 21a9.75 9.75 0 0 0 9.002-5.998"/></symbol><use href="#ai:heroicons:moon"></use> </svg> <svg width="1em" height="1em" data-theme-icon="auto" class="hidden w-5 h-5" data-icon="heroicons:computer-desktop"> <symbol id="ai:heroicons:computer-desktop" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"/></symbol><use href="#ai:heroicons:computer-desktop"></use> </svg> </button> <!-- Tooltip --> <div class="absolute left-1/2 -translate-x-1/2 top-full mt-2
|
||||||
|
px-2 py-1 text-xs font-medium whitespace-nowrap rounded-md shadow-sm
|
||||||
|
bg-gray-900 text-white dark:bg-white dark:text-gray-900
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-200 pointer-events-none"> <span data-tooltip-text="light" class="hidden">Light</span> <span data-tooltip-text="dark" class="hidden">Dark</span> <span data-tooltip-text="auto" class="hidden">System</span> </div> </div> <script type="module">function r(){const c=document.querySelectorAll("[data-theme-toggle]");function n(){const e=localStorage.getItem("theme");return e==="dark"||e==="light"||e==="auto"?e:"auto"}function i(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function d(e){return e==="auto"?i():e}function s(e){document.querySelectorAll("[data-theme-icon]").forEach(t=>{const a=t.dataset.themeIcon;t.classList.toggle("hidden",a!==e)}),document.querySelectorAll("[data-tooltip-text]").forEach(t=>{const a=t.dataset.tooltipText;t.classList.toggle("hidden",a!==e)})}function o(e){d(e)==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark"),s(e)}function u(e){localStorage.setItem("theme",e),o(e)}function l(){const e=n();return e==="light"?"dark":e==="dark"?"auto":"light"}const f=n();o(f),c.forEach(e=>{e.dataset.initialized||(e.dataset.initialized="true",e.addEventListener("click",()=>{u(l())}))}),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{n()==="auto"&&o("auto")})}r();document.addEventListener("astro:after-swap",r);</script> <a href="https://github.com/jimeh/common-flow" target="_blank" rel="noopener noreferrer" class="p-2 rounded-lg transition-colors
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="View on GitHub"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="simple-icons:github"> <symbol id="ai:simple-icons:github" viewBox="0 0 24 24"><path fill="currentColor" d="M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></symbol><use href="#ai:simple-icons:github"></use> </svg> </a> <!-- Mobile menu button --> <button id="mobile-menu-btn" class="md:hidden p-2 rounded-lg
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle menu"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:bars-3"> <symbol id="ai:heroicons:bars-3" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/></symbol><use href="#ai:heroicons:bars-3"></use> </svg> </button> </div> </div> <!-- Mobile Navigation --> <nav id="mobile-nav" class="md:hidden hidden border-t border-gray-200 dark:border-neutral-800"> <div class="px-4 py-3 space-y-1 text-center"> <div class="py-2 flex justify-center"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.1</span> <svg width="1em" height="1em" viewBox="0 0 24 24" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> </div> <a href="#about" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="about"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:information-circle"> <use href="#ai:heroicons:information-circle"></use> </svg> About </a><a href="#spec" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="spec"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:document-text"> <use href="#ai:heroicons:document-text"></use> </svg> Spec </a><a href="#faq" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="faq"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:question-mark-circle"> <use href="#ai:heroicons:question-mark-circle"></use> </svg> FAQ </a> </div> </nav> </header> <script type="module" src="/_astro/Header.astro_astro_type_script_index_0_lang.ClIJVJFM.js"></script> <main> <section id="hero" class="relative min-h-[75vh] flex flex-col items-center justify-center
|
||||||
|
px-6 pt-16 pb-24 overflow-hidden"> <!-- Background gradient/texture --> <div class="absolute inset-0 bg-gradient-to-b
|
||||||
|
from-gray-100 to-gray-50
|
||||||
|
dark:from-neutral-900 dark:to-neutral-950"></div> <!-- Subtle grid pattern with fade --> <div class="absolute inset-0 opacity-[0.06] dark:opacity-[0.12]
|
||||||
|
bg-[linear-gradient(theme(colors.gray.950)_1px,transparent_1px),linear-gradient(90deg,theme(colors.gray.950)_1px,transparent_1px)]
|
||||||
|
dark:bg-[linear-gradient(theme(colors.neutral.600)_1px,transparent_1px),linear-gradient(90deg,theme(colors.neutral.600)_1px,transparent_1px)]
|
||||||
|
bg-[size:60px_60px] bg-center
|
||||||
|
[-webkit-mask-image:linear-gradient(to_bottom,black_20%,transparent_80%)]
|
||||||
|
[mask-image:linear-gradient(to_bottom,black_20%,transparent_80%)]"></div> <!-- Top bar with version & theme --> <div class="absolute top-0 inset-x-0 z-20 flex items-center justify-between
|
||||||
|
px-6 py-4 animate-fade-in-down"> <div class="flex items-center gap-3"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.1</span> <svg width="1em" height="1em" viewBox="0 0 24 24" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> </div> <div class="flex items-center gap-2"> <div class="relative group"> <button data-theme-toggle type="button" class="p-2 rounded-lg cursor-pointer transition-colors duration-200
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle theme"> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="light" class="hidden w-5 h-5" data-icon="heroicons:sun"> <use href="#ai:heroicons:sun"></use> </svg> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="dark" class="hidden w-5 h-5" data-icon="heroicons:moon"> <use href="#ai:heroicons:moon"></use> </svg> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="auto" class="hidden w-5 h-5" data-icon="heroicons:computer-desktop"> <use href="#ai:heroicons:computer-desktop"></use> </svg> </button> <!-- Tooltip --> <div class="absolute left-1/2 -translate-x-1/2 top-full mt-2
|
||||||
|
px-2 py-1 text-xs font-medium whitespace-nowrap rounded-md shadow-sm
|
||||||
|
bg-gray-900 text-white dark:bg-white dark:text-gray-900
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-200 pointer-events-none"> <span data-tooltip-text="light" class="hidden">Light</span> <span data-tooltip-text="dark" class="hidden">Dark</span> <span data-tooltip-text="auto" class="hidden">System</span> </div> </div> <a href="https://github.com/jimeh/common-flow" target="_blank" rel="noopener noreferrer" class="p-2 rounded-lg transition-colors
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-white/50 dark:hover:bg-neutral-800/50" aria-label="View on GitHub"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-5 h-5" data-icon="simple-icons:github"> <use href="#ai:simple-icons:github"></use> </svg> </a> </div> </div> <!-- Main content --> <div class="relative z-10 w-full max-w-4xl mx-auto text-center"> <!-- Title --> <h1 class="animate-fade-in-up mb-4
|
||||||
|
text-gray-950 dark:text-neutral-50">
|
||||||
|
Git Common-Flow
|
||||||
|
</h1> <!-- Tagline --> <p class="animate-fade-in-up delay-100
|
||||||
|
text-lg sm:text-xl max-w-2xl mx-auto mb-8
|
||||||
|
text-gray-600 dark:text-neutral-400">
|
||||||
|
A sensible git workflow for teams who ship
|
||||||
|
</p> <!-- Version badge --> <div class="animate-fade-in-up delay-200 mb-10"> <span class="inline-flex items-center px-3 py-1 font-mono text-xs font-medium
|
||||||
|
rounded-full border
|
||||||
|
bg-gray-100 border-gray-200 text-gray-500
|
||||||
|
dark:bg-neutral-800/50 dark:border-neutral-700 dark:text-neutral-400">
|
||||||
|
v1.0.0-rc.1 </span> </div> <!-- SVG Diagram --> <div class="animate-fade-in-up delay-300
|
||||||
|
relative mx-auto mb-12 p-4 sm:p-8
|
||||||
|
bg-white dark:bg-neutral-900
|
||||||
|
rounded-2xl shadow-lg dark:shadow-none
|
||||||
|
border border-gray-200 dark:border-neutral-800"> <img src="/spec/1.0.0-rc.1.svg" alt="Git Common-Flow diagram" class="w-full h-auto max-w-3xl mx-auto
|
||||||
|
dark:invert dark:hue-rotate-180 dark:contrast-90"> </div> <!-- Navigation links --> <nav class="animate-fade-in-up delay-400
|
||||||
|
flex flex-wrap items-center justify-center gap-4"> <a href="#about" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50">
|
||||||
|
About
|
||||||
|
</a> <a href="#spec" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
bg-sky-600 text-white
|
||||||
|
hover:bg-sky-500 hover:-translate-y-0.5 hover:shadow-md">
|
||||||
|
Read the Spec
|
||||||
|
</a> <a href="#faq" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50">
|
||||||
|
FAQ
|
||||||
|
</a> </nav> </div> <!-- Scroll indicator --> <a href="#about" class="absolute bottom-8 left-1/2 -translate-x-1/2
|
||||||
|
animate-fade-in delay-700
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-sky-600 transition-colors" aria-label="Scroll to content"> <svg width="1em" height="1em" class="w-6 h-6 animate-bounce-subtle" data-icon="heroicons:arrow-down"> <symbol id="ai:heroicons:arrow-down" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3"/></symbol><use href="#ai:heroicons:arrow-down"></use> </svg> </a> </section> <section id="about" class="py-20 sm:py-28"> <div class="section-container"> <div class="max-w-3xl mx-auto"> <div class="mb-12 text-center"> <h2 class="text-3xl sm:text-4xl mb-4">About Common-Flow</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> A practical git workflow that combines the best of GitHub Flow with versioned releases </p> </div> <!-- Introduction --> <div class="prose-spec mb-12"></div> <!-- Summary as feature cards --> <div class="mb-16"> <h3 class="text-xl font-display font-semibold mb-6
|
||||||
|
text-gray-950 dark:text-neutral-50">
|
||||||
|
Key Principles
|
||||||
|
</h3> <div class="prose-spec"><p>Common-Flow is an attempt to gather a sensible selection of the most common
|
||||||
|
usage patterns of git into a single and concise specification. It is based on
|
||||||
|
the <a href="http://scottchacon.com/2011/08/31/github-flow.html">original variant</a>
|
||||||
|
of <a href="https://guides.github.com/introduction/flow/">GitHub Flow</a>, while taking
|
||||||
|
into account how a lot of open source projects use git.</p>
|
||||||
|
<p>TL;DR: Common-Flow is basically GitHub Flow with the addition of versioned
|
||||||
|
releases, maintenance releases for old versions, and without the requirement to
|
||||||
|
deploy to production all the time.</p></div> </div> <!-- Feedback & License --> <div class="pt-8 border-t border-gray-200 dark:border-neutral-800"> <div class="grid sm:grid-cols-2 gap-8"> <div> <h4 class="text-sm font-semibold uppercase tracking-wider mb-3
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Feedback
|
||||||
|
</h4> <p class="text-gray-600 dark:text-neutral-400">
|
||||||
|
Please <a href="https://github.com/jimeh/common-flow/issues" class="text-sky-600 hover:text-sky-400" target="_blank" rel="noopener noreferrer">open an issue on GitHub</a>.
|
||||||
|
</p> </div> <div> <h4 class="text-sm font-semibold uppercase tracking-wider mb-3
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
License
|
||||||
|
</h4> <div class="text-gray-600 dark:text-neutral-400"><p><a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons - CC BY 3.0</a></p></div> </div> </div> </div> </div> </div> </section> <section id="spec" class="py-20 sm:py-28"> <div class="section-container"> <div class="mb-12 text-center max-w-3xl mx-auto"> <h2 class="text-3xl sm:text-4xl mb-4">The Specification</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> The complete Git Common-Flow specification </p> </div> <!-- Content with sidebar --> <div class="lg:flex lg:gap-8"> <!-- Sidebar --> <div class="lg:w-64 lg:flex-shrink-0"> <aside id="spec-sidebar" class="hidden lg:block lg:sticky lg:top-24 lg:self-start
|
||||||
|
lg:max-h-[calc(100vh-8rem)] lg:overflow-y-auto
|
||||||
|
lg:pr-8 lg:mr-8 lg:border-r border-gray-200 dark:border-neutral-800"> <nav class="space-y-1 py-2"> <div class="text-xs font-semibold uppercase tracking-wider mb-4
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Table of Contents
|
||||||
|
</div> <a href="#terminology" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-sidebar-link data-section-id="terminology"> <span>Terminology</span> </a><a href="#specification" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-sidebar-link data-section-id="specification"> <span>Specification</span> </a><a href="#clause-1" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-1"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 1. </span> <span>The Master Branch</span> </a><a href="#clause-2" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-2"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 2. </span> <span>Changes</span> </a><a href="#clause-3" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-3"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 3. </span> <span>Git Best Practices</span> </a><a href="#clause-4" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-4"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 4. </span> <span>Versioning</span> </a><a href="#clause-5" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-5"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 5. </span> <span>Releases</span> </a><a href="#clause-6" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-6"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 6. </span> <span>Bug Fixes & Rollback</span> </a><a href="#clause-7" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-7"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 7. </span> <span>Maintenance Releases</span> </a> </nav> </aside> <!-- Mobile floating button --> <button id="spec-toc-toggle" class="lg:hidden fixed bottom-6 right-6 z-40
|
||||||
|
w-12 h-12 rounded-full shadow-lg
|
||||||
|
bg-sky-600 text-white
|
||||||
|
flex items-center justify-center
|
||||||
|
hover:bg-sky-500
|
||||||
|
transition-all duration-200" aria-label="Jump to section"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:bars-3-bottom-left"> <symbol id="ai:heroicons:bars-3-bottom-left" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12"/></symbol><use href="#ai:heroicons:bars-3-bottom-left"></use> </svg> </button> <!-- Mobile TOC drawer --> <div id="spec-toc-drawer" class="lg:hidden fixed inset-0 z-50 hidden" data-toc-drawer> <!-- Backdrop --> <div class="absolute inset-0 bg-black/50" data-toc-backdrop></div> <!-- Drawer --> <div class="absolute bottom-0 inset-x-0 max-h-[70vh] overflow-y-auto
|
||||||
|
bg-gray-50 dark:bg-neutral-950
|
||||||
|
rounded-t-2xl shadow-xl p-6"> <div class="flex items-center justify-between mb-4"> <span class="text-sm font-semibold uppercase tracking-wider
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Jump to Section
|
||||||
|
</span> <button class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-neutral-800" data-toc-close aria-label="Close"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:x-mark"> <symbol id="ai:heroicons:x-mark" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18L18 6M6 6l12 12"/></symbol><use href="#ai:heroicons:x-mark"></use> </svg> </button> </div> <nav class="space-y-1"> <a href="#terminology" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-toc-link> <span>Terminology</span> </a><a href="#specification" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-toc-link> <span>Specification</span> </a><a href="#clause-1" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 1. </span> <span>The Master Branch</span> </a><a href="#clause-2" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 2. </span> <span>Changes</span> </a><a href="#clause-3" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 3. </span> <span>Git Best Practices</span> </a><a href="#clause-4" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 4. </span> <span>Versioning</span> </a><a href="#clause-5" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 5. </span> <span>Releases</span> </a><a href="#clause-6" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 6. </span> <span>Bug Fixes & Rollback</span> </a><a href="#clause-7" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 7. </span> <span>Maintenance Releases</span> </a> </nav> </div> </div> <script type="module" src="/_astro/SpecSidebar.astro_astro_type_script_index_0_lang.BQBj5HuJ.js"></script> </div> <!-- Main content --> <div class="flex-1 min-w-0"> <article class="prose-spec"> <!-- Terminology --> <section id="terminology"> <h2>Terminology</h2> <ul>
|
||||||
|
<li><strong>Master Branch</strong> - Must always have passing tests, is considered bleeding
|
||||||
|
edge, and must be named <code>master</code>.</li>
|
||||||
|
<li><strong>Change Branches</strong> - Any branch that introduces changes like a new feature, a
|
||||||
|
bug fix, etc.</li>
|
||||||
|
<li><strong>Source Branch</strong> - The branch that a change branch was created from. New
|
||||||
|
changes in the source branch should be incorporated into the change branch via
|
||||||
|
rebasing.</li>
|
||||||
|
<li><strong>Merge Target</strong> - A branch that is the intended merge target for a change
|
||||||
|
branch. Typically the merge target branch will be the same as the source
|
||||||
|
branch.</li>
|
||||||
|
<li><strong>Maintenance Branches</strong> - Used for maintaining old versions and releasing
|
||||||
|
PATCH updates when the master branch has moved on. Should follow a
|
||||||
|
<code>stable-X.Y</code> naming pattern, where <code>X</code> is MAJOR version and <code>Y</code> is MINOR
|
||||||
|
version.</li>
|
||||||
|
<li><strong>Pull Request</strong> - A means of requesting that a change branch is merged in to
|
||||||
|
its merge target, allowing others to review, discuss and approve the changes.</li>
|
||||||
|
<li><strong>Release</strong> - Consists of a version bump commit directly on the master branch,
|
||||||
|
and a git tag named according to the new version string placed on said commit.</li>
|
||||||
|
<li><strong>Maintenance Release</strong> - Just like a regular release, except the version bump
|
||||||
|
commit and release tag are on a maintenance branch instead of the master
|
||||||
|
branch.</li>
|
||||||
|
</ul> </section> <!-- Main specification --> <section id="specification"> <h2>Specification</h2> <p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||||
|
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||||
|
interpreted as described in <a href="https://tools.ietf.org/html/rfc2119">RFC 2119</a>.</p>
|
||||||
|
<ol>
|
||||||
|
<li id="clause-1"><a href="#clause-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.</a>The Master Branch
|
||||||
|
<ol>
|
||||||
|
<li id="clause-1-1"><a href="#clause-1-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.1.</a>A branch named "master" MUST exist and it MUST be referred to as the
|
||||||
|
"master branch".</li>
|
||||||
|
<li id="clause-1-2"><a href="#clause-1-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.2.</a>The master branch MUST be considered bleeding edge.</li>
|
||||||
|
<li id="clause-1-3"><a href="#clause-1-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.3.</a>The master branch MUST always be in a non-broken state with its test
|
||||||
|
suite passing.</li>
|
||||||
|
<li id="clause-1-4"><a href="#clause-1-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.4.</a>The master branch SHOULD always be in a "as near as possible ready for
|
||||||
|
release/production" state to reduce the friction of creating a new
|
||||||
|
release.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-2"><a href="#clause-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.</a>Changes
|
||||||
|
<ol>
|
||||||
|
<li id="clause-2-1"><a href="#clause-2-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.1.</a>Changes MUST be performed on a separate branch that SHOULD be referred to
|
||||||
|
as a "change branch". All change branches MUST have descriptive names. It
|
||||||
|
is RECOMMENDED that you commit often locally, and you SHOULD regularly
|
||||||
|
push your work to the same named branch on the remote server.</li>
|
||||||
|
<li id="clause-2-2"><a href="#clause-2-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.2.</a>When a change branch is created, the branch that it is created from
|
||||||
|
SHOULD be referred to as the "source branch". Each change branch also
|
||||||
|
needs a designated "merge target branch", typically this will be the same
|
||||||
|
as the source branch.</li>
|
||||||
|
<li id="clause-2-3"><a href="#clause-2-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.3.</a>Change branches MUST be regularly updated with any changes from their
|
||||||
|
source branch. This MUST be done by rebasing the change branch on top of
|
||||||
|
the source branch. To be clear you MUST NOT merge a source branch into a
|
||||||
|
change branch.</li>
|
||||||
|
<li id="clause-2-4"><a href="#clause-2-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.4.</a>After rebasing a change branch on top of its source branch you MUST push
|
||||||
|
the change branch to the remote server. This will require you do a force
|
||||||
|
push, and you SHOULD use the "--force-with-lease" git push option.</li>
|
||||||
|
<li id="clause-2-5"><a href="#clause-2-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.5.</a>To merge a change branch into its merge target branch, you MUST open a
|
||||||
|
"pull request" (or equivalent) so others can review and approve your
|
||||||
|
changes.</li>
|
||||||
|
<li id="clause-2-6"><a href="#clause-2-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.6.</a>A pull request MUST only be merged when the change branch is up-to-date
|
||||||
|
with its source branch, the test suite is passing, and you and others are
|
||||||
|
happy with the change. This is especially important if the merge target
|
||||||
|
is the master branch.</li>
|
||||||
|
<li id="clause-2-7"><a href="#clause-2-7" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.7.</a>To get feedback, help, or generally just discuss a change branch with
|
||||||
|
others, it is RECOMMENDED you do this by creating a pull request and
|
||||||
|
discuss the changes with others there.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-3"><a href="#clause-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.</a>Git Best Practices
|
||||||
|
<ol>
|
||||||
|
<li id="clause-3-1"><a href="#clause-3-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.1.</a>All commit messages SHOULD follow the Commit Guidelines and format from
|
||||||
|
the official git
|
||||||
|
documentation:
|
||||||
|
<a href="https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project">https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project</a></li>
|
||||||
|
<li id="clause-3-2"><a href="#clause-3-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.2.</a>You SHOULD always use "--force-with-lease" when doing a force push. The
|
||||||
|
plain "--force" option is dangerous and destructive. More
|
||||||
|
information:
|
||||||
|
<a href="https://developer.atlassian.com/blog/2015/04/force-with-lease/">https://developer.atlassian.com/blog/2015/04/force-with-lease/</a></li>
|
||||||
|
<li id="clause-3-3"><a href="#clause-3-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.3.</a>You SHOULD understand and be comfortable with
|
||||||
|
rebasing: <a href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing">https://git-scm.com/book/en/v2/Git-Branching-Rebasing</a></li>
|
||||||
|
<li id="clause-3-4"><a href="#clause-3-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.4.</a>It is RECOMMENDED that you always do "git pull --rebase" instead of "git
|
||||||
|
pull" to avoid unnecessary merge commits. You can make this the default
|
||||||
|
behavior of "git pull" with "git config --global pull.rebase true".</li>
|
||||||
|
<li id="clause-3-5"><a href="#clause-3-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.5.</a>It is RECOMMENDED that all branches be merged using "git merge --no-ff".
|
||||||
|
This makes sure the reference to the original branch is kept in the commits,
|
||||||
|
allows one to revert a merge by reverting a single merge commit, and creates
|
||||||
|
a merge commit to mark the integration of the branch with master.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-4"><a href="#clause-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.</a>Versioning
|
||||||
|
<ol>
|
||||||
|
<li id="clause-4-1"><a href="#clause-4-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.1.</a>The project MUST have its version hard-coded somewhere in the
|
||||||
|
code-base. It is RECOMMENDED that this is done in a file called "VERSION"
|
||||||
|
located in the root of the project.</li>
|
||||||
|
<li id="clause-4-2"><a href="#clause-4-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.2.</a>If you are using a "VERSION" file in the root of the project, this MUST
|
||||||
|
only contain the exact version string.</li>
|
||||||
|
<li id="clause-4-3"><a href="#clause-4-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.3.</a>The version string SHOULD follow the Semantic Versioning
|
||||||
|
(<a href="http://semver.org/">http://semver.org/</a>) format. Use of Semantic Versioning is OPTIONAL,
|
||||||
|
but the version string MUST NOT have a "v" prefix. For example "v2.11.4"
|
||||||
|
is bad, and "2.11.4" is good.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-5"><a href="#clause-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.</a>Releases
|
||||||
|
<ol>
|
||||||
|
<li id="clause-5-1"><a href="#clause-5-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.1.</a>To create a new release, you MUST create a "version bump" commit directly
|
||||||
|
on the master branch which changes the hard-coded version value of the
|
||||||
|
project. The version bump commit MUST have a git tag created on it and
|
||||||
|
named as the exact version string.</li>
|
||||||
|
<li id="clause-5-2"><a href="#clause-5-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.2.</a>A version bump commit MUST have a commit message title of "Bump version
|
||||||
|
to VERSION". For example, if the new version string is "2.11.4", the
|
||||||
|
first line of the commit message MUST read: "Bump version to 2.11.4"</li>
|
||||||
|
<li id="clause-5-3"><a href="#clause-5-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.3.</a>The release tag on the version bump commit MUST be named exactly the same
|
||||||
|
as the version string. The tag name can OPTIONALLY be prefixed with
|
||||||
|
"v". For example the tag name can be either "2.11.4" or "v2.11.4".</li>
|
||||||
|
<li id="clause-5-4"><a href="#clause-5-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.4.</a>It is RECOMMENDED that release tags are lightweight tags, but you can
|
||||||
|
OPTIONALLY use annotated tags if you want to include changelog
|
||||||
|
information in the release tag itself.</li>
|
||||||
|
<li id="clause-5-5"><a href="#clause-5-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.5.</a>If you use annotated release tags, the first line of the annotation MUST
|
||||||
|
read "Release VERSION". For example for version "2.11.4" the first line
|
||||||
|
of the tag annotation would read "Release 2.11.4". The second line must
|
||||||
|
be blank, and the changelog MUST start on the third line.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-6"><a href="#clause-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.</a>Bug Fixes & Rollback
|
||||||
|
<ol>
|
||||||
|
<li id="clause-6-1"><a href="#clause-6-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.1.</a>You MUST NOT under any circumstances force push to the master branch.</li>
|
||||||
|
<li id="clause-6-2"><a href="#clause-6-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.2.</a>If a change branch which has been merged in to the master branch is found
|
||||||
|
to have a bug in it, the bug fix work MUST be done as a new separate
|
||||||
|
change branch and MUST follow the same workflow as any other change
|
||||||
|
branch.</li>
|
||||||
|
<li id="clause-6-3"><a href="#clause-6-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.3.</a>If a change branch is wrongfully merged in to master, or for any other
|
||||||
|
reason the merge must be undone, you MUST undo the merge by reverting the
|
||||||
|
merge commit itself. Effectively creating a new commit that reverses all
|
||||||
|
the relevant changes.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-7"><a href="#clause-7" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.</a>Maintenance Releases
|
||||||
|
<ol>
|
||||||
|
<li id="clause-7-1"><a href="#clause-7-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.1.</a>Any branch that has a name starting with "stable-" SHOULD be referred to
|
||||||
|
as a "maintenance branch".</li>
|
||||||
|
<li id="clause-7-2"><a href="#clause-7-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.2.</a>Maintenance branches are used for managing new releases of older
|
||||||
|
versions. Typically this is used to provide security updates for older
|
||||||
|
versions when the master branch has moved on to a point that a new
|
||||||
|
release for the old version cannot be made from the master branch.</li>
|
||||||
|
<li id="clause-7-3"><a href="#clause-7-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.3.</a>A "maintenance release" is identical to a regular release, except the
|
||||||
|
version bump commit and the release tag are placed on the maintenance
|
||||||
|
branch instead of on the master branch.</li>
|
||||||
|
<li id="clause-7-4"><a href="#clause-7-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.4.</a>A maintenance branch SHOULD follow a "stable-X.Y" naming pattern, where
|
||||||
|
"X" is the MAJOR version and "Y" is the minor version.</li>
|
||||||
|
<li id="clause-7-5"><a href="#clause-7-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.</a>A maintenance branch MUST be created from the relevant release tag. For
|
||||||
|
example if there is a security fix for all 2.9.x releases, the latest of
|
||||||
|
which is "2.9.7", we create a new branch called "stable-2.9" off of the
|
||||||
|
"2.9.7" release tag. The security fix release will then end up being
|
||||||
|
version "2.9.8".</li>
|
||||||
|
<li id="clause-7-6"><a href="#clause-7-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.6.</a>When working on a maintenance release, the relevant maintenance branch
|
||||||
|
MUST be thought of as the master branch for that maintenance work.</li>
|
||||||
|
<li id="clause-7-7"><a href="#clause-7-7" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.7.</a>Changes in a maintenance branch SHOULD typically come from work being
|
||||||
|
done against the master branch. Meaning changes SHOULD only trickle
|
||||||
|
downwards from the master branch. If a change needs to trickle back up
|
||||||
|
into the master branch, that work should have happened against the master
|
||||||
|
branch in the first place.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol> </section> </article> </div> </div> </div> </section> <script type="module">const i="clause-highlight";function a(t){t.classList.remove(i),t.offsetWidth,t.classList.add(i),setTimeout(()=>{t.classList.remove(i)},2e3)}function n(){const t=window.location.hash;if(!t||!t.startsWith("#clause-"))return;const s=t.slice(1),e=document.getElementById(s);e&&setTimeout(()=>a(e),100)}function h(){document.addEventListener("click",t=>{const s=t.target.closest('a[href^="#clause-"]');if(!s)return;const e=s.getAttribute("href");if(!e)return;const c=e.slice(1),o=document.getElementById(c);o&&setTimeout(()=>a(o),100)}),window.addEventListener("hashchange",n),window.location.hash?.startsWith("#clause-")&&(document.readyState==="complete"?n():window.addEventListener("load",n))}h();</script> <section id="faq" class="py-20 sm:py-28"> <div class="section-container"> <div class="max-w-3xl mx-auto"> <div class="mb-12 text-center"> <h2 class="text-3xl sm:text-4xl mb-4">FAQ</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> Common questions about Git Common-Flow </p> </div> <!-- FAQ Items --> <div class="space-y-0"> </div> </div> </div> </section> <script type="module">function n(){document.querySelectorAll("[data-faq-item]").forEach(r=>{const t=r.querySelector("[data-faq-trigger]"),a=r.querySelector("[data-faq-content]"),s=r.querySelector("[data-faq-icon]");!t||!a||!s||t.addEventListener("click",()=>{const e=t.getAttribute("aria-expanded")==="true";t.setAttribute("aria-expanded",e?"false":"true"),a.classList.toggle("grid-rows-[1fr]",!e),a.classList.toggle("grid-rows-[0fr]",e),s.classList.toggle("rotate-180",!e)})})}n();document.addEventListener("astro:after-swap",n);</script> </main> <footer class="pt-12 pb-6 my-28 text-sm
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
border-t border-gray-200 dark:border-neutral-800"> <div class="section-container flex flex-col sm:flex-row
|
||||||
|
sm:justify-between sm:items-center gap-2"> <p>
|
||||||
|
License:
|
||||||
|
<a href="https://creativecommons.org/licenses/by/4.0/" class="hover:text-sky-600" target="_blank" rel="noopener noreferrer"> CC BY 4.0 </a> </p> <p> Git Common-Flow by
|
||||||
|
<a href="https://jimeh.me/" class="hover:text-sky-600" target="_blank" rel="noopener noreferrer"> Jim Myhrberg </a> </p> </div> </footer> <!-- Re-init theme on Astro page transitions --> <script type="module">document.addEventListener("astro:after-swap",()=>{const e=localStorage.getItem("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches;e==="dark"||e!=="light"&&t?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")});</script> </body> </html>
|
||||||
2
docs/spec/1.0.0-rc.2.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
377
docs/spec/1.0.0-rc.2/index.html
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
<!DOCTYPE html><html lang="en"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="canonical" href="https://commonflow.org/spec/1.0.0-rc.2/"><title>Git Common-Flow 1.0.0-rc.2 | Git Common-Flow</title><meta name="description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta name="author" content="Jim Myhrberg"><!-- Open Graph --><meta property="og:title" content="Git Common-Flow 1.0.0-rc.2 | Git Common-Flow"><meta property="og:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta property="og:type" content="website"><meta property="og:url" content="https://commonflow.org/spec/1.0.0-rc.2/"><!-- Twitter --><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Git Common-Flow 1.0.0-rc.2 | Git Common-Flow"><meta name="twitter:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><!-- Favicon --><link rel="icon" href="/favicon.ico" sizes="32x32"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- Prevent flash of wrong theme --><script>
|
||||||
|
(function () {
|
||||||
|
const mode = localStorage.getItem("theme");
|
||||||
|
const prefersDark = window.matchMedia(
|
||||||
|
"(prefers-color-scheme: dark)",
|
||||||
|
).matches;
|
||||||
|
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
||||||
|
document.documentElement.classList.add("dark");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script><link rel="stylesheet" href="/_astro/index.qe8PXlQZ.css"></head> <body class="min-h-screen"> <header id="site-header" class="fixed top-0 inset-x-0 z-50 border-b border-transparent
|
||||||
|
translate-y-[-100%] transition-transform duration-300
|
||||||
|
backdrop-blur-xl bg-gray-50/85 dark:bg-neutral-950/85"> <div class="max-w-6xl mx-auto px-4 sm:px-6 h-16 flex items-center justify-between"> <!-- Logo / Title + Version --> <div class="flex items-center gap-3"> <a href="#hero" class="flex items-center gap-3 no-underline
|
||||||
|
text-gray-950 dark:text-neutral-50
|
||||||
|
hover:text-sky-600 transition-colors"> <span class="font-display font-bold text-lg tracking-tight">
|
||||||
|
Git Common-Flow
|
||||||
|
</span> </a> <div class="hidden md:block"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.2</span> <svg width="1em" height="1em" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <symbol id="ai:heroicons:chevron-down" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m19.5 8.25l-7.5 7.5l-7.5-7.5"/></symbol><use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> <script type="module">function c(){document.querySelectorAll("[data-version-selector]").forEach(e=>{if(e.dataset.initialized)return;e.dataset.initialized="true";const t=e.querySelector("[data-version-trigger]"),a=e.querySelector("[data-version-dropdown]"),n=e.querySelector("[data-arrow-icon]");if(!t||!a)return;const l=()=>{a.dataset.open="true",t.setAttribute("aria-expanded","true"),n&&(n.style.transform="rotate(180deg)")},o=()=>{delete a.dataset.open,t.setAttribute("aria-expanded","false"),n&&(n.style.transform="")};t.addEventListener("click",r=>{r.stopPropagation();const u=a.dataset.open==="true";document.querySelectorAll("[data-version-dropdown][data-open]").forEach(s=>{delete s.dataset.open;const i=s.previousElementSibling;i?.setAttribute("aria-expanded","false");const d=i?.querySelector("[data-arrow-icon]");d&&(d.style.transform="")}),u?o():l()}),document.addEventListener("click",r=>{e.contains(r.target)||o()}),document.addEventListener("keydown",r=>{r.key==="Escape"&&a.dataset.open==="true"&&(o(),t.focus())})})}c();document.addEventListener("astro:after-swap",c);</script> </div> </div> <!-- Desktop Navigation --> <nav class="hidden md:flex items-center gap-1"> <a href="#about" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="about"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:information-circle"> <symbol id="ai:heroicons:information-circle" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/></symbol><use href="#ai:heroicons:information-circle"></use> </svg> About </a><a href="#spec" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="spec"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:document-text"> <symbol id="ai:heroicons:document-text" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9"/></symbol><use href="#ai:heroicons:document-text"></use> </svg> Spec </a><a href="#faq" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="faq"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:question-mark-circle"> <symbol id="ai:heroicons:question-mark-circle" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.879 7.519c1.172-1.025 3.071-1.025 4.243 0c1.171 1.025 1.171 2.687 0 3.712q-.308.268-.67.442c-.746.361-1.452.999-1.452 1.827v.75M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9 5.25h.008v.008H12z"/></symbol><use href="#ai:heroicons:question-mark-circle"></use> </svg> FAQ </a> </nav> <!-- Right side: Theme, GitHub --> <div class="flex items-center gap-3"> <div class="relative group"> <button data-theme-toggle type="button" class="p-2 rounded-lg cursor-pointer transition-colors duration-200
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle theme"> <svg width="1em" height="1em" data-theme-icon="light" class="hidden w-5 h-5" data-icon="heroicons:sun"> <symbol id="ai:heroicons:sun" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0a3.75 3.75 0 0 1 7.5 0"/></symbol><use href="#ai:heroicons:sun"></use> </svg> <svg width="1em" height="1em" data-theme-icon="dark" class="hidden w-5 h-5" data-icon="heroicons:moon"> <symbol id="ai:heroicons:moon" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M21.752 15.002A9.7 9.7 0 0 1 18 15.75A9.75 9.75 0 0 1 8.25 6c0-1.33.266-2.597.748-3.752A9.75 9.75 0 0 0 3 11.25A9.75 9.75 0 0 0 12.75 21a9.75 9.75 0 0 0 9.002-5.998"/></symbol><use href="#ai:heroicons:moon"></use> </svg> <svg width="1em" height="1em" data-theme-icon="auto" class="hidden w-5 h-5" data-icon="heroicons:computer-desktop"> <symbol id="ai:heroicons:computer-desktop" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"/></symbol><use href="#ai:heroicons:computer-desktop"></use> </svg> </button> <!-- Tooltip --> <div class="absolute left-1/2 -translate-x-1/2 top-full mt-2
|
||||||
|
px-2 py-1 text-xs font-medium whitespace-nowrap rounded-md shadow-sm
|
||||||
|
bg-gray-900 text-white dark:bg-white dark:text-gray-900
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-200 pointer-events-none"> <span data-tooltip-text="light" class="hidden">Light</span> <span data-tooltip-text="dark" class="hidden">Dark</span> <span data-tooltip-text="auto" class="hidden">System</span> </div> </div> <script type="module">function r(){const c=document.querySelectorAll("[data-theme-toggle]");function n(){const e=localStorage.getItem("theme");return e==="dark"||e==="light"||e==="auto"?e:"auto"}function i(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function d(e){return e==="auto"?i():e}function s(e){document.querySelectorAll("[data-theme-icon]").forEach(t=>{const a=t.dataset.themeIcon;t.classList.toggle("hidden",a!==e)}),document.querySelectorAll("[data-tooltip-text]").forEach(t=>{const a=t.dataset.tooltipText;t.classList.toggle("hidden",a!==e)})}function o(e){d(e)==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark"),s(e)}function u(e){localStorage.setItem("theme",e),o(e)}function l(){const e=n();return e==="light"?"dark":e==="dark"?"auto":"light"}const f=n();o(f),c.forEach(e=>{e.dataset.initialized||(e.dataset.initialized="true",e.addEventListener("click",()=>{u(l())}))}),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{n()==="auto"&&o("auto")})}r();document.addEventListener("astro:after-swap",r);</script> <a href="https://github.com/jimeh/common-flow" target="_blank" rel="noopener noreferrer" class="p-2 rounded-lg transition-colors
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="View on GitHub"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="simple-icons:github"> <symbol id="ai:simple-icons:github" viewBox="0 0 24 24"><path fill="currentColor" d="M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></symbol><use href="#ai:simple-icons:github"></use> </svg> </a> <!-- Mobile menu button --> <button id="mobile-menu-btn" class="md:hidden p-2 rounded-lg
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle menu"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:bars-3"> <symbol id="ai:heroicons:bars-3" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/></symbol><use href="#ai:heroicons:bars-3"></use> </svg> </button> </div> </div> <!-- Mobile Navigation --> <nav id="mobile-nav" class="md:hidden hidden border-t border-gray-200 dark:border-neutral-800"> <div class="px-4 py-3 space-y-1 text-center"> <div class="py-2 flex justify-center"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.2</span> <svg width="1em" height="1em" viewBox="0 0 24 24" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> </div> <a href="#about" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="about"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:information-circle"> <use href="#ai:heroicons:information-circle"></use> </svg> About </a><a href="#spec" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="spec"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:document-text"> <use href="#ai:heroicons:document-text"></use> </svg> Spec </a><a href="#faq" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="faq"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:question-mark-circle"> <use href="#ai:heroicons:question-mark-circle"></use> </svg> FAQ </a> </div> </nav> </header> <script type="module" src="/_astro/Header.astro_astro_type_script_index_0_lang.ClIJVJFM.js"></script> <main> <section id="hero" class="relative min-h-[75vh] flex flex-col items-center justify-center
|
||||||
|
px-6 pt-16 pb-24 overflow-hidden"> <!-- Background gradient/texture --> <div class="absolute inset-0 bg-gradient-to-b
|
||||||
|
from-gray-100 to-gray-50
|
||||||
|
dark:from-neutral-900 dark:to-neutral-950"></div> <!-- Subtle grid pattern with fade --> <div class="absolute inset-0 opacity-[0.06] dark:opacity-[0.12]
|
||||||
|
bg-[linear-gradient(theme(colors.gray.950)_1px,transparent_1px),linear-gradient(90deg,theme(colors.gray.950)_1px,transparent_1px)]
|
||||||
|
dark:bg-[linear-gradient(theme(colors.neutral.600)_1px,transparent_1px),linear-gradient(90deg,theme(colors.neutral.600)_1px,transparent_1px)]
|
||||||
|
bg-[size:60px_60px] bg-center
|
||||||
|
[-webkit-mask-image:linear-gradient(to_bottom,black_20%,transparent_80%)]
|
||||||
|
[mask-image:linear-gradient(to_bottom,black_20%,transparent_80%)]"></div> <!-- Top bar with version & theme --> <div class="absolute top-0 inset-x-0 z-20 flex items-center justify-between
|
||||||
|
px-6 py-4 animate-fade-in-down"> <div class="flex items-center gap-3"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.2</span> <svg width="1em" height="1em" viewBox="0 0 24 24" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> </div> <div class="flex items-center gap-2"> <div class="relative group"> <button data-theme-toggle type="button" class="p-2 rounded-lg cursor-pointer transition-colors duration-200
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle theme"> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="light" class="hidden w-5 h-5" data-icon="heroicons:sun"> <use href="#ai:heroicons:sun"></use> </svg> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="dark" class="hidden w-5 h-5" data-icon="heroicons:moon"> <use href="#ai:heroicons:moon"></use> </svg> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="auto" class="hidden w-5 h-5" data-icon="heroicons:computer-desktop"> <use href="#ai:heroicons:computer-desktop"></use> </svg> </button> <!-- Tooltip --> <div class="absolute left-1/2 -translate-x-1/2 top-full mt-2
|
||||||
|
px-2 py-1 text-xs font-medium whitespace-nowrap rounded-md shadow-sm
|
||||||
|
bg-gray-900 text-white dark:bg-white dark:text-gray-900
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-200 pointer-events-none"> <span data-tooltip-text="light" class="hidden">Light</span> <span data-tooltip-text="dark" class="hidden">Dark</span> <span data-tooltip-text="auto" class="hidden">System</span> </div> </div> <a href="https://github.com/jimeh/common-flow" target="_blank" rel="noopener noreferrer" class="p-2 rounded-lg transition-colors
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-white/50 dark:hover:bg-neutral-800/50" aria-label="View on GitHub"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-5 h-5" data-icon="simple-icons:github"> <use href="#ai:simple-icons:github"></use> </svg> </a> </div> </div> <!-- Main content --> <div class="relative z-10 w-full max-w-4xl mx-auto text-center"> <!-- Title --> <h1 class="animate-fade-in-up mb-4
|
||||||
|
text-gray-950 dark:text-neutral-50">
|
||||||
|
Git Common-Flow
|
||||||
|
</h1> <!-- Tagline --> <p class="animate-fade-in-up delay-100
|
||||||
|
text-lg sm:text-xl max-w-2xl mx-auto mb-8
|
||||||
|
text-gray-600 dark:text-neutral-400">
|
||||||
|
A sensible git workflow for teams who ship
|
||||||
|
</p> <!-- Version badge --> <div class="animate-fade-in-up delay-200 mb-10"> <span class="inline-flex items-center px-3 py-1 font-mono text-xs font-medium
|
||||||
|
rounded-full border
|
||||||
|
bg-gray-100 border-gray-200 text-gray-500
|
||||||
|
dark:bg-neutral-800/50 dark:border-neutral-700 dark:text-neutral-400">
|
||||||
|
v1.0.0-rc.2 </span> </div> <!-- SVG Diagram --> <div class="animate-fade-in-up delay-300
|
||||||
|
relative mx-auto mb-12 p-4 sm:p-8
|
||||||
|
bg-white dark:bg-neutral-900
|
||||||
|
rounded-2xl shadow-lg dark:shadow-none
|
||||||
|
border border-gray-200 dark:border-neutral-800"> <img src="/spec/1.0.0-rc.2.svg" alt="Git Common-Flow diagram" class="w-full h-auto max-w-3xl mx-auto
|
||||||
|
dark:invert dark:hue-rotate-180 dark:contrast-90"> </div> <!-- Navigation links --> <nav class="animate-fade-in-up delay-400
|
||||||
|
flex flex-wrap items-center justify-center gap-4"> <a href="#about" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50">
|
||||||
|
About
|
||||||
|
</a> <a href="#spec" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
bg-sky-600 text-white
|
||||||
|
hover:bg-sky-500 hover:-translate-y-0.5 hover:shadow-md">
|
||||||
|
Read the Spec
|
||||||
|
</a> <a href="#faq" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50">
|
||||||
|
FAQ
|
||||||
|
</a> </nav> </div> <!-- Scroll indicator --> <a href="#about" class="absolute bottom-8 left-1/2 -translate-x-1/2
|
||||||
|
animate-fade-in delay-700
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-sky-600 transition-colors" aria-label="Scroll to content"> <svg width="1em" height="1em" class="w-6 h-6 animate-bounce-subtle" data-icon="heroicons:arrow-down"> <symbol id="ai:heroicons:arrow-down" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3"/></symbol><use href="#ai:heroicons:arrow-down"></use> </svg> </a> </section> <section id="about" class="py-20 sm:py-28"> <div class="section-container"> <div class="max-w-3xl mx-auto"> <div class="mb-12 text-center"> <h2 class="text-3xl sm:text-4xl mb-4">About Common-Flow</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> A practical git workflow that combines the best of GitHub Flow with versioned releases </p> </div> <!-- Introduction --> <div class="prose-spec mb-12"></div> <!-- Summary as feature cards --> <div class="mb-16"> <h3 class="text-xl font-display font-semibold mb-6
|
||||||
|
text-gray-950 dark:text-neutral-50">
|
||||||
|
Key Principles
|
||||||
|
</h3> <div class="prose-spec"><p>Common-Flow is an attempt to gather a sensible selection of the most common
|
||||||
|
usage patterns of git into a single and concise specification. It is based on
|
||||||
|
the <a href="http://scottchacon.com/2011/08/31/github-flow.html">original variant</a>
|
||||||
|
of <a href="https://guides.github.com/introduction/flow/">GitHub Flow</a>, while taking
|
||||||
|
into account how a lot of open source projects use git.</p>
|
||||||
|
<p>TL;DR: Common-Flow is basically GitHub Flow with the addition of versioned
|
||||||
|
releases, maintenance releases for old versions, and without the requirement to
|
||||||
|
deploy to production all the time.</p></div> </div> <!-- Feedback & License --> <div class="pt-8 border-t border-gray-200 dark:border-neutral-800"> <div class="grid sm:grid-cols-2 gap-8"> <div> <h4 class="text-sm font-semibold uppercase tracking-wider mb-3
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Feedback
|
||||||
|
</h4> <p class="text-gray-600 dark:text-neutral-400">
|
||||||
|
Please <a href="https://github.com/jimeh/common-flow/issues" class="text-sky-600 hover:text-sky-400" target="_blank" rel="noopener noreferrer">open an issue on GitHub</a>.
|
||||||
|
</p> </div> <div> <h4 class="text-sm font-semibold uppercase tracking-wider mb-3
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
License
|
||||||
|
</h4> <div class="text-gray-600 dark:text-neutral-400"><p><a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons - CC BY 3.0</a></p></div> </div> </div> </div> </div> </div> </section> <section id="spec" class="py-20 sm:py-28"> <div class="section-container"> <div class="mb-12 text-center max-w-3xl mx-auto"> <h2 class="text-3xl sm:text-4xl mb-4">The Specification</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> The complete Git Common-Flow specification </p> </div> <!-- Content with sidebar --> <div class="lg:flex lg:gap-8"> <!-- Sidebar --> <div class="lg:w-64 lg:flex-shrink-0"> <aside id="spec-sidebar" class="hidden lg:block lg:sticky lg:top-24 lg:self-start
|
||||||
|
lg:max-h-[calc(100vh-8rem)] lg:overflow-y-auto
|
||||||
|
lg:pr-8 lg:mr-8 lg:border-r border-gray-200 dark:border-neutral-800"> <nav class="space-y-1 py-2"> <div class="text-xs font-semibold uppercase tracking-wider mb-4
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Table of Contents
|
||||||
|
</div> <a href="#terminology" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-sidebar-link data-section-id="terminology"> <span>Terminology</span> </a><a href="#specification" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-sidebar-link data-section-id="specification"> <span>Specification</span> </a><a href="#clause-1" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-1"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 1. </span> <span>The Master Branch</span> </a><a href="#clause-2" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-2"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 2. </span> <span>Change Branches</span> </a><a href="#clause-3" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-3"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 3. </span> <span>Pull Requests</span> </a><a href="#clause-4" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-4"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 4. </span> <span>Versioning</span> </a><a href="#clause-5" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-5"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 5. </span> <span>Releases</span> </a><a href="#clause-6" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-6"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 6. </span> <span>Release Branches</span> </a><a href="#clause-7" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-7"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 7. </span> <span>Bug Fixes & Rollback</span> </a><a href="#clause-8" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-8"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 8. </span> <span>Git Best Practices</span> </a> </nav> </aside> <!-- Mobile floating button --> <button id="spec-toc-toggle" class="lg:hidden fixed bottom-6 right-6 z-40
|
||||||
|
w-12 h-12 rounded-full shadow-lg
|
||||||
|
bg-sky-600 text-white
|
||||||
|
flex items-center justify-center
|
||||||
|
hover:bg-sky-500
|
||||||
|
transition-all duration-200" aria-label="Jump to section"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:bars-3-bottom-left"> <symbol id="ai:heroicons:bars-3-bottom-left" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12"/></symbol><use href="#ai:heroicons:bars-3-bottom-left"></use> </svg> </button> <!-- Mobile TOC drawer --> <div id="spec-toc-drawer" class="lg:hidden fixed inset-0 z-50 hidden" data-toc-drawer> <!-- Backdrop --> <div class="absolute inset-0 bg-black/50" data-toc-backdrop></div> <!-- Drawer --> <div class="absolute bottom-0 inset-x-0 max-h-[70vh] overflow-y-auto
|
||||||
|
bg-gray-50 dark:bg-neutral-950
|
||||||
|
rounded-t-2xl shadow-xl p-6"> <div class="flex items-center justify-between mb-4"> <span class="text-sm font-semibold uppercase tracking-wider
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Jump to Section
|
||||||
|
</span> <button class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-neutral-800" data-toc-close aria-label="Close"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:x-mark"> <symbol id="ai:heroicons:x-mark" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18L18 6M6 6l12 12"/></symbol><use href="#ai:heroicons:x-mark"></use> </svg> </button> </div> <nav class="space-y-1"> <a href="#terminology" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-toc-link> <span>Terminology</span> </a><a href="#specification" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-toc-link> <span>Specification</span> </a><a href="#clause-1" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 1. </span> <span>The Master Branch</span> </a><a href="#clause-2" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 2. </span> <span>Change Branches</span> </a><a href="#clause-3" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 3. </span> <span>Pull Requests</span> </a><a href="#clause-4" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 4. </span> <span>Versioning</span> </a><a href="#clause-5" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 5. </span> <span>Releases</span> </a><a href="#clause-6" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 6. </span> <span>Release Branches</span> </a><a href="#clause-7" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 7. </span> <span>Bug Fixes & Rollback</span> </a><a href="#clause-8" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 8. </span> <span>Git Best Practices</span> </a> </nav> </div> </div> <script type="module" src="/_astro/SpecSidebar.astro_astro_type_script_index_0_lang.BQBj5HuJ.js"></script> </div> <!-- Main content --> <div class="flex-1 min-w-0"> <article class="prose-spec"> <!-- Terminology --> <section id="terminology"> <h2>Terminology</h2> <ul>
|
||||||
|
<li><strong>Master Branch</strong> - Must always have passing tests, is considered bleeding
|
||||||
|
edge, and must be named <code>master</code>.</li>
|
||||||
|
<li><strong>Change Branches</strong> - Any branch that introduces changes like a new feature, a
|
||||||
|
bug fix, etc.</li>
|
||||||
|
<li><strong>Source Branch</strong> - The branch that a change branch was created from. New
|
||||||
|
changes in the source branch should be incorporated into the change branch via
|
||||||
|
rebasing.</li>
|
||||||
|
<li><strong>Merge Target</strong> - A branch that is the intended merge target for a change
|
||||||
|
branch. Typically the merge target branch will be the same as the source
|
||||||
|
branch.</li>
|
||||||
|
<li><strong>Pull Request</strong> - A means of requesting that a change branch is merged in to
|
||||||
|
its merge target, allowing others to review, discuss and approve the changes.</li>
|
||||||
|
<li><strong>Release</strong> - Consists of a version bump commit, and a git tag named according
|
||||||
|
to the new version string placed on said commit.</li>
|
||||||
|
<li><strong>Release Branches</strong> - Used both for short-term preparations of a release, and
|
||||||
|
also for long-term maintenance of older version.</li>
|
||||||
|
</ul> </section> <!-- Main specification --> <section id="specification"> <h2>Specification</h2> <p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||||
|
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||||
|
interpreted as described in <a href="https://tools.ietf.org/html/rfc2119">RFC 2119</a>.</p>
|
||||||
|
<ol>
|
||||||
|
<li id="clause-1"><a href="#clause-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.</a>The Master Branch
|
||||||
|
<ol>
|
||||||
|
<li id="clause-1-1"><a href="#clause-1-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.1.</a>A branch named "master" MUST exist and it MUST be referred to as the
|
||||||
|
"master branch".</li>
|
||||||
|
<li id="clause-1-2"><a href="#clause-1-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.2.</a>The master branch MUST be considered bleeding edge.</li>
|
||||||
|
<li id="clause-1-3"><a href="#clause-1-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.3.</a>The master branch MUST always be in a non-broken state with its test
|
||||||
|
suite passing.</li>
|
||||||
|
<li id="clause-1-4"><a href="#clause-1-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.4.</a>The master branch SHOULD always be in a "as near as possibly ready for
|
||||||
|
release/production" state to reduce any friction with creating a new
|
||||||
|
release.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-2"><a href="#clause-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.</a>Change Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-2-1"><a href="#clause-2-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.1.</a>Each change (feature, bugfix, etc.) MUST be performed on separate
|
||||||
|
branches that SHOULD be referred to as "change branches". All change
|
||||||
|
branches MUST have descriptive names. It is RECOMMENDED that you commit
|
||||||
|
often locally, and you SHOULD regularly push your work to the same named
|
||||||
|
branch on the remote server.</li>
|
||||||
|
<li id="clause-2-2"><a href="#clause-2-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.2.</a>You MUST create separate change branches for each distinctly different
|
||||||
|
change. You MUST NOT include multiple unrelated changes into a single
|
||||||
|
change branch.</li>
|
||||||
|
<li id="clause-2-3"><a href="#clause-2-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.3.</a>When a change branch is created, the branch that it is created from
|
||||||
|
SHOULD be referred to as the "source branch". Each change branch also
|
||||||
|
needs a designated "merge target" branch, typically this will be the same
|
||||||
|
as the source branch.</li>
|
||||||
|
<li id="clause-2-4"><a href="#clause-2-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.4.</a>Change branches MUST be regularly updated with any changes from their
|
||||||
|
source branch. This MUST be done by rebasing the change branch on top of
|
||||||
|
the source branch.</li>
|
||||||
|
<li id="clause-2-5"><a href="#clause-2-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.5.</a>After rebasing a change branch on top of its source branch you MUST push
|
||||||
|
the change branch to the remote server. This will require you to do a
|
||||||
|
force push, and you SHOULD use the "--force-with-lease" git push option.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-3"><a href="#clause-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.</a>Pull Requests
|
||||||
|
<ol>
|
||||||
|
<li id="clause-3-1"><a href="#clause-3-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.1.</a>To merge a change branch into its merge target, you MUST open a "pull
|
||||||
|
request" (or equivalent) so others can review and approve your changes.</li>
|
||||||
|
<li id="clause-3-2"><a href="#clause-3-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.2.</a>A pull request MUST only be merged when the change branch is up-to-date
|
||||||
|
with its source branch, the test suite is passing, and you and others are
|
||||||
|
happy with the change. This is especially important if the merge target
|
||||||
|
is the master branch.</li>
|
||||||
|
<li id="clause-3-3"><a href="#clause-3-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.3.</a>To get feedback, help, or generally just discuss a change branch with
|
||||||
|
others, the RECOMMENDED way to do so is by creating a pull request and
|
||||||
|
discuss the changes with others there.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-4"><a href="#clause-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.</a>Versioning
|
||||||
|
<ol>
|
||||||
|
<li id="clause-4-1"><a href="#clause-4-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.1.</a>The project MUST have its version hard-coded somewhere in the
|
||||||
|
code-base. It is RECOMMENDED that this is done in a file called "VERSION"
|
||||||
|
located in the root of the project.</li>
|
||||||
|
<li id="clause-4-2"><a href="#clause-4-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.2.</a>If you are using a "VERSION" file in the root of the project, this MUST
|
||||||
|
only contain the exact version string.</li>
|
||||||
|
<li id="clause-4-3"><a href="#clause-4-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.3.</a>The version string SHOULD follow the Semantic Versioning
|
||||||
|
(<a href="http://semver.org/">http://semver.org/</a>) format. Use of Semantic Versioning is OPTIONAL,
|
||||||
|
but the version string MUST NOT have a "v" prefix. For example "v2.11.4"
|
||||||
|
is bad, and "2.11.4" is good.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-5"><a href="#clause-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.</a>Releases
|
||||||
|
<ol>
|
||||||
|
<li id="clause-5-1"><a href="#clause-5-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.1.</a>To create a new release, you MUST create a "version bump" commit which
|
||||||
|
changes the hard-coded version string of the project. The version bump
|
||||||
|
commit MUST have a git tag created on it and named as the exact version
|
||||||
|
string.</li>
|
||||||
|
<li id="clause-5-2"><a href="#clause-5-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.2.</a>If you are not using a release branch, then the version bump commit MUST
|
||||||
|
be created directly on the master branch.</li>
|
||||||
|
<li id="clause-5-3"><a href="#clause-5-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.3.</a>The version bump commit MUST have a commit message title of "Bump version
|
||||||
|
to VERSION". For example, if the new version string is "2.11.4", the
|
||||||
|
first line of the commit message MUST read: "Bump version to 2.11.4"</li>
|
||||||
|
<li id="clause-5-4"><a href="#clause-5-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.4.</a>The release tag on the version bump commit MUST be named exactly the same
|
||||||
|
as the version string. The tag name can OPTIONALLY be prefixed with
|
||||||
|
"v". For example the tag name can be either "2.11.4" or "v2.11.4". You
|
||||||
|
MUST not use a mix of "v" prefixed and non-prefixed tags. Pick one form
|
||||||
|
and stick to it.</li>
|
||||||
|
<li id="clause-5-5"><a href="#clause-5-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.5.</a>It is RECOMMENDED that release tags are lightweight tags, but you can
|
||||||
|
OPTIONALLY use annotated tags if you want to include changelog
|
||||||
|
information in the release tag itself.</li>
|
||||||
|
<li id="clause-5-6"><a href="#clause-5-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.6.</a>If you use annotated release tags, the first line of the annotation MUST
|
||||||
|
read "Release VERSION". For example for version "2.11.4" the first line
|
||||||
|
of the tag annotation would read "Release 2.11.4". The second line must
|
||||||
|
be blank, and the changelog MUST start on the third line.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-6"><a href="#clause-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.</a>Release Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-6-1"><a href="#clause-6-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.1.</a>Any branch that has a name starting with "release-" SHOULD be referred to
|
||||||
|
as a "release branch".</li>
|
||||||
|
<li id="clause-6-2"><a href="#clause-6-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.2.</a>Use of release branches is OPTIONAL.</li>
|
||||||
|
<li id="clause-6-3"><a href="#clause-6-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.3.</a>Changes in a release branch SHOULD typically come from work being
|
||||||
|
done against the master branch. Meaning changes SHOULD only trickle
|
||||||
|
downwards from the master branch. If a change needs to trickle back up
|
||||||
|
into the master branch, that work should have happened against the master
|
||||||
|
branch in the first place. One exception to this is version bump commits.</li>
|
||||||
|
<li id="clause-6-4"><a href="#clause-6-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.4.</a>There are two types of release branches; short-term, and long-term.</li>
|
||||||
|
<li id="clause-6-5"><a href="#clause-6-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.</a>Short-Term Release Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-6-5-1"><a href="#clause-6-5-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.1.</a>Used for creating a specific versioned release.</li>
|
||||||
|
<li id="clause-6-5-2"><a href="#clause-6-5-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.2.</a>A short-term release branch is RECOMMENDED if there is a lengthy
|
||||||
|
pre-release verification process to avoid a code freeze on the master
|
||||||
|
branch.</li>
|
||||||
|
<li id="clause-6-5-3"><a href="#clause-6-5-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.3.</a>MUST have a name of "release-VERSION". For example for version
|
||||||
|
"2.11.4" the release branch name MUST be "release-2.11.4".</li>
|
||||||
|
<li id="clause-6-5-4"><a href="#clause-6-5-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.4.</a>When using a short-term release branch, the version bump commit and
|
||||||
|
release tag MUST be made directly on the release branch itself.</li>
|
||||||
|
<li id="clause-6-5-5"><a href="#clause-6-5-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.5.</a>Only very minor changes should be performed on a short-term release
|
||||||
|
branch directly. Any larger changes SHOULD be done in the master
|
||||||
|
branch, and SHOULD be pulled into the release branch by rebasing it
|
||||||
|
on top of the master branch the same way a change branch pulls in
|
||||||
|
updates from its source branch.</li>
|
||||||
|
<li id="clause-6-5-6"><a href="#clause-6-5-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.6.</a>After the version bump commit and release tag have been created, the
|
||||||
|
release branch MUST be merged back into its source branch and then
|
||||||
|
deleted. Typically the source branch will be the master branch.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-6-6"><a href="#clause-6-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.6.</a>Long-Term Release Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-6-6-1"><a href="#clause-6-6-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.6.1.</a>Used for work on versions which are not currently part of the master
|
||||||
|
branch. Typically this is useful when you need to create a new
|
||||||
|
maintenance release for a older version.</li>
|
||||||
|
<li id="clause-6-6-2"><a href="#clause-6-6-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.6.2.</a>The branch name MUST have a non-specific version number. For example
|
||||||
|
a long-term release branch for creating new 2.9.x releases would be
|
||||||
|
named "release-2.9".</li>
|
||||||
|
<li id="clause-6-6-3"><a href="#clause-6-6-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.6.3.</a>To create a new release from a long-term release branch, you MUST
|
||||||
|
create a version bump commit and release tag directly on the release
|
||||||
|
branch.</li>
|
||||||
|
<li id="clause-6-6-4"><a href="#clause-6-6-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.6.4.</a>A long-term release branch MUST be created from the relevant release
|
||||||
|
tag. For example if the master branch is on version 2.11.4 and there
|
||||||
|
is a security fix for all 2.9.x releases, the latest of which is
|
||||||
|
"2.9.7". Create a new branch called "release-2.9" off of the "2.9.7"
|
||||||
|
release tag. The security fix release will then end up being version
|
||||||
|
"2.9.8".</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-7"><a href="#clause-7" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.</a>Bug Fixes & Rollback
|
||||||
|
<ol>
|
||||||
|
<li id="clause-7-1"><a href="#clause-7-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.1.</a>You MUST NOT under any circumstances force push to the master branch.</li>
|
||||||
|
<li id="clause-7-2"><a href="#clause-7-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.2.</a>If a change branch which has been merged into the master branch is found
|
||||||
|
to have a bug in it, the bug fix work MUST be done as a new separate
|
||||||
|
change branch and MUST follow the same workflow as any other change
|
||||||
|
branch.</li>
|
||||||
|
<li id="clause-7-3"><a href="#clause-7-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.3.</a>If a change branch is wrongfully merged into master, or for any other
|
||||||
|
reason the merge must be undone, you MUST undo the merge by reverting the
|
||||||
|
merge commit itself. Effectively creating a new commit that reverses all
|
||||||
|
the relevant changes.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-8"><a href="#clause-8" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.</a>Git Best Practices
|
||||||
|
<ol>
|
||||||
|
<li id="clause-8-1"><a href="#clause-8-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.1.</a>All commit messages SHOULD follow the Commit Guidelines and format from
|
||||||
|
the official git
|
||||||
|
documentation:
|
||||||
|
<a href="https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project">https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project</a></li>
|
||||||
|
<li id="clause-8-2"><a href="#clause-8-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.2.</a>You SHOULD never blindly commit all changes with "git commit -a". It is
|
||||||
|
RECOMMENDED you use "git add -i" to add individual changes to the staging
|
||||||
|
area so you are fully aware of what you are committing.</li>
|
||||||
|
<li id="clause-8-3"><a href="#clause-8-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.3.</a>You SHOULD always use "--force-with-lease" when doing a force push. The
|
||||||
|
regular "--force" option is dangerous and destructive. More
|
||||||
|
information:
|
||||||
|
<a href="https://developer.atlassian.com/blog/2015/04/force-with-lease/">https://developer.atlassian.com/blog/2015/04/force-with-lease/</a></li>
|
||||||
|
<li id="clause-8-4"><a href="#clause-8-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.4.</a>You SHOULD understand and be comfortable with
|
||||||
|
rebasing: <a href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing">https://git-scm.com/book/en/v2/Git-Branching-Rebasing</a></li>
|
||||||
|
<li id="clause-8-5"><a href="#clause-8-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.5.</a>It is RECOMMENDED that you always do "git pull --rebase" instead of "git
|
||||||
|
pull" to avoid unnecessary merge commits. You can make this the default
|
||||||
|
behavior of "git pull" with "git config --global pull.rebase true".</li>
|
||||||
|
<li id="clause-8-6"><a href="#clause-8-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.6.</a>It is RECOMMENDED that all branches be merged using "git merge --no-ff".
|
||||||
|
This makes sure the reference to the original branch is kept in the
|
||||||
|
commits, allows one to revert a merge by reverting a single merge commit,
|
||||||
|
and creates a merge commit to mark the integration of the branch with
|
||||||
|
master.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol> </section> </article> </div> </div> </div> </section> <script type="module">const i="clause-highlight";function a(t){t.classList.remove(i),t.offsetWidth,t.classList.add(i),setTimeout(()=>{t.classList.remove(i)},2e3)}function n(){const t=window.location.hash;if(!t||!t.startsWith("#clause-"))return;const s=t.slice(1),e=document.getElementById(s);e&&setTimeout(()=>a(e),100)}function h(){document.addEventListener("click",t=>{const s=t.target.closest('a[href^="#clause-"]');if(!s)return;const e=s.getAttribute("href");if(!e)return;const c=e.slice(1),o=document.getElementById(c);o&&setTimeout(()=>a(o),100)}),window.addEventListener("hashchange",n),window.location.hash?.startsWith("#clause-")&&(document.readyState==="complete"?n():window.addEventListener("load",n))}h();</script> <section id="faq" class="py-20 sm:py-28"> <div class="section-container"> <div class="max-w-3xl mx-auto"> <div class="mb-12 text-center"> <h2 class="text-3xl sm:text-4xl mb-4">FAQ</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> Common questions about Git Common-Flow </p> </div> <!-- FAQ Items --> <div class="space-y-0"> </div> </div> </div> </section> <script type="module">function n(){document.querySelectorAll("[data-faq-item]").forEach(r=>{const t=r.querySelector("[data-faq-trigger]"),a=r.querySelector("[data-faq-content]"),s=r.querySelector("[data-faq-icon]");!t||!a||!s||t.addEventListener("click",()=>{const e=t.getAttribute("aria-expanded")==="true";t.setAttribute("aria-expanded",e?"false":"true"),a.classList.toggle("grid-rows-[1fr]",!e),a.classList.toggle("grid-rows-[0fr]",e),s.classList.toggle("rotate-180",!e)})})}n();document.addEventListener("astro:after-swap",n);</script> </main> <footer class="pt-12 pb-6 my-28 text-sm
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
border-t border-gray-200 dark:border-neutral-800"> <div class="section-container flex flex-col sm:flex-row
|
||||||
|
sm:justify-between sm:items-center gap-2"> <p>
|
||||||
|
License:
|
||||||
|
<a href="https://creativecommons.org/licenses/by/4.0/" class="hover:text-sky-600" target="_blank" rel="noopener noreferrer"> CC BY 4.0 </a> </p> <p> Git Common-Flow by
|
||||||
|
<a href="https://jimeh.me/" class="hover:text-sky-600" target="_blank" rel="noopener noreferrer"> Jim Myhrberg </a> </p> </div> </footer> <!-- Re-init theme on Astro page transitions --> <script type="module">document.addEventListener("astro:after-swap",()=>{const e=localStorage.getItem("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches;e==="dark"||e!=="light"&&t?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")});</script> </body> </html>
|
||||||
2
docs/spec/1.0.0-rc.3.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
386
docs/spec/1.0.0-rc.3/index.html
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
<!DOCTYPE html><html lang="en"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="canonical" href="https://commonflow.org/spec/1.0.0-rc.3/"><title>Git Common-Flow 1.0.0-rc.3 | Git Common-Flow</title><meta name="description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta name="author" content="Jim Myhrberg"><!-- Open Graph --><meta property="og:title" content="Git Common-Flow 1.0.0-rc.3 | Git Common-Flow"><meta property="og:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><meta property="og:type" content="website"><meta property="og:url" content="https://commonflow.org/spec/1.0.0-rc.3/"><!-- Twitter --><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Git Common-Flow 1.0.0-rc.3 | Git Common-Flow"><meta name="twitter:description" content="An attempt to gather a sensible selection of the most common usage patterns of git into a single and concise specification."><!-- Favicon --><link rel="icon" href="/favicon.ico" sizes="32x32"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- Prevent flash of wrong theme --><script>
|
||||||
|
(function () {
|
||||||
|
const mode = localStorage.getItem("theme");
|
||||||
|
const prefersDark = window.matchMedia(
|
||||||
|
"(prefers-color-scheme: dark)",
|
||||||
|
).matches;
|
||||||
|
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
||||||
|
document.documentElement.classList.add("dark");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script><link rel="stylesheet" href="/_astro/index.qe8PXlQZ.css"></head> <body class="min-h-screen"> <header id="site-header" class="fixed top-0 inset-x-0 z-50 border-b border-transparent
|
||||||
|
translate-y-[-100%] transition-transform duration-300
|
||||||
|
backdrop-blur-xl bg-gray-50/85 dark:bg-neutral-950/85"> <div class="max-w-6xl mx-auto px-4 sm:px-6 h-16 flex items-center justify-between"> <!-- Logo / Title + Version --> <div class="flex items-center gap-3"> <a href="#hero" class="flex items-center gap-3 no-underline
|
||||||
|
text-gray-950 dark:text-neutral-50
|
||||||
|
hover:text-sky-600 transition-colors"> <span class="font-display font-bold text-lg tracking-tight">
|
||||||
|
Git Common-Flow
|
||||||
|
</span> </a> <div class="hidden md:block"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.3</span> <svg width="1em" height="1em" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <symbol id="ai:heroicons:chevron-down" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m19.5 8.25l-7.5 7.5l-7.5-7.5"/></symbol><use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> <script type="module">function c(){document.querySelectorAll("[data-version-selector]").forEach(e=>{if(e.dataset.initialized)return;e.dataset.initialized="true";const t=e.querySelector("[data-version-trigger]"),a=e.querySelector("[data-version-dropdown]"),n=e.querySelector("[data-arrow-icon]");if(!t||!a)return;const l=()=>{a.dataset.open="true",t.setAttribute("aria-expanded","true"),n&&(n.style.transform="rotate(180deg)")},o=()=>{delete a.dataset.open,t.setAttribute("aria-expanded","false"),n&&(n.style.transform="")};t.addEventListener("click",r=>{r.stopPropagation();const u=a.dataset.open==="true";document.querySelectorAll("[data-version-dropdown][data-open]").forEach(s=>{delete s.dataset.open;const i=s.previousElementSibling;i?.setAttribute("aria-expanded","false");const d=i?.querySelector("[data-arrow-icon]");d&&(d.style.transform="")}),u?o():l()}),document.addEventListener("click",r=>{e.contains(r.target)||o()}),document.addEventListener("keydown",r=>{r.key==="Escape"&&a.dataset.open==="true"&&(o(),t.focus())})})}c();document.addEventListener("astro:after-swap",c);</script> </div> </div> <!-- Desktop Navigation --> <nav class="hidden md:flex items-center gap-1"> <a href="#about" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="about"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:information-circle"> <symbol id="ai:heroicons:information-circle" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/></symbol><use href="#ai:heroicons:information-circle"></use> </svg> About </a><a href="#spec" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="spec"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:document-text"> <symbol id="ai:heroicons:document-text" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9"/></symbol><use href="#ai:heroicons:document-text"></use> </svg> Spec </a><a href="#faq" class="nav-link inline-flex items-center gap-1.5 px-4 py-2 text-sm
|
||||||
|
font-medium rounded-lg transition-colors cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50" data-nav-link data-section-id="faq"> <svg width="1em" height="1em" class="w-4 h-4" data-icon="heroicons:question-mark-circle"> <symbol id="ai:heroicons:question-mark-circle" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.879 7.519c1.172-1.025 3.071-1.025 4.243 0c1.171 1.025 1.171 2.687 0 3.712q-.308.268-.67.442c-.746.361-1.452.999-1.452 1.827v.75M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9 5.25h.008v.008H12z"/></symbol><use href="#ai:heroicons:question-mark-circle"></use> </svg> FAQ </a> </nav> <!-- Right side: Theme, GitHub --> <div class="flex items-center gap-3"> <div class="relative group"> <button data-theme-toggle type="button" class="p-2 rounded-lg cursor-pointer transition-colors duration-200
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle theme"> <svg width="1em" height="1em" data-theme-icon="light" class="hidden w-5 h-5" data-icon="heroicons:sun"> <symbol id="ai:heroicons:sun" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0a3.75 3.75 0 0 1 7.5 0"/></symbol><use href="#ai:heroicons:sun"></use> </svg> <svg width="1em" height="1em" data-theme-icon="dark" class="hidden w-5 h-5" data-icon="heroicons:moon"> <symbol id="ai:heroicons:moon" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M21.752 15.002A9.7 9.7 0 0 1 18 15.75A9.75 9.75 0 0 1 8.25 6c0-1.33.266-2.597.748-3.752A9.75 9.75 0 0 0 3 11.25A9.75 9.75 0 0 0 12.75 21a9.75 9.75 0 0 0 9.002-5.998"/></symbol><use href="#ai:heroicons:moon"></use> </svg> <svg width="1em" height="1em" data-theme-icon="auto" class="hidden w-5 h-5" data-icon="heroicons:computer-desktop"> <symbol id="ai:heroicons:computer-desktop" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"/></symbol><use href="#ai:heroicons:computer-desktop"></use> </svg> </button> <!-- Tooltip --> <div class="absolute left-1/2 -translate-x-1/2 top-full mt-2
|
||||||
|
px-2 py-1 text-xs font-medium whitespace-nowrap rounded-md shadow-sm
|
||||||
|
bg-gray-900 text-white dark:bg-white dark:text-gray-900
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-200 pointer-events-none"> <span data-tooltip-text="light" class="hidden">Light</span> <span data-tooltip-text="dark" class="hidden">Dark</span> <span data-tooltip-text="auto" class="hidden">System</span> </div> </div> <script type="module">function r(){const c=document.querySelectorAll("[data-theme-toggle]");function n(){const e=localStorage.getItem("theme");return e==="dark"||e==="light"||e==="auto"?e:"auto"}function i(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function d(e){return e==="auto"?i():e}function s(e){document.querySelectorAll("[data-theme-icon]").forEach(t=>{const a=t.dataset.themeIcon;t.classList.toggle("hidden",a!==e)}),document.querySelectorAll("[data-tooltip-text]").forEach(t=>{const a=t.dataset.tooltipText;t.classList.toggle("hidden",a!==e)})}function o(e){d(e)==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark"),s(e)}function u(e){localStorage.setItem("theme",e),o(e)}function l(){const e=n();return e==="light"?"dark":e==="dark"?"auto":"light"}const f=n();o(f),c.forEach(e=>{e.dataset.initialized||(e.dataset.initialized="true",e.addEventListener("click",()=>{u(l())}))}),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{n()==="auto"&&o("auto")})}r();document.addEventListener("astro:after-swap",r);</script> <a href="https://github.com/jimeh/common-flow" target="_blank" rel="noopener noreferrer" class="p-2 rounded-lg transition-colors
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="View on GitHub"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="simple-icons:github"> <symbol id="ai:simple-icons:github" viewBox="0 0 24 24"><path fill="currentColor" d="M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></symbol><use href="#ai:simple-icons:github"></use> </svg> </a> <!-- Mobile menu button --> <button id="mobile-menu-btn" class="md:hidden p-2 rounded-lg
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle menu"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:bars-3"> <symbol id="ai:heroicons:bars-3" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/></symbol><use href="#ai:heroicons:bars-3"></use> </svg> </button> </div> </div> <!-- Mobile Navigation --> <nav id="mobile-nav" class="md:hidden hidden border-t border-gray-200 dark:border-neutral-800"> <div class="px-4 py-3 space-y-1 text-center"> <div class="py-2 flex justify-center"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.3</span> <svg width="1em" height="1em" viewBox="0 0 24 24" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> </div> <a href="#about" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="about"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:information-circle"> <use href="#ai:heroicons:information-circle"></use> </svg> About </a><a href="#spec" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="spec"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:document-text"> <use href="#ai:heroicons:document-text"></use> </svg> Spec </a><a href="#faq" class="nav-link flex items-center justify-center gap-1.5 py-2
|
||||||
|
text-gray-600 dark:text-neutral-400 hover:text-sky-600" data-nav-link data-section-id="faq"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-4 h-4" data-icon="heroicons:question-mark-circle"> <use href="#ai:heroicons:question-mark-circle"></use> </svg> FAQ </a> </div> </nav> </header> <script type="module" src="/_astro/Header.astro_astro_type_script_index_0_lang.ClIJVJFM.js"></script> <main> <section id="hero" class="relative min-h-[75vh] flex flex-col items-center justify-center
|
||||||
|
px-6 pt-16 pb-24 overflow-hidden"> <!-- Background gradient/texture --> <div class="absolute inset-0 bg-gradient-to-b
|
||||||
|
from-gray-100 to-gray-50
|
||||||
|
dark:from-neutral-900 dark:to-neutral-950"></div> <!-- Subtle grid pattern with fade --> <div class="absolute inset-0 opacity-[0.06] dark:opacity-[0.12]
|
||||||
|
bg-[linear-gradient(theme(colors.gray.950)_1px,transparent_1px),linear-gradient(90deg,theme(colors.gray.950)_1px,transparent_1px)]
|
||||||
|
dark:bg-[linear-gradient(theme(colors.neutral.600)_1px,transparent_1px),linear-gradient(90deg,theme(colors.neutral.600)_1px,transparent_1px)]
|
||||||
|
bg-[size:60px_60px] bg-center
|
||||||
|
[-webkit-mask-image:linear-gradient(to_bottom,black_20%,transparent_80%)]
|
||||||
|
[mask-image:linear-gradient(to_bottom,black_20%,transparent_80%)]"></div> <!-- Top bar with version & theme --> <div class="absolute top-0 inset-x-0 z-20 flex items-center justify-between
|
||||||
|
px-6 py-4 animate-fade-in-down"> <div class="flex items-center gap-3"> <div class="relative" data-version-selector> <!-- Trigger button --> <button type="button" data-version-trigger aria-haspopup="listbox" aria-expanded="false" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-mono
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-md bg-transparent cursor-pointer transition-colors
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:border-sky-600 hover:text-gray-950 dark:hover:text-neutral-50"> <span>v1.0.0-rc.3</span> <svg width="1em" height="1em" viewBox="0 0 24 24" data-arrow-icon="true" class="w-3.5 h-3.5 transition-transform duration-150" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <!-- Dropdown menu --> <div data-version-dropdown role="listbox" aria-label="Select version" class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
|
bg-gray-50 dark:bg-neutral-900
|
||||||
|
border border-gray-200 dark:border-neutral-700
|
||||||
|
rounded-lg shadow-lg
|
||||||
|
opacity-0 invisible -translate-y-1 transition-all duration-150
|
||||||
|
data-[open]:opacity-100 data-[open]:visible data-[open]:translate-y-0"> <a href="/spec/1.0.0-rc.5" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.5 </a><a href="/spec/1.0.0-rc.4" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.4 </a><a href="/spec/1.0.0-rc.3" role="option" aria-selected="true" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50 bg-sky-500/15 dark:bg-sky-500/20 text-sky-600 dark:text-sky-400">
|
||||||
|
v1.0.0-rc.3 </a><a href="/spec/1.0.0-rc.2" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.2 </a><a href="/spec/1.0.0-rc.1" role="option" aria-selected="false" class="block px-3 py-2 font-mono text-sm rounded transition-colors text-gray-600 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-800 hover:text-gray-950 dark:hover:text-neutral-50">
|
||||||
|
v1.0.0-rc.1 </a> </div> </div> </div> <div class="flex items-center gap-2"> <div class="relative group"> <button data-theme-toggle type="button" class="p-2 rounded-lg cursor-pointer transition-colors duration-200
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-gray-100 dark:hover:bg-neutral-800" aria-label="Toggle theme"> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="light" class="hidden w-5 h-5" data-icon="heroicons:sun"> <use href="#ai:heroicons:sun"></use> </svg> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="dark" class="hidden w-5 h-5" data-icon="heroicons:moon"> <use href="#ai:heroicons:moon"></use> </svg> <svg width="1em" height="1em" viewBox="0 0 24 24" data-theme-icon="auto" class="hidden w-5 h-5" data-icon="heroicons:computer-desktop"> <use href="#ai:heroicons:computer-desktop"></use> </svg> </button> <!-- Tooltip --> <div class="absolute left-1/2 -translate-x-1/2 top-full mt-2
|
||||||
|
px-2 py-1 text-xs font-medium whitespace-nowrap rounded-md shadow-sm
|
||||||
|
bg-gray-900 text-white dark:bg-white dark:text-gray-900
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-200 pointer-events-none"> <span data-tooltip-text="light" class="hidden">Light</span> <span data-tooltip-text="dark" class="hidden">Dark</span> <span data-tooltip-text="auto" class="hidden">System</span> </div> </div> <a href="https://github.com/jimeh/common-flow" target="_blank" rel="noopener noreferrer" class="p-2 rounded-lg transition-colors
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-gray-950 dark:hover:text-neutral-50
|
||||||
|
hover:bg-white/50 dark:hover:bg-neutral-800/50" aria-label="View on GitHub"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-5 h-5" data-icon="simple-icons:github"> <use href="#ai:simple-icons:github"></use> </svg> </a> </div> </div> <!-- Main content --> <div class="relative z-10 w-full max-w-4xl mx-auto text-center"> <!-- Title --> <h1 class="animate-fade-in-up mb-4
|
||||||
|
text-gray-950 dark:text-neutral-50">
|
||||||
|
Git Common-Flow
|
||||||
|
</h1> <!-- Tagline --> <p class="animate-fade-in-up delay-100
|
||||||
|
text-lg sm:text-xl max-w-2xl mx-auto mb-8
|
||||||
|
text-gray-600 dark:text-neutral-400">
|
||||||
|
A sensible git workflow for teams who ship
|
||||||
|
</p> <!-- Version badge --> <div class="animate-fade-in-up delay-200 mb-10"> <span class="inline-flex items-center px-3 py-1 font-mono text-xs font-medium
|
||||||
|
rounded-full border
|
||||||
|
bg-gray-100 border-gray-200 text-gray-500
|
||||||
|
dark:bg-neutral-800/50 dark:border-neutral-700 dark:text-neutral-400">
|
||||||
|
v1.0.0-rc.3 </span> </div> <!-- SVG Diagram --> <div class="animate-fade-in-up delay-300
|
||||||
|
relative mx-auto mb-12 p-4 sm:p-8
|
||||||
|
bg-white dark:bg-neutral-900
|
||||||
|
rounded-2xl shadow-lg dark:shadow-none
|
||||||
|
border border-gray-200 dark:border-neutral-800"> <img src="/spec/1.0.0-rc.3.svg" alt="Git Common-Flow diagram" class="w-full h-auto max-w-3xl mx-auto
|
||||||
|
dark:invert dark:hue-rotate-180 dark:contrast-90"> </div> <!-- Navigation links --> <nav class="animate-fade-in-up delay-400
|
||||||
|
flex flex-wrap items-center justify-center gap-4"> <a href="#about" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50">
|
||||||
|
About
|
||||||
|
</a> <a href="#spec" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
bg-sky-600 text-white
|
||||||
|
hover:bg-sky-500 hover:-translate-y-0.5 hover:shadow-md">
|
||||||
|
Read the Spec
|
||||||
|
</a> <a href="#faq" class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50">
|
||||||
|
FAQ
|
||||||
|
</a> </nav> </div> <!-- Scroll indicator --> <a href="#about" class="absolute bottom-8 left-1/2 -translate-x-1/2
|
||||||
|
animate-fade-in delay-700
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
hover:text-sky-600 transition-colors" aria-label="Scroll to content"> <svg width="1em" height="1em" class="w-6 h-6 animate-bounce-subtle" data-icon="heroicons:arrow-down"> <symbol id="ai:heroicons:arrow-down" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3"/></symbol><use href="#ai:heroicons:arrow-down"></use> </svg> </a> </section> <section id="about" class="py-20 sm:py-28"> <div class="section-container"> <div class="max-w-3xl mx-auto"> <div class="mb-12 text-center"> <h2 class="text-3xl sm:text-4xl mb-4">About Common-Flow</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> A practical git workflow that combines the best of GitHub Flow with versioned releases </p> </div> <!-- Introduction --> <div class="prose-spec mb-12"></div> <!-- Summary as feature cards --> <div class="mb-16"> <h3 class="text-xl font-display font-semibold mb-6
|
||||||
|
text-gray-950 dark:text-neutral-50">
|
||||||
|
Key Principles
|
||||||
|
</h3> <div class="prose-spec"><p>Common-Flow is an attempt to gather a sensible selection of the most common
|
||||||
|
usage patterns of git into a single and concise specification. It is based on
|
||||||
|
the <a href="http://scottchacon.com/2011/08/31/github-flow.html">original variant</a>
|
||||||
|
of <a href="https://guides.github.com/introduction/flow/">GitHub Flow</a>, while taking
|
||||||
|
into account how a lot of open source projects use git.</p>
|
||||||
|
<p>In short, Common-Flow is essentially GitHub Flow with the addition of versioned
|
||||||
|
releases, optional release branches, and without the requirement to deploy to
|
||||||
|
production all the time.</p></div> </div> <!-- Feedback & License --> <div class="pt-8 border-t border-gray-200 dark:border-neutral-800"> <div class="grid sm:grid-cols-2 gap-8"> <div> <h4 class="text-sm font-semibold uppercase tracking-wider mb-3
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Feedback
|
||||||
|
</h4> <p class="text-gray-600 dark:text-neutral-400">
|
||||||
|
Please <a href="https://github.com/jimeh/common-flow/issues" class="text-sky-600 hover:text-sky-400" target="_blank" rel="noopener noreferrer">open an issue on GitHub</a>.
|
||||||
|
</p> </div> <div> <h4 class="text-sm font-semibold uppercase tracking-wider mb-3
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
License
|
||||||
|
</h4> <div class="text-gray-600 dark:text-neutral-400"><p><a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons - CC BY 3.0</a></p></div> </div> </div> </div> </div> </div> </section> <section id="spec" class="py-20 sm:py-28"> <div class="section-container"> <div class="mb-12 text-center max-w-3xl mx-auto"> <h2 class="text-3xl sm:text-4xl mb-4">The Specification</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> The complete Git Common-Flow specification </p> </div> <!-- Content with sidebar --> <div class="lg:flex lg:gap-8"> <!-- Sidebar --> <div class="lg:w-64 lg:flex-shrink-0"> <aside id="spec-sidebar" class="hidden lg:block lg:sticky lg:top-24 lg:self-start
|
||||||
|
lg:max-h-[calc(100vh-8rem)] lg:overflow-y-auto
|
||||||
|
lg:pr-8 lg:mr-8 lg:border-r border-gray-200 dark:border-neutral-800"> <nav class="space-y-1 py-2"> <div class="text-xs font-semibold uppercase tracking-wider mb-4
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Table of Contents
|
||||||
|
</div> <a href="#terminology" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-sidebar-link data-section-id="terminology"> <span>Terminology</span> </a><a href="#specification" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-sidebar-link data-section-id="specification"> <span>Specification</span> </a><a href="#clause-1" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-1"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 1. </span> <span>TL;DR</span> </a><a href="#clause-2" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-2"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 2. </span> <span>The Master Branch</span> </a><a href="#clause-3" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-3"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 3. </span> <span>Change Branches</span> </a><a href="#clause-4" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-4"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 4. </span> <span>Pull Requests</span> </a><a href="#clause-5" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-5"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 5. </span> <span>Versioning</span> </a><a href="#clause-6" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-6"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 6. </span> <span>Releases</span> </a><a href="#clause-7" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-7"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 7. </span> <span>Release Branches</span> </a><a href="#clause-8" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-8"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 8. </span> <span>Bug Fixes & Rollback</span> </a><a href="#clause-9" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-sidebar-link data-section-id="clause-9"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 9. </span> <span>Git Best Practices</span> </a> </nav> </aside> <!-- Mobile floating button --> <button id="spec-toc-toggle" class="lg:hidden fixed bottom-6 right-6 z-40
|
||||||
|
w-12 h-12 rounded-full shadow-lg
|
||||||
|
bg-sky-600 text-white
|
||||||
|
flex items-center justify-center
|
||||||
|
hover:bg-sky-500
|
||||||
|
transition-all duration-200" aria-label="Jump to section"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:bars-3-bottom-left"> <symbol id="ai:heroicons:bars-3-bottom-left" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12"/></symbol><use href="#ai:heroicons:bars-3-bottom-left"></use> </svg> </button> <!-- Mobile TOC drawer --> <div id="spec-toc-drawer" class="lg:hidden fixed inset-0 z-50 hidden" data-toc-drawer> <!-- Backdrop --> <div class="absolute inset-0 bg-black/50" data-toc-backdrop></div> <!-- Drawer --> <div class="absolute bottom-0 inset-x-0 max-h-[70vh] overflow-y-auto
|
||||||
|
bg-gray-50 dark:bg-neutral-950
|
||||||
|
rounded-t-2xl shadow-xl p-6"> <div class="flex items-center justify-between mb-4"> <span class="text-sm font-semibold uppercase tracking-wider
|
||||||
|
text-gray-500 dark:text-neutral-500">
|
||||||
|
Jump to Section
|
||||||
|
</span> <button class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-neutral-800" data-toc-close aria-label="Close"> <svg width="1em" height="1em" class="w-5 h-5" data-icon="heroicons:x-mark"> <symbol id="ai:heroicons:x-mark" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18L18 6M6 6l12 12"/></symbol><use href="#ai:heroicons:x-mark"></use> </svg> </button> </div> <nav class="space-y-1"> <a href="#terminology" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-toc-link> <span>Terminology</span> </a><a href="#specification" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800" data-toc-link> <span>Specification</span> </a><a href="#clause-1" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 1. </span> <span>TL;DR</span> </a><a href="#clause-2" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 2. </span> <span>The Master Branch</span> </a><a href="#clause-3" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 3. </span> <span>Change Branches</span> </a><a href="#clause-4" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 4. </span> <span>Pull Requests</span> </a><a href="#clause-5" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 5. </span> <span>Versioning</span> </a><a href="#clause-6" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 6. </span> <span>Releases</span> </a><a href="#clause-7" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 7. </span> <span>Release Branches</span> </a><a href="#clause-8" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 8. </span> <span>Bug Fixes & Rollback</span> </a><a href="#clause-9" class="sidebar-link block py-2 px-4 text-sm rounded-md transition-colors text-gray-500 hover:text-gray-950 hover:bg-gray-100 dark:text-neutral-500 dark:hover:text-neutral-50 dark:hover:bg-neutral-800 pl-6 text-[0.8125rem] flex" data-toc-link> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 9. </span> <span>Git Best Practices</span> </a> </nav> </div> </div> <script type="module" src="/_astro/SpecSidebar.astro_astro_type_script_index_0_lang.BQBj5HuJ.js"></script> </div> <!-- Main content --> <div class="flex-1 min-w-0"> <article class="prose-spec"> <!-- Terminology --> <section id="terminology"> <h2>Terminology</h2> <ul>
|
||||||
|
<li><strong>Master Branch</strong> - Must be named "master", must always have passing tests,
|
||||||
|
and is not guaranteed to always work in production environments.</li>
|
||||||
|
<li><strong>Change Branches</strong> - Any branch that introduces changes like a new feature, a
|
||||||
|
bug fix, etc.</li>
|
||||||
|
<li><strong>Source Branch</strong> - The branch that a change branch was created from. New
|
||||||
|
changes in the source branch should be incorporated into the change branch via
|
||||||
|
rebasing.</li>
|
||||||
|
<li><strong>Merge Target</strong> - A branch that is the intended merge target for a change
|
||||||
|
branch. Typically the merge target branch will be the same as the source
|
||||||
|
branch.</li>
|
||||||
|
<li><strong>Pull Request</strong> - A means of requesting that a change branch is merged in to
|
||||||
|
its merge target, allowing others to review, discuss and approve the changes.</li>
|
||||||
|
<li><strong>Release</strong> - May be considered safe to use in production
|
||||||
|
environments. Consists of a version bump commit, and a git tag named according
|
||||||
|
to the new version string placed on said commit.</li>
|
||||||
|
<li><strong>Release Branches</strong> - Used both for short-term preparations of a release, and
|
||||||
|
also for long-term maintenance of older version.</li>
|
||||||
|
</ul> </section> <!-- Main specification --> <section id="specification"> <h2>Specification</h2> <p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||||
|
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||||
|
interpreted as described in <a href="https://tools.ietf.org/html/rfc2119">RFC 2119</a>.</p>
|
||||||
|
<ol>
|
||||||
|
<li id="clause-1"><a href="#clause-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.</a>TL;DR
|
||||||
|
<ol>
|
||||||
|
<li id="clause-1-1"><a href="#clause-1-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.1.</a>Don't break the master branch.</li>
|
||||||
|
<li id="clause-1-2"><a href="#clause-1-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>1.2.</a>A release is a git tag.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-2"><a href="#clause-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.</a>The Master Branch
|
||||||
|
<ol>
|
||||||
|
<li id="clause-2-1"><a href="#clause-2-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.1.</a>A branch named "master" MUST exist and it MUST be referred to as the
|
||||||
|
"master branch".</li>
|
||||||
|
<li id="clause-2-2"><a href="#clause-2-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.2.</a>The master branch MUST always be in a non-broken state with its test
|
||||||
|
suite passing.</li>
|
||||||
|
<li id="clause-2-3"><a href="#clause-2-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.3.</a>The master branch IS NOT guaranteed to always work in production
|
||||||
|
environments. Despite test suites passing it may at times contain
|
||||||
|
unfinished work. Only releases may be considered safe for production use.</li>
|
||||||
|
<li id="clause-2-4"><a href="#clause-2-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>2.4.</a>The master branch SHOULD always be in a "as near as possibly ready for
|
||||||
|
release/production" state to reduce any friction with creating a new
|
||||||
|
release.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-3"><a href="#clause-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.</a>Change Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-3-1"><a href="#clause-3-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.1.</a>Each change (feature, bugfix, etc.) MUST be performed on separate
|
||||||
|
branches that SHOULD be referred to as "change branches". All change
|
||||||
|
branches MUST have descriptive names. It is RECOMMENDED that you commit
|
||||||
|
often locally, and you SHOULD regularly push your work to the same named
|
||||||
|
branch on the remote server.</li>
|
||||||
|
<li id="clause-3-2"><a href="#clause-3-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.2.</a>You MUST create separate change branches for each distinctly different
|
||||||
|
change. You MUST NOT include multiple unrelated changes into a single
|
||||||
|
change branch.</li>
|
||||||
|
<li id="clause-3-3"><a href="#clause-3-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.3.</a>When a change branch is created, the branch that it is created from
|
||||||
|
SHOULD be referred to as the "source branch". Each change branch also
|
||||||
|
needs a designated "merge target" branch, typically this will be the same
|
||||||
|
as the source branch.</li>
|
||||||
|
<li id="clause-3-4"><a href="#clause-3-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.4.</a>Change branches MUST be regularly updated with any changes from their
|
||||||
|
source branch. This MUST be done by rebasing the change branch on top of
|
||||||
|
the source branch.</li>
|
||||||
|
<li id="clause-3-5"><a href="#clause-3-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>3.5.</a>After rebasing a change branch on top of its source branch you MUST push
|
||||||
|
the change branch to the remote server. This will require you to do a
|
||||||
|
force push, and you SHOULD use the "--force-with-lease" git push option.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-4"><a href="#clause-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.</a>Pull Requests
|
||||||
|
<ol>
|
||||||
|
<li id="clause-4-1"><a href="#clause-4-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.1.</a>To merge a change branch into its merge target, you MUST open a "pull
|
||||||
|
request" (or equivalent) so others can review and approve your changes.</li>
|
||||||
|
<li id="clause-4-2"><a href="#clause-4-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.2.</a>A pull request MUST only be merged when the change branch is up-to-date
|
||||||
|
with its source branch, the test suite is passing, and you and others are
|
||||||
|
happy with the change. This is especially important if the merge target
|
||||||
|
is the master branch.</li>
|
||||||
|
<li id="clause-4-3"><a href="#clause-4-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>4.3.</a>To get feedback, help, or generally just discuss a change branch with
|
||||||
|
others, the RECOMMENDED way to do so is by creating a pull request and
|
||||||
|
discuss the changes with others there.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-5"><a href="#clause-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.</a>Versioning
|
||||||
|
<ol>
|
||||||
|
<li id="clause-5-1"><a href="#clause-5-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.1.</a>The project MUST have its version hard-coded somewhere in the
|
||||||
|
code-base. It is RECOMMENDED that this is done in a file called "VERSION"
|
||||||
|
located in the root of the project.</li>
|
||||||
|
<li id="clause-5-2"><a href="#clause-5-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.2.</a>If you are using a "VERSION" file in the root of the project, this MUST
|
||||||
|
only contain the exact version string.</li>
|
||||||
|
<li id="clause-5-3"><a href="#clause-5-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>5.3.</a>The version string SHOULD follow the Semantic Versioning
|
||||||
|
(<a href="http://semver.org/">http://semver.org/</a>) format. Use of Semantic Versioning is OPTIONAL,
|
||||||
|
but the version string MUST NOT have a "v" prefix. For example "v2.11.4"
|
||||||
|
is bad, and "2.11.4" is good.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-6"><a href="#clause-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.</a>Releases
|
||||||
|
<ol>
|
||||||
|
<li id="clause-6-1"><a href="#clause-6-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.1.</a>To create a new release, you MUST create a "version bump" commit which
|
||||||
|
changes the hard-coded version string of the project. The version bump
|
||||||
|
commit MUST have a git tag created on it and named as the exact version
|
||||||
|
string.</li>
|
||||||
|
<li id="clause-6-2"><a href="#clause-6-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.2.</a>If you are not using a release branch, then the version bump commit MUST
|
||||||
|
be created directly on the master branch.</li>
|
||||||
|
<li id="clause-6-3"><a href="#clause-6-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.3.</a>The version bump commit MUST have a commit message title of "Bump version
|
||||||
|
to VERSION". For example, if the new version string is "2.11.4", the
|
||||||
|
first line of the commit message MUST read: "Bump version to 2.11.4"</li>
|
||||||
|
<li id="clause-6-4"><a href="#clause-6-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.4.</a>The release tag on the version bump commit MUST be named exactly the same
|
||||||
|
as the version string. The tag name can OPTIONALLY be prefixed with
|
||||||
|
"v". For example the tag name can be either "2.11.4" or "v2.11.4". You
|
||||||
|
MUST not use a mix of "v" prefixed and non-prefixed tags. Pick one form
|
||||||
|
and stick to it.</li>
|
||||||
|
<li id="clause-6-5"><a href="#clause-6-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.5.</a>It is RECOMMENDED that release tags are lightweight tags, but you can
|
||||||
|
OPTIONALLY use annotated tags if you want to include changelog
|
||||||
|
information in the release tag itself.</li>
|
||||||
|
<li id="clause-6-6"><a href="#clause-6-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>6.6.</a>If you use annotated release tags, the first line of the annotation MUST
|
||||||
|
read "Release VERSION". For example for version "2.11.4" the first line
|
||||||
|
of the tag annotation would read "Release 2.11.4". The second line must
|
||||||
|
be blank, and the changelog MUST start on the third line.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-7"><a href="#clause-7" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.</a>Release Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-7-1"><a href="#clause-7-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.1.</a>Any branch that has a name starting with "release-" SHOULD be referred to
|
||||||
|
as a "release branch".</li>
|
||||||
|
<li id="clause-7-2"><a href="#clause-7-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.2.</a>Use of release branches is OPTIONAL.</li>
|
||||||
|
<li id="clause-7-3"><a href="#clause-7-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.3.</a>Changes in a release branch SHOULD typically come from work being
|
||||||
|
done against the master branch. Meaning changes SHOULD only trickle
|
||||||
|
downwards from the master branch. If a change needs to trickle back up
|
||||||
|
into the master branch, that work should have happened against the master
|
||||||
|
branch in the first place. One exception to this is version bump commits.</li>
|
||||||
|
<li id="clause-7-4"><a href="#clause-7-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.4.</a>There are two types of release branches; short-term, and long-term.</li>
|
||||||
|
<li id="clause-7-5"><a href="#clause-7-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.</a>Short-Term Release Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-7-5-1"><a href="#clause-7-5-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.1.</a>Used for creating a specific versioned release.</li>
|
||||||
|
<li id="clause-7-5-2"><a href="#clause-7-5-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.2.</a>A short-term release branch is RECOMMENDED if there is a lengthy
|
||||||
|
pre-release verification process to avoid a code freeze on the master
|
||||||
|
branch.</li>
|
||||||
|
<li id="clause-7-5-3"><a href="#clause-7-5-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.3.</a>MUST have a name of "release-VERSION". For example for version
|
||||||
|
"2.11.4" the release branch name MUST be "release-2.11.4".</li>
|
||||||
|
<li id="clause-7-5-4"><a href="#clause-7-5-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.4.</a>When using a short-term release branch, the version bump commit and
|
||||||
|
release tag MUST be made directly on the release branch itself.</li>
|
||||||
|
<li id="clause-7-5-5"><a href="#clause-7-5-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.5.</a>Only very minor changes should be performed on a short-term release
|
||||||
|
branch directly. Any larger changes SHOULD be done in the master
|
||||||
|
branch, and SHOULD be pulled into the release branch by rebasing it
|
||||||
|
on top of the master branch the same way a change branch pulls in
|
||||||
|
updates from its source branch.</li>
|
||||||
|
<li id="clause-7-5-6"><a href="#clause-7-5-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.5.6.</a>After the version bump commit and release tag have been created, the
|
||||||
|
release branch MUST be merged back into its source branch and then
|
||||||
|
deleted. Typically the source branch will be the master branch.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-7-6"><a href="#clause-7-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.6.</a>Long-Term Release Branches
|
||||||
|
<ol>
|
||||||
|
<li id="clause-7-6-1"><a href="#clause-7-6-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.6.1.</a>Used for work on versions which are not currently part of the master
|
||||||
|
branch. Typically this is useful when you need to create a new
|
||||||
|
maintenance release for a older version.</li>
|
||||||
|
<li id="clause-7-6-2"><a href="#clause-7-6-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.6.2.</a>The branch name MUST have a non-specific version number. For example
|
||||||
|
a long-term release branch for creating new 2.9.x releases would be
|
||||||
|
named "release-2.9".</li>
|
||||||
|
<li id="clause-7-6-3"><a href="#clause-7-6-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.6.3.</a>To create a new release from a long-term release branch, you MUST
|
||||||
|
create a version bump commit and release tag directly on the release
|
||||||
|
branch.</li>
|
||||||
|
<li id="clause-7-6-4"><a href="#clause-7-6-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>7.6.4.</a>A long-term release branch MUST be created from the relevant release
|
||||||
|
tag. For example if the master branch is on version 2.11.4 and there
|
||||||
|
is a security fix for all 2.9.x releases, the latest of which is
|
||||||
|
"2.9.7". Create a new branch called "release-2.9" off of the "2.9.7"
|
||||||
|
release tag. The security fix release will then end up being version
|
||||||
|
"2.9.8".</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-8"><a href="#clause-8" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.</a>Bug Fixes & Rollback
|
||||||
|
<ol>
|
||||||
|
<li id="clause-8-1"><a href="#clause-8-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.1.</a>You MUST NOT under any circumstances force push to the master branch.</li>
|
||||||
|
<li id="clause-8-2"><a href="#clause-8-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.2.</a>If a change branch which has been merged into the master branch is found
|
||||||
|
to have a bug in it, the bug fix work MUST be done as a new separate
|
||||||
|
change branch and MUST follow the same workflow as any other change
|
||||||
|
branch.</li>
|
||||||
|
<li id="clause-8-3"><a href="#clause-8-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>8.3.</a>If a change branch is wrongfully merged into master, or for any other
|
||||||
|
reason the merge must be undone, you MUST undo the merge by reverting the
|
||||||
|
merge commit itself. Effectively creating a new commit that reverses all
|
||||||
|
the relevant changes.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li id="clause-9"><a href="#clause-9" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>9.</a>Git Best Practices
|
||||||
|
<ol>
|
||||||
|
<li id="clause-9-1"><a href="#clause-9-1" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>9.1.</a>All commit messages SHOULD follow the Commit Guidelines and format from
|
||||||
|
the official git
|
||||||
|
documentation:
|
||||||
|
<a href="https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines">https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines</a></li>
|
||||||
|
<li id="clause-9-2"><a href="#clause-9-2" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>9.2.</a>You SHOULD never blindly commit all changes with "git commit -a". It is
|
||||||
|
RECOMMENDED you use "git add -i" to add individual changes to the staging
|
||||||
|
area so you are fully aware of what you are committing.</li>
|
||||||
|
<li id="clause-9-3"><a href="#clause-9-3" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>9.3.</a>You SHOULD always use "--force-with-lease" when doing a force push. The
|
||||||
|
regular "--force" option is dangerous and destructive. More
|
||||||
|
information:
|
||||||
|
<a href="https://developer.atlassian.com/blog/2015/04/force-with-lease/">https://developer.atlassian.com/blog/2015/04/force-with-lease/</a></li>
|
||||||
|
<li id="clause-9-4"><a href="#clause-9-4" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>9.4.</a>You SHOULD understand and be comfortable with
|
||||||
|
rebasing: <a href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing">https://git-scm.com/book/en/v2/Git-Branching-Rebasing</a></li>
|
||||||
|
<li id="clause-9-5"><a href="#clause-9-5" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>9.5.</a>It is RECOMMENDED that you always do "git pull --rebase" instead of "git
|
||||||
|
pull" to avoid unnecessary merge commits. You can make this the default
|
||||||
|
behavior of "git pull" with "git config --global pull.rebase true".</li>
|
||||||
|
<li id="clause-9-6"><a href="#clause-9-6" class="clause-link" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" class="clause-link-icon" stroke="currentColor" stroke-width="2"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"/></svg>9.6.</a>It is RECOMMENDED that all branches be merged using "git merge --no-ff".
|
||||||
|
This makes sure the reference to the original branch is kept in the
|
||||||
|
commits, allows one to revert a merge by reverting a single merge commit,
|
||||||
|
and creates a merge commit to mark the integration of the branch with
|
||||||
|
master.</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol> </section> </article> </div> </div> </div> </section> <script type="module">const i="clause-highlight";function a(t){t.classList.remove(i),t.offsetWidth,t.classList.add(i),setTimeout(()=>{t.classList.remove(i)},2e3)}function n(){const t=window.location.hash;if(!t||!t.startsWith("#clause-"))return;const s=t.slice(1),e=document.getElementById(s);e&&setTimeout(()=>a(e),100)}function h(){document.addEventListener("click",t=>{const s=t.target.closest('a[href^="#clause-"]');if(!s)return;const e=s.getAttribute("href");if(!e)return;const c=e.slice(1),o=document.getElementById(c);o&&setTimeout(()=>a(o),100)}),window.addEventListener("hashchange",n),window.location.hash?.startsWith("#clause-")&&(document.readyState==="complete"?n():window.addEventListener("load",n))}h();</script> <section id="faq" class="py-20 sm:py-28"> <div class="section-container"> <div class="max-w-3xl mx-auto"> <div class="mb-12 text-center"> <h2 class="text-3xl sm:text-4xl mb-4">FAQ</h2> <p class="text-lg text-gray-600 dark:text-neutral-400"> Common questions about Git Common-Flow </p> </div> <!-- FAQ Items --> <div class="space-y-0"> </div> </div> </div> </section> <script type="module">function n(){document.querySelectorAll("[data-faq-item]").forEach(r=>{const t=r.querySelector("[data-faq-trigger]"),a=r.querySelector("[data-faq-content]"),s=r.querySelector("[data-faq-icon]");!t||!a||!s||t.addEventListener("click",()=>{const e=t.getAttribute("aria-expanded")==="true";t.setAttribute("aria-expanded",e?"false":"true"),a.classList.toggle("grid-rows-[1fr]",!e),a.classList.toggle("grid-rows-[0fr]",e),s.classList.toggle("rotate-180",!e)})})}n();document.addEventListener("astro:after-swap",n);</script> </main> <footer class="pt-12 pb-6 my-28 text-sm
|
||||||
|
text-gray-500 dark:text-neutral-500
|
||||||
|
border-t border-gray-200 dark:border-neutral-800"> <div class="section-container flex flex-col sm:flex-row
|
||||||
|
sm:justify-between sm:items-center gap-2"> <p>
|
||||||
|
License:
|
||||||
|
<a href="https://creativecommons.org/licenses/by/4.0/" class="hover:text-sky-600" target="_blank" rel="noopener noreferrer"> CC BY 4.0 </a> </p> <p> Git Common-Flow by
|
||||||
|
<a href="https://jimeh.me/" class="hover:text-sky-600" target="_blank" rel="noopener noreferrer"> Jim Myhrberg </a> </p> </div> </footer> <!-- Re-init theme on Astro page transitions --> <script type="module">document.addEventListener("astro:after-swap",()=>{const e=localStorage.getItem("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches;e==="dark"||e!=="light"&&t?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")});</script> </body> </html>
|
||||||
2
docs/spec/1.0.0-rc.4.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
505
docs/spec/1.0.0-rc.4/index.html
Normal file
2
docs/spec/1.0.0-rc.5.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
522
docs/spec/1.0.0-rc.5/index.html
Normal file
10102
package-lock.json
generated
28
package.json
@@ -10,17 +10,18 @@
|
|||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"format:check": "prettier --check .",
|
"format:check": "prettier --check .",
|
||||||
"update-specs": "tsx scripts/update-specs.ts",
|
"update-specs": "bun scripts/update-specs.ts",
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/sitemap": "^3.7.0",
|
"@astrojs/sitemap": "^3.6.1",
|
||||||
|
"@fontsource-variable/bricolage-grotesque": "^5.2.10",
|
||||||
|
"@fontsource-variable/dm-sans": "^5.2.8",
|
||||||
|
"@fontsource-variable/jetbrains-mono": "^5.2.8",
|
||||||
"@iconify-json/heroicons": "^1.2.3",
|
"@iconify-json/heroicons": "^1.2.3",
|
||||||
"@iconify-json/simple-icons": "^1.2.69",
|
"@iconify-json/simple-icons": "^1.2.65",
|
||||||
"astro": "^5.17.1",
|
"astro": "^5.16.8",
|
||||||
"astro-icon": "^1.1.5",
|
"astro-icon": "^1.1.5",
|
||||||
"rehype-autolink-headings": "^7.1.0",
|
|
||||||
"rehype-slug": "^6.0.0",
|
|
||||||
"rehype-stringify": "^10.0.1",
|
"rehype-stringify": "^10.0.1",
|
||||||
"remark-parse": "^11.0.0",
|
"remark-parse": "^11.0.0",
|
||||||
"remark-rehype": "^11.1.2",
|
"remark-rehype": "^11.1.2",
|
||||||
@@ -29,18 +30,17 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/check": "^0.9.6",
|
"@astrojs/check": "^0.9.6",
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^9.39.2",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tailwindcss/vite": "^4.2.0",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
|
"@types/bun": "^1.3.5",
|
||||||
"@types/semver": "^7.7.1",
|
"@types/semver": "^7.7.1",
|
||||||
"eslint": "^10.0.0",
|
"eslint": "^9.39.2",
|
||||||
"eslint-plugin-astro": "^1.6.0",
|
"eslint-plugin-astro": "^1.5.0",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.7.4",
|
||||||
"prettier-plugin-astro": "^0.14.1",
|
"prettier-plugin-astro": "^0.14.1",
|
||||||
"svgo": "^4.0.0",
|
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"tsx": "^4.21.0",
|
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.56.0"
|
"typescript-eslint": "^8.52.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
0
public/.nojekyll
Normal file
2
public/spec/1.0.0-rc.1.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
2
public/spec/1.0.0-rc.2.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
2
public/spec/1.0.0-rc.3.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
2
public/spec/1.0.0-rc.4.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
2
public/spec/1.0.0-rc.5.svg
Normal file
|
After Width: | Height: | Size: 18 KiB |
@@ -5,11 +5,10 @@
|
|||||||
* Versions are discovered from git tags and filtered based on config.
|
* Versions are discovered from git tags and filtered based on config.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { execSync } from "node:child_process";
|
|
||||||
import * as fs from "node:fs";
|
import * as fs from "node:fs";
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import * as semver from "semver";
|
import * as semver from "semver";
|
||||||
import { optimize as optimizeSvg, type Config as SvgoConfig } from "svgo";
|
import { $ } from "bun";
|
||||||
import { config } from "../src/config";
|
import { config } from "../src/config";
|
||||||
|
|
||||||
const updateConfig = {
|
const updateConfig = {
|
||||||
@@ -19,25 +18,18 @@ version: {{version}}
|
|||||||
---
|
---
|
||||||
{{content}}`,
|
{{content}}`,
|
||||||
outputDir: "src/content/spec",
|
outputDir: "src/content/spec",
|
||||||
};
|
publicDir: "public/spec",
|
||||||
|
|
||||||
// SVGO config: use removeDimensions to convert width/height to viewBox
|
|
||||||
// for responsive scaling while preserving aspect ratio
|
|
||||||
const svgoConfig: SvgoConfig = {
|
|
||||||
plugins: ["preset-default", "removeDimensions"],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch all tags from the GitHub repository.
|
* Fetch all tags from the GitHub repository.
|
||||||
*/
|
*/
|
||||||
function fetchTags(repository: string): string[] {
|
async function fetchTags(repository: string): Promise<string[]> {
|
||||||
const repoUrl = `https://github.com/${repository}.git`;
|
const repoUrl = `https://github.com/${repository}.git`;
|
||||||
console.log(`Fetching tags from ${repoUrl}...`);
|
console.log(`Fetching tags from ${repoUrl}...`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = execSync(`git ls-remote --tags ${repoUrl}`, {
|
const result = await $`git ls-remote --tags ${repoUrl}`.text();
|
||||||
encoding: "utf-8",
|
|
||||||
});
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
.split("\n")
|
.split("\n")
|
||||||
@@ -127,20 +119,22 @@ function removeStaleSpecs(versionsToKeep: string[]): void {
|
|||||||
const keepSet = new Set(versionsToKeep);
|
const keepSet = new Set(versionsToKeep);
|
||||||
let removedAny = false;
|
let removedAny = false;
|
||||||
|
|
||||||
if (!fs.existsSync(updateConfig.outputDir)) return;
|
for (const dir of [updateConfig.outputDir, updateConfig.publicDir]) {
|
||||||
|
if (!fs.existsSync(dir)) continue;
|
||||||
|
|
||||||
const files = fs.readdirSync(updateConfig.outputDir);
|
const files = fs.readdirSync(dir);
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
// Extract version from filename (e.g., "1.0.0-rc.1.md" -> "1.0.0-rc.1")
|
// Extract version from filename (e.g., "1.0.0-rc.1.md" -> "1.0.0-rc.1")
|
||||||
const version = path.basename(file, path.extname(file));
|
const version = path.basename(file, path.extname(file));
|
||||||
if (!keepSet.has(version)) {
|
if (!keepSet.has(version)) {
|
||||||
if (!removedAny) {
|
if (!removedAny) {
|
||||||
console.log("\nRemoving stale spec files:");
|
console.log("\nRemoving stale spec files:");
|
||||||
removedAny = true;
|
removedAny = true;
|
||||||
|
}
|
||||||
|
const filePath = path.join(dir, file);
|
||||||
|
fs.unlinkSync(filePath);
|
||||||
|
console.log(` ${filePath}`);
|
||||||
}
|
}
|
||||||
const filePath = path.join(updateConfig.outputDir, file);
|
|
||||||
fs.unlinkSync(filePath);
|
|
||||||
console.log(` ${filePath}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,20 +161,11 @@ async function fetchSpec(version: string): Promise<Spec> {
|
|||||||
throw new Error(`Failed to fetch document for version ${version}`);
|
throw new Error(`Failed to fetch document for version ${version}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace {{version}} placeholder with v-prefixed version
|
// Replace {{version}} placeholder throughout the document
|
||||||
document = document.replaceAll("{{version}}", `v${version}`);
|
document = document.replaceAll("{{version}}", version);
|
||||||
|
|
||||||
// Handle setext-style H1 heading (title with === underline)
|
|
||||||
const lines = document.split("\n");
|
|
||||||
if (lines.length >= 2 && /^=+$/.test(lines[1])) {
|
|
||||||
// Adjust the underline length to match the title
|
|
||||||
lines[1] = "=".repeat(lines[0].length);
|
|
||||||
document = lines.join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract title from first line (after version replacement)
|
// Extract title from first line (after version replacement)
|
||||||
// Handle both ATX-style (# Title) and setext-style (Title\n===) headings
|
const title = document.split("\n", 1)[0];
|
||||||
const title = lines[0].replace(/^#\s+/, "");
|
|
||||||
|
|
||||||
// Build body with frontmatter
|
// Build body with frontmatter
|
||||||
const body = updateConfig.bodyTemplate
|
const body = updateConfig.bodyTemplate
|
||||||
@@ -198,7 +183,7 @@ async function fetchSpec(version: string): Promise<Spec> {
|
|||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
// 1. Discover and filter versions
|
// 1. Discover and filter versions
|
||||||
const tags = fetchTags(config.update.repository);
|
const tags = await fetchTags(config.update.repository);
|
||||||
console.log(`Found ${tags.length} tags`);
|
console.log(`Found ${tags.length} tags`);
|
||||||
|
|
||||||
const filtered = filterVersions(tags);
|
const filtered = filterVersions(tags);
|
||||||
@@ -226,18 +211,17 @@ async function main(): Promise<void> {
|
|||||||
const mdPath = path.join(updateConfig.outputDir, `${version}.md`);
|
const mdPath = path.join(updateConfig.outputDir, `${version}.md`);
|
||||||
writeFile(mdPath, spec.body);
|
writeFile(mdPath, spec.body);
|
||||||
|
|
||||||
// Write SVG diagram next to markdown (with metadata stripped)
|
// Write SVG diagram to public directory
|
||||||
if (spec.diagram) {
|
if (spec.diagram) {
|
||||||
const svgPath = path.join(updateConfig.outputDir, `${version}.svg`);
|
const svgPath = path.join(updateConfig.publicDir, `${version}.svg`);
|
||||||
const optimizedSvg = optimizeSvg(spec.diagram, svgoConfig).data;
|
writeFile(svgPath, spec.diagram);
|
||||||
writeFile(svgPath, optimizedSvg);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error processing version ${version}:`, error);
|
console.error(`Error processing version ${version}:`, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("\nDone! Run `npm run build` to rebuild the site.");
|
console.log("\nDone! Run `bun run build` to rebuild the site.");
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { config } from "../config";
|
|||||||
border-t border-gray-200 dark:border-neutral-800"
|
border-t border-gray-200 dark:border-neutral-800"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="section-container flex flex-col items-center text-center
|
class="section-container flex flex-col sm:flex-row
|
||||||
sm:flex-row sm:justify-between sm:items-center sm:text-left gap-2"
|
sm:justify-between sm:items-center gap-2"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
License:
|
License:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const navItems = [
|
|||||||
<!-- Logo / Title + Version -->
|
<!-- Logo / Title + Version -->
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<a
|
<a
|
||||||
href="#top"
|
href="#hero"
|
||||||
class="flex items-center gap-3 no-underline
|
class="flex items-center gap-3 no-underline
|
||||||
text-gray-950 dark:text-neutral-50
|
text-gray-950 dark:text-neutral-50
|
||||||
hover:text-sky-600 transition-colors"
|
hover:text-sky-600 transition-colors"
|
||||||
@@ -127,7 +127,7 @@ const navItems = [
|
|||||||
|
|
||||||
function initHeader() {
|
function initHeader() {
|
||||||
const header = document.getElementById("site-header");
|
const header = document.getElementById("site-header");
|
||||||
const hero = document.getElementById("top");
|
const hero = document.getElementById("hero");
|
||||||
const mobileMenuBtn = document.getElementById("mobile-menu-btn");
|
const mobileMenuBtn = document.getElementById("mobile-menu-btn");
|
||||||
const mobileNav = document.getElementById("mobile-nav");
|
const mobileNav = document.getElementById("mobile-nav");
|
||||||
|
|
||||||
|
|||||||
@@ -7,33 +7,14 @@ import { config } from "../config";
|
|||||||
interface Props {
|
interface Props {
|
||||||
version: string;
|
version: string;
|
||||||
versions: string[];
|
versions: string[];
|
||||||
svgContent?: string | null;
|
svgPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { version, versions, svgContent } = Astro.props;
|
const { version, versions, svgPath } = Astro.props;
|
||||||
|
|
||||||
const navItems = [
|
|
||||||
{ id: "about", label: "About", align: "end" },
|
|
||||||
{ id: "spec", label: "Read the Spec", primary: true },
|
|
||||||
{ id: "faq", label: "FAQ", align: "start" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const baseClasses = `inline-flex items-center justify-center gap-2
|
|
||||||
px-4 py-2.5 sm:px-6 sm:py-3
|
|
||||||
text-sm sm:text-base font-medium rounded-lg
|
|
||||||
transition-all cursor-pointer`;
|
|
||||||
|
|
||||||
const primaryClasses = `bg-sky-600 text-white
|
|
||||||
hover:bg-sky-500 hover:-translate-y-0.5 hover:shadow-md`;
|
|
||||||
|
|
||||||
const secondaryClasses = `text-gray-600 dark:text-neutral-400
|
|
||||||
hover:bg-gray-100 hover:text-gray-950
|
|
||||||
dark:hover:bg-neutral-800 dark:hover:text-neutral-50`;
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<section
|
<section
|
||||||
id="top"
|
id="hero"
|
||||||
class="relative min-h-[75vh] flex flex-col items-center justify-center
|
class="relative min-h-[75vh] flex flex-col items-center justify-center
|
||||||
px-6 pt-16 pb-24 overflow-hidden"
|
px-6 pt-16 pb-24 overflow-hidden"
|
||||||
>
|
>
|
||||||
@@ -113,44 +94,55 @@ const secondaryClasses = `text-gray-600 dark:text-neutral-400
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- SVG Diagram -->
|
<!-- SVG Diagram -->
|
||||||
{
|
<div
|
||||||
svgContent && (
|
class="animate-fade-in-up delay-300
|
||||||
<div
|
relative mx-auto mb-12 p-4 sm:p-8
|
||||||
class="animate-fade-in-up delay-300
|
bg-white dark:bg-neutral-900
|
||||||
relative mx-auto mb-12 py-8 px-6 sm:py-16 sm:px-14
|
rounded-2xl shadow-lg dark:shadow-none
|
||||||
bg-white dark:bg-neutral-900
|
border border-gray-200 dark:border-neutral-800"
|
||||||
rounded-2xl shadow-lg dark:shadow-none
|
>
|
||||||
border border-gray-200 dark:border-neutral-800"
|
<img
|
||||||
>
|
src={svgPath}
|
||||||
<div
|
alt="Git Common-Flow diagram"
|
||||||
class="w-full max-w-3xl mx-auto [&>svg]:w-full [&>svg]:h-auto
|
class="w-full h-auto max-w-3xl mx-auto
|
||||||
dark:invert dark:hue-rotate-180 dark:contrast-90"
|
dark:invert dark:hue-rotate-180 dark:contrast-90"
|
||||||
set:html={svgContent}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
<!-- Navigation links -->
|
<!-- Navigation links -->
|
||||||
<nav
|
<nav
|
||||||
class="animate-fade-in-up delay-400
|
class="animate-fade-in-up delay-400
|
||||||
grid grid-cols-[1fr_auto_1fr] items-center gap-2 sm:gap-4"
|
flex flex-wrap items-center justify-center gap-4"
|
||||||
>
|
>
|
||||||
{
|
<a
|
||||||
navItems.map((item) => (
|
href="#about"
|
||||||
<a
|
class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
href={`#${item.id}`}
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
class:list={[
|
text-gray-600 dark:text-neutral-400
|
||||||
baseClasses,
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
item.primary ? primaryClasses : secondaryClasses,
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50"
|
||||||
item.align === "end" && "justify-self-end",
|
>
|
||||||
item.align === "start" && "justify-self-start",
|
About
|
||||||
]}
|
</a>
|
||||||
>
|
<a
|
||||||
{item.label}
|
href="#spec"
|
||||||
</a>
|
class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
))
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
}
|
bg-sky-600 text-white
|
||||||
|
hover:bg-sky-500 hover:-translate-y-0.5 hover:shadow-md"
|
||||||
|
>
|
||||||
|
Read the Spec
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#faq"
|
||||||
|
class="inline-flex items-center justify-center gap-2 px-6 py-3
|
||||||
|
text-base font-medium rounded-lg transition-all cursor-pointer
|
||||||
|
text-gray-600 dark:text-neutral-400
|
||||||
|
hover:bg-gray-100 hover:text-gray-950
|
||||||
|
dark:hover:bg-neutral-800 dark:hover:text-neutral-50"
|
||||||
|
>
|
||||||
|
FAQ
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -166,34 +158,3 @@ const secondaryClasses = `text-gray-600 dark:text-neutral-400
|
|||||||
<Icon name="heroicons:arrow-down" class="w-6 h-6 animate-bounce-subtle" />
|
<Icon name="heroicons:arrow-down" class="w-6 h-6 animate-bounce-subtle" />
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script>
|
|
||||||
// Remove animation classes after they complete to prevent re-triggering
|
|
||||||
// on theme toggle.
|
|
||||||
const animationClasses = [
|
|
||||||
"animate-fade-in",
|
|
||||||
"animate-fade-in-up",
|
|
||||||
"animate-fade-in-down",
|
|
||||||
"animate-slide-in-left",
|
|
||||||
];
|
|
||||||
|
|
||||||
function cleanupAnimations() {
|
|
||||||
const selector = animationClasses.map((c) => `.${c}`).join(", ");
|
|
||||||
const animatedElements = document.querySelectorAll(selector);
|
|
||||||
|
|
||||||
animatedElements.forEach((el) => {
|
|
||||||
el.addEventListener(
|
|
||||||
"animationend",
|
|
||||||
() => {
|
|
||||||
animationClasses.forEach((cls) => el.classList.remove(cls));
|
|
||||||
// Also remove delay classes
|
|
||||||
el.className = el.className.replace(/\bdelay-\d+\b/g, "").trim();
|
|
||||||
},
|
|
||||||
{ once: true },
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanupAnimations();
|
|
||||||
document.addEventListener("astro:after-swap", cleanupAnimations);
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
import { Icon } from "astro-icon/components";
|
|
||||||
import SectionHeader from "./SectionHeader.astro";
|
import SectionHeader from "./SectionHeader.astro";
|
||||||
import SpecSidebar from "./SpecSidebar.astro";
|
import SpecSidebar from "./SpecSidebar.astro";
|
||||||
import type { TocItem } from "../utils/parseSpecContent";
|
import type { TocItem } from "../utils/parseSpecContent";
|
||||||
@@ -9,11 +8,9 @@ interface Props {
|
|||||||
terminologyTitle: string;
|
terminologyTitle: string;
|
||||||
specification: string;
|
specification: string;
|
||||||
tocItems: TocItem[];
|
tocItems: TocItem[];
|
||||||
version: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { terminology, terminologyTitle, specification, tocItems, version } =
|
const { terminology, terminologyTitle, specification, tocItems } = Astro.props;
|
||||||
Astro.props;
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<section id="spec" class="py-20 sm:py-28">
|
<section id="spec" class="py-20 sm:py-28">
|
||||||
@@ -24,20 +21,6 @@ const { terminology, terminologyTitle, specification, tocItems, version } =
|
|||||||
class="max-w-3xl mx-auto"
|
class="max-w-3xl mx-auto"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex justify-center mb-8 -mt-8">
|
|
||||||
<a
|
|
||||||
href={`/spec/${version}/md`}
|
|
||||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm
|
|
||||||
font-medium rounded-lg transition-colors
|
|
||||||
text-gray-500 dark:text-neutral-500
|
|
||||||
hover:bg-gray-100 hover:text-gray-700
|
|
||||||
dark:hover:bg-neutral-800 dark:hover:text-neutral-300"
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:code-bracket" class="w-4 h-4" />
|
|
||||||
View Markdown Version
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Content with sidebar -->
|
<!-- Content with sidebar -->
|
||||||
<div class="lg:flex lg:gap-8">
|
<div class="lg:flex lg:gap-8">
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ import { Icon } from "astro-icon/components";
|
|||||||
>
|
>
|
||||||
<Icon name="heroicons:sun" data-theme-icon="light" class="hidden w-5 h-5" />
|
<Icon name="heroicons:sun" data-theme-icon="light" class="hidden w-5 h-5" />
|
||||||
<Icon name="heroicons:moon" data-theme-icon="dark" class="hidden w-5 h-5" />
|
<Icon name="heroicons:moon" data-theme-icon="dark" class="hidden w-5 h-5" />
|
||||||
<Icon name="sun-moon" data-theme-icon="auto" class="hidden w-5 h-5" />
|
<Icon
|
||||||
|
name="heroicons:computer-desktop"
|
||||||
|
data-theme-icon="auto"
|
||||||
|
class="hidden w-5 h-5"
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
<!-- Tooltip -->
|
<!-- Tooltip -->
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const { currentVersion, versions } = Astro.props;
|
|||||||
data-version-dropdown
|
data-version-dropdown
|
||||||
role="listbox"
|
role="listbox"
|
||||||
aria-label="Select version"
|
aria-label="Select version"
|
||||||
class="absolute top-full left-0 mt-2 w-max min-w-full p-1.5 z-50
|
class="absolute top-full left-0 mt-2 min-w-full p-1.5 z-50
|
||||||
bg-gray-50 dark:bg-neutral-900
|
bg-gray-50 dark:bg-neutral-900
|
||||||
border border-gray-200 dark:border-neutral-700
|
border border-gray-200 dark:border-neutral-700
|
||||||
rounded-lg shadow-lg
|
rounded-lg shadow-lg
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ title: Git Common-Flow 1.0.0-rc.1
|
|||||||
version: 1.0.0-rc.1
|
version: 1.0.0-rc.1
|
||||||
---
|
---
|
||||||
Git Common-Flow 1.0.0-rc.1
|
Git Common-Flow 1.0.0-rc.1
|
||||||
==========================
|
==============================
|
||||||
|
|
||||||
Summary
|
Summary
|
||||||
-------
|
-------
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: Git Common-Flow v1.0.0-rc.2
|
title: Git Common-Flow 1.0.0-rc.2
|
||||||
version: 1.0.0-rc.2
|
version: 1.0.0-rc.2
|
||||||
---
|
---
|
||||||
Git Common-Flow v1.0.0-rc.2
|
Git Common-Flow 1.0.0-rc.2
|
||||||
===========================
|
==============================
|
||||||
|
|
||||||
Summary
|
Summary
|
||||||
-------
|
-------
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: Git Common-Flow v1.0.0-rc.3
|
title: Git Common-Flow 1.0.0-rc.3
|
||||||
version: 1.0.0-rc.3
|
version: 1.0.0-rc.3
|
||||||
---
|
---
|
||||||
Git Common-Flow v1.0.0-rc.3
|
Git Common-Flow 1.0.0-rc.3
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
Summary
|
Summary
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: Git Common-Flow v1.0.0-rc.4
|
title: Git Common-Flow 1.0.0-rc.4
|
||||||
version: 1.0.0-rc.4
|
version: 1.0.0-rc.4
|
||||||
---
|
---
|
||||||
Git Common-Flow v1.0.0-rc.4
|
Git Common-Flow 1.0.0-rc.4
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
Summary
|
Summary
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: Git Common-Flow v1.0.0-rc.5
|
title: Git Common-Flow 1.0.0-rc.5
|
||||||
version: 1.0.0-rc.5
|
version: 1.0.0-rc.5
|
||||||
---
|
---
|
||||||
Git Common-Flow v1.0.0-rc.5
|
Git Common-Flow 1.0.0-rc.5
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,380 +0,0 @@
|
|||||||
---
|
|
||||||
title: Git Common-Flow v2.0.0
|
|
||||||
version: 2.0.0
|
|
||||||
---
|
|
||||||
# Git Common-Flow v2.0.0
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
Common-Flow is an attempt to gather a sensible selection of the most common
|
|
||||||
usage patterns of git into a single and concise specification. It is based on
|
|
||||||
the [original variant](https://scottchacon.com/2011/08/31/github-flow/) of
|
|
||||||
[GitHub Flow](https://docs.github.com/en/get-started/using-github/github-flow),
|
|
||||||
while taking into account how a lot of open source projects most commonly use
|
|
||||||
git.
|
|
||||||
|
|
||||||
In short, Common-Flow is essentially GitHub Flow with the addition of versioned
|
|
||||||
releases, optional release branches, and without the requirement to deploy to
|
|
||||||
production all the time.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
- The "main" branch is the mainline branch with latest changes, and must not be
|
|
||||||
broken.
|
|
||||||
- Changes (features, bugfixes, etc.) are done on "change branches" created from
|
|
||||||
the main branch.
|
|
||||||
- Rebase change branches early and often.
|
|
||||||
- When a change branch is stable and ready, it is merged back in to main.
|
|
||||||
- A release is just a git tag who's name is the exact release version string
|
|
||||||
(e.g. "2.11.4" or "v2.11.4").
|
|
||||||
- Release branches can be used when the release process and verification might
|
|
||||||
be lengthy, allowing main to remain open for new changes. They are not
|
|
||||||
required, instead they are available if you need them.
|
|
||||||
|
|
||||||
## Terminology
|
|
||||||
|
|
||||||
- **Main Branch** - Must be named "main", must always have passing tests, and is
|
|
||||||
not guaranteed to always work in production environments.
|
|
||||||
- **Change Branches** - Any branch that introduces changes like a new feature, a
|
|
||||||
bugfix, etc.
|
|
||||||
- **Source Branch** - The branch that a change branch was created from. New
|
|
||||||
changes in the source branch should be incorporated into the change branch via
|
|
||||||
rebasing.
|
|
||||||
- **Merge Target** - A branch that is the intended merge target for a change
|
|
||||||
branch. Typically the merge target branch will be the same as the source
|
|
||||||
branch.
|
|
||||||
- **Pull Request** - A means of requesting that a change branch is merged in to
|
|
||||||
its merge target, allowing others to review, discuss and approve the changes.
|
|
||||||
- **Release** - May be considered safe to use in production environments. Is
|
|
||||||
effectively just a git tag named after the version of the release.
|
|
||||||
- **Release Branches** - Used both for short-term preparations of a release, and
|
|
||||||
for long-term maintenance of older versions.
|
|
||||||
|
|
||||||
## Git Common-Flow Specification (Common-Flow)
|
|
||||||
|
|
||||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
|
||||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
|
||||||
interpreted as described in [RFC
|
|
||||||
2119](https://datatracker.ietf.org/doc/html/rfc2119).
|
|
||||||
|
|
||||||
1. TL;DR
|
|
||||||
1. Do not break the main branch.
|
|
||||||
2. A release is a git tag.
|
|
||||||
2. The Main Branch
|
|
||||||
1. A branch named "main" MUST exist and it MUST be referred to as the "main
|
|
||||||
branch".
|
|
||||||
2. The main branch MUST always be in a non-broken state with its test suite
|
|
||||||
passing.
|
|
||||||
3. The main branch is not guaranteed to always work in production
|
|
||||||
environments. Despite test suites passing it may at times contain
|
|
||||||
unfinished work. Only releases may be considered safe for production use.
|
|
||||||
4. The main branch SHOULD always be in a "as near as possibly ready for
|
|
||||||
release/production" state to reduce any friction with creating a new
|
|
||||||
release.
|
|
||||||
3. Change Branches
|
|
||||||
1. Each change (feature, bugfix, etc.) MUST be performed on separate
|
|
||||||
branches that SHOULD be referred to as "change branches".
|
|
||||||
2. All change branches MUST have descriptive names.
|
|
||||||
3. It is RECOMMENDED that you commit often locally, and that you try and
|
|
||||||
keep the commits reasonably structured to avoid a messy and confusing git
|
|
||||||
history.
|
|
||||||
4. You SHOULD regularly push your work to the same named branch on the
|
|
||||||
remote server.
|
|
||||||
5. You SHOULD create separate change branches for each distinctly different
|
|
||||||
change. You SHOULD NOT include multiple unrelated changes into a single
|
|
||||||
change branch.
|
|
||||||
6. When a change branch is created, the branch that it is created from
|
|
||||||
SHOULD be referred to as the "source branch". Each change branch also
|
|
||||||
needs a designated "merge target" branch, typically this will be the same
|
|
||||||
as the source branch.
|
|
||||||
7. Change branches MUST be regularly updated with any changes from their
|
|
||||||
source branch. This MUST be done by rebasing the change branch on top of
|
|
||||||
the source branch.
|
|
||||||
8. After updating a change branch from its source branch you MUST push the
|
|
||||||
change branch to the remote server. Due to the nature of rebasing, you
|
|
||||||
will be required to do a force push, and you MUST use the
|
|
||||||
"--force-with-lease" git push option when doing so instead of the regular
|
|
||||||
"--force".
|
|
||||||
9. If there is a truly valid technical reason to not use rebase when
|
|
||||||
updating change branches, then you MAY update change branches via merge
|
|
||||||
instead of rebase. The decision to use merge MUST only be taken after all
|
|
||||||
possible options to use rebase have been tried and failed. People not
|
|
||||||
understanding how to use rebase is NOT a valid reason to use merge. If
|
|
||||||
you do decide to use merge instead of rebase, you MUST NOT use a mixture
|
|
||||||
of both methods.
|
|
||||||
4. Pull Requests
|
|
||||||
1. To merge a change branch into its merge target, you MUST open a "pull
|
|
||||||
request" (or equivalent).
|
|
||||||
2. The purpose of a pull request is to allow others to review your changes
|
|
||||||
and give feedback. You can then fix any issues, complaints, and more that
|
|
||||||
might arise, and then let people review again.
|
|
||||||
3. Before creating a pull request, it is RECOMMENDED that you consider the
|
|
||||||
state of your change branch's commit history. If it is messy and
|
|
||||||
confusing, it might be a good idea to rebase your branch with "git rebase
|
|
||||||
-i" to present a cleaner and easier to follow commit history for your
|
|
||||||
reviewers.
|
|
||||||
4. A pull request MUST only be merged when the change branch is up-to-date
|
|
||||||
with its source branch, the test suite and other CI checks are passing,
|
|
||||||
and you and others are happy with the changes. This is especially
|
|
||||||
important if the merge target is the main branch.
|
|
||||||
5. To get feedback, help, or generally just discuss a change branch with
|
|
||||||
others, it is RECOMMENDED you create a draft pull request and discuss the
|
|
||||||
changes with others there. This leaves a clear and visible history of
|
|
||||||
how, when, and why the code looks and behaves the way it does.
|
|
||||||
5. Git Best Practices
|
|
||||||
1. It is RECOMMENDED that all commit messages follow the Conventional
|
|
||||||
Commits specification (<https://www.conventionalcommits.org/>). This
|
|
||||||
provides a structured format that integrates well with Semantic
|
|
||||||
Versioning, and enables automated changelog generation. At minimum,
|
|
||||||
commit messages SHOULD follow the Commit Guidelines from the official git
|
|
||||||
documentation:
|
|
||||||
<https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines>
|
|
||||||
2. You SHOULD always use "--force-with-lease" when doing a force push. The
|
|
||||||
regular "--force" option is dangerous and destructive. More information:
|
|
||||||
<https://www.codestudy.net/blog/git-push-force-with-lease-vs-force/>
|
|
||||||
3. You SHOULD understand and be comfortable with rebasing:
|
|
||||||
<https://git-scm.com/book/en/v2/Git-Branching-Rebasing>
|
|
||||||
4. It is RECOMMENDED that you always do "git pull --rebase" instead of "git
|
|
||||||
pull" to avoid unnecessary merge commits. You can make this the default
|
|
||||||
behavior of "git pull" with "git config --global pull.rebase true".
|
|
||||||
5. When using Conventional Commits, it is RECOMMENDED to use tooling to
|
|
||||||
automate version bumping and generate changelogs from commit messages.
|
|
||||||
This pairs well with the release process and ensures changelogs are
|
|
||||||
consistent and complete.
|
|
||||||
6. Versioning
|
|
||||||
1. A "version string" is a typically mostly numeric string that identifies a
|
|
||||||
specific version of a project. The version string itself MUST NOT have a
|
|
||||||
"v" prefix, but the version string can be displayed with a "v" prefix.
|
|
||||||
2. The source of truth for a project's version MUST be a git tag with a name
|
|
||||||
based on the version string. This kind of tag MUST be referred to as a
|
|
||||||
"release tag".
|
|
||||||
3. It is OPTIONAL, but RECOMMENDED to also keep the version string
|
|
||||||
hard-coded somewhere in the project code-base.
|
|
||||||
4. If you hard-code the version string into the code-base, it is RECOMMENDED
|
|
||||||
that you do so in a file called "VERSION" located in the root of the
|
|
||||||
project. But be mindful of the conventions of your programming language
|
|
||||||
and community when choosing if, where and how to hard-code the version
|
|
||||||
string.
|
|
||||||
5. If you are using a "VERSION" file in the root of the project, this file
|
|
||||||
MUST only contain the exact version string, meaning it MUST NOT have a
|
|
||||||
"v" prefix. For example, "v2.11.4" is bad, and "2.11.4" is good.
|
|
||||||
6. It is OPTIONAL, but RECOMMENDED that the version string follows Semantic
|
|
||||||
Versioning (<http://semver.org/>).
|
|
||||||
7. Releases
|
|
||||||
1. To create a new release, you MUST create a git tag named as the exact
|
|
||||||
version string of the release. This kind of tag MUST be referred to as a
|
|
||||||
"release tag".
|
|
||||||
2. The release tag name can OPTIONALLY be prefixed with "v". For example,
|
|
||||||
the tag name can be either "2.11.4" or "v2.11.4". Note that this "v"
|
|
||||||
prefix is only for the tag name itself, the version string (as defined in
|
|
||||||
section 6.1) MUST NOT have a "v" prefix.
|
|
||||||
3. If the version string is hard-coded into the code-base, you MUST create a
|
|
||||||
"version bump" commit which changes the hard-coded version string of the
|
|
||||||
project.
|
|
||||||
4. When using version bump commits, the release tag MUST be placed on the
|
|
||||||
version bump commit, unless using a release pull request.
|
|
||||||
5. It is OPTIONAL to use a "release pull request" to propose a release. A
|
|
||||||
release pull request contains the version bump commit and any
|
|
||||||
release-related changes (changelog updates, etc.). When using release
|
|
||||||
pull requests, the release tag SHOULD be placed on the resulting merge
|
|
||||||
commit.
|
|
||||||
6. If you are not using a release branch, then the release tag, and if
|
|
||||||
relevant the version bump commit, MUST be created directly on the main
|
|
||||||
branch.
|
|
||||||
7. If you are using Conventional Commits, the version bump commit MUST also
|
|
||||||
follow the format. For example, "chore(release): 2.11.4". Otherwise, a
|
|
||||||
simple "Bump version to 2.11.4" format is acceptable.
|
|
||||||
8. Release tags SHOULD be lightweight tags unless you need features that
|
|
||||||
annotated tags provide. Annotated tags allow you to include changelog
|
|
||||||
information in the tag itself, GPG sign the tag, or include additional
|
|
||||||
metadata like the tagger's name and email.
|
|
||||||
9. If you use annotated release tags, the first line of the annotation
|
|
||||||
SHOULD read "Release VERSION". For example for version "2.11.4" the first
|
|
||||||
line of the tag annotation SHOULD read "Release 2.11.4". The second line
|
|
||||||
MUST be blank, and the changelog SHOULD start on the third line.
|
|
||||||
10. It is OPTIONAL, but RECOMMENDED for high-security projects, to GPG sign
|
|
||||||
release tags. This provides cryptographic verification that the release
|
|
||||||
was created by a trusted party.
|
|
||||||
8. Short-Term Release Branches
|
|
||||||
1. Any branch that has a name starting with "release-" SHOULD be referred to
|
|
||||||
as a "release branch".
|
|
||||||
2. Any release branch which has a name ending with a specific version
|
|
||||||
string, MUST be referred to as a "short-term release branch".
|
|
||||||
3. Use of short-term release branches are OPTIONAL, and intended to be used
|
|
||||||
to create a specific versioned release.
|
|
||||||
4. A short-term release branch is RECOMMENDED if there is a lengthy release
|
|
||||||
verification process to avoid a code freeze on the main branch.
|
|
||||||
5. Short-term release branches MUST have a name of "release-VERSION". For
|
|
||||||
example for version "2.11.4" the release branch name MUST be
|
|
||||||
"release-2.11.4".
|
|
||||||
6. When using a short-term release branch to create a release, the version
|
|
||||||
bump commit if used, MUST be created on the short-term release branch.
|
|
||||||
The release tag MUST be placed on the version bump commit, or on the
|
|
||||||
merge commit when using a release pull request to merge the release
|
|
||||||
branch.
|
|
||||||
7. Only very minor changes SHOULD be performed on a short-term release
|
|
||||||
branch directly. Any larger changes SHOULD be done in the main branch,
|
|
||||||
and SHOULD be pulled into the release branch by rebasing it on top of the
|
|
||||||
main branch the same way a change branch pulls in updates from its source
|
|
||||||
branch.
|
|
||||||
8. After a release tag has been created, the release branch MUST be merged
|
|
||||||
back into its source branch and then deleted. Typically the source branch
|
|
||||||
will be the main branch.
|
|
||||||
9. Long-Term Release Branches
|
|
||||||
1. Any release branch which has a name ending with a nonspecific version
|
|
||||||
string, MUST be referred to as a "long-term release branch". For example,
|
|
||||||
"release-2.11" is a long-term release branch, while "release-2.11.4" is a
|
|
||||||
short-term release branch.
|
|
||||||
2. Use of long-term release branches are OPTIONAL, and intended for work on
|
|
||||||
versions which are not currently part of the main branch. Typically this
|
|
||||||
is useful when you need to create a new maintenance release for an older
|
|
||||||
version.
|
|
||||||
3. A long-term release branch MUST have a name with a nonspecific version
|
|
||||||
number. For example, a long-term release branch for creating new 2.9.x
|
|
||||||
releases MUST be named "release-2.9", or "release-2" for all 2.x.x
|
|
||||||
releases when main has moved to 3.x.x.
|
|
||||||
4. Long-term release branches for maintenance releases of older versions
|
|
||||||
MUST be created from the relevant release tag. For example, if the main
|
|
||||||
branch is on version 2.11.4 and there is a security fix for all 2.9.x
|
|
||||||
releases, the latest of which is "2.9.7". Create a new branch called
|
|
||||||
"release-2.9" from the "2.9.7" release tag. The security fix release will
|
|
||||||
then end up being version "2.9.8". Similarly, if main is on 3.x.x and you
|
|
||||||
need to maintain the entire 2.x.x line, create a "release-2" branch from
|
|
||||||
the latest 2.x.x release tag.
|
|
||||||
5. To create a new release from a long-term release branch, you MUST follow
|
|
||||||
the same process as a release from the main branch, except the long-term
|
|
||||||
release branch takes the place of the main branch.
|
|
||||||
6. A long-term release branch SHOULD be treated with the same respect as the
|
|
||||||
main branch. It is effectively the main branch for the release series in
|
|
||||||
question. Meaning it MUST always be in a non-broken state, MUST NOT be
|
|
||||||
force pushed to, etc.
|
|
||||||
10. Bug Fixes & Rollback
|
|
||||||
1. You MUST NOT under any circumstances force push to the main branch or to
|
|
||||||
long-term release branches.
|
|
||||||
2. If a change branch which has been merged into the main branch is found to
|
|
||||||
have a bug in it, the bugfix work MUST be done as a new separate change
|
|
||||||
branch. This new change branch MUST follow the same workflow as any other
|
|
||||||
change branch.
|
|
||||||
3. If a change branch is wrongfully merged into main, or for any other
|
|
||||||
reason the merge must be undone, you MUST undo the merge by reverting the
|
|
||||||
merge commit itself. Effectively creating a new commit that reverses all
|
|
||||||
the relevant changes.
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
### Why use Common-Flow instead of Git Flow, and how does it differ?
|
|
||||||
|
|
||||||
Common-Flow tries to be a lot less complicated than Git Flow by having fewer
|
|
||||||
types of branches, and simpler rules. Normal day to day development doesn't
|
|
||||||
really change much:
|
|
||||||
|
|
||||||
- You create change branches instead of feature branches, without the need of a
|
|
||||||
"feature/" or "change/" prefix in the branch name.
|
|
||||||
- Change branches are typically created from and merged back into "main" instead
|
|
||||||
of "develop".
|
|
||||||
- Creating a release is done by simply creating a git tag, typically on the main
|
|
||||||
branch.
|
|
||||||
|
|
||||||
In detail, the main differences between Git Flow and Common-Flow are:
|
|
||||||
|
|
||||||
- There is no "develop" branch, there is only a "main" branch which contains the
|
|
||||||
latest work. In Git Flow the main branch effectively ends up just being a
|
|
||||||
pointer to the latest release, despite the fact that Git Flow includes release
|
|
||||||
tags too. In Common-Flow you just look at the tags to find the latest release.
|
|
||||||
- There are no "feature" or "hotfix" branches, there's only "change" branches.
|
|
||||||
Any branch that is not main and introduces changes is a change branch. Change
|
|
||||||
branches also don't have an enforced naming convention, they just need to have
|
|
||||||
a "descriptive name". This makes things simpler and allows more flexibility.
|
|
||||||
- Release branches are available, but optional. Instead of enforcing the use of
|
|
||||||
release branches like Git Flow, Common-Flow only recommends the use of release
|
|
||||||
branches when it makes things easier. If creating a new release by tagging
|
|
||||||
"main" works for you, great, do that.
|
|
||||||
|
|
||||||
### Why use Common-Flow instead of GitHub Flow, and how does it differ?
|
|
||||||
|
|
||||||
Common-Flow is essentially GitHub Flow with the addition of a "Release" concept
|
|
||||||
that uses tags. It also attempts to define how certain common tasks are done,
|
|
||||||
like updating change/feature branches from their source branches for example.
|
|
||||||
This is to help end arguments about how such things are done.
|
|
||||||
|
|
||||||
If a deployment/release for you is just getting the latest code in the main
|
|
||||||
branch out without caring about bumping version numbers, GitHub Flow is a good
|
|
||||||
fit for you. You probably don't need the extras of Common-Flow.
|
|
||||||
|
|
||||||
However, if your deployments/releases have specific version numbers, then
|
|
||||||
Common-Flow gives you a simple set of rules for how to create and manage
|
|
||||||
releases, on top of what GitHub Flow already does.
|
|
||||||
|
|
||||||
### What does "descriptive name" mean for change branches?
|
|
||||||
|
|
||||||
It means what it sounds like. The name should be descriptive, as in by just
|
|
||||||
reading the name of the branch you should understand what the branch's purpose
|
|
||||||
is and what it does. Here's a few examples:
|
|
||||||
|
|
||||||
- add-2fa-support
|
|
||||||
- fix-login-issue
|
|
||||||
- remove-sort-by-middle-name-functionality
|
|
||||||
- update-font-awesome
|
|
||||||
- change-search-behavior
|
|
||||||
- improve-pagination-performance
|
|
||||||
- tweak-footer-style
|
|
||||||
|
|
||||||
Notice how none of these have any prefixes like "feature/" or "hotfix/", they're
|
|
||||||
not needed when branch names are properly descriptive. However, there's nothing
|
|
||||||
to say you can't use such prefixes if you want.
|
|
||||||
|
|
||||||
You can also add ticket numbers to the branch name if your team/org has that as
|
|
||||||
part of its process. But it is recommended that ticket numbers are added to the
|
|
||||||
end of the branch name. The ticket number is essentially metadata, so put it at
|
|
||||||
the end and out of the way of humans trying to read the descriptive name from
|
|
||||||
left to right.
|
|
||||||
|
|
||||||
### How do we release an emergency hotfix when the main branch is broken?
|
|
||||||
|
|
||||||
This should ideally never happen, however if it does you can do one of the
|
|
||||||
following:
|
|
||||||
|
|
||||||
- Review why the main branch is broken and revert the changes that caused the
|
|
||||||
issues. Then apply the hotfix and release.
|
|
||||||
- Or use a short-term release branch created from the latest release tag instead
|
|
||||||
of the main branch. Apply the hotfix to the release branch, create a release
|
|
||||||
tag on the release branch, and then merge it back into main.
|
|
||||||
|
|
||||||
In this situation, it is recommended you try to revert the offending changes
|
|
||||||
that's preventing a new release from main. But if that proves to be a
|
|
||||||
complicated task and you're short on time, a short-term release branch gives you
|
|
||||||
an instant fix to the situation at hand. You can then resolve the issues with
|
|
||||||
the main branch later.
|
|
||||||
|
|
||||||
### How do I handle monorepos?
|
|
||||||
|
|
||||||
Common-Flow works well with monorepos. The key considerations are:
|
|
||||||
|
|
||||||
- Use a single main branch for the entire monorepo. This keeps things simple and
|
|
||||||
ensures all packages/projects are always in a consistent state.
|
|
||||||
- For versioning, you have two main options:
|
|
||||||
- **Unified versioning**: All packages share the same version number. Simple
|
|
||||||
to manage, but may result in version bumps for packages that haven't
|
|
||||||
changed.
|
|
||||||
- **Independent versioning**: Each package has its own version. Use tags with
|
|
||||||
a package prefix, e.g., "package-a-2.1.0" or "package-a-v2.1.0". This allows
|
|
||||||
packages to evolve at their own pace.
|
|
||||||
- Change branches can span multiple packages. Describe the scope in the branch
|
|
||||||
name if helpful, e.g., "update-auth-across-services".
|
|
||||||
- For releases, if using independent versioning, you can create release branches
|
|
||||||
per package when needed, e.g., "release-package-a-2.1".
|
|
||||||
|
|
||||||
The core workflow remains the same: don't break main, use change branches, and
|
|
||||||
tag releases.
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
The Git Common-Flow specification is authored by [Jim
|
|
||||||
Myhrberg](https://jimeh.me/).
|
|
||||||
|
|
||||||
If you'd like to leave feedback, please [open an issue on
|
|
||||||
GitHub](https://github.com/jimeh/common-flow/issues).
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[Creative Commons - CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)
|
|
||||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
||||||
<!-- Circle outline -->
|
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"/>
|
|
||||||
<!-- Right half filled (dark/moon side) -->
|
|
||||||
<path fill="currentColor" d="M12 8.25a3.75 3.75 0 0 1 0 7.5z"/>
|
|
||||||
<!-- Left-side sun rays (top, top-left, left, bottom-left, bottom) -->
|
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 3v2.25M7.227 7.227 5.636 5.636M5.25 12H3M7.227 16.773l-1.591 1.591M12 18.75V21"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 633 B |
@@ -1,5 +1,7 @@
|
|||||||
---
|
---
|
||||||
import { Font } from "astro:assets";
|
import "@fontsource-variable/bricolage-grotesque";
|
||||||
|
import "@fontsource-variable/dm-sans";
|
||||||
|
import "@fontsource-variable/jetbrains-mono";
|
||||||
import "../styles/global.css";
|
import "../styles/global.css";
|
||||||
import { config } from "../config";
|
import { config } from "../config";
|
||||||
|
|
||||||
@@ -9,9 +11,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { title, description = config.description } = Astro.props;
|
const { title, description = config.description } = Astro.props;
|
||||||
const fullTitle = title.includes(config.title)
|
const fullTitle = title === config.title ? title : `${title} | ${config.title}`;
|
||||||
? title
|
|
||||||
: `${title} | ${config.title}`;
|
|
||||||
const canonicalUrl = Astro.url.href;
|
const canonicalUrl = Astro.url.href;
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -42,23 +42,12 @@ const canonicalUrl = Astro.url.href;
|
|||||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||||
|
|
||||||
<!-- Fonts -->
|
|
||||||
<Font
|
|
||||||
cssVariable="--font-bricolage"
|
|
||||||
preload={[{ weight: "700" }, { weight: "800" }]}
|
|
||||||
/>
|
|
||||||
<Font cssVariable="--font-dm-sans" preload={[{ weight: "400" }]} />
|
|
||||||
<Font cssVariable="--font-jetbrains" preload={[{ weight: "400" }]} />
|
|
||||||
|
|
||||||
<!-- Slot for page-specific head content -->
|
|
||||||
<slot name="head" />
|
|
||||||
|
|
||||||
<!-- Prevent flash of wrong theme -->
|
<!-- Prevent flash of wrong theme -->
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
(function () {
|
(function () {
|
||||||
const mode = localStorage.getItem("theme");
|
const mode = localStorage.getItem("theme");
|
||||||
const prefersDark = window.matchMedia(
|
const prefersDark = window.matchMedia(
|
||||||
"(prefers-color-scheme: dark)"
|
"(prefers-color-scheme: dark)",
|
||||||
).matches;
|
).matches;
|
||||||
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
@@ -74,7 +63,7 @@ const canonicalUrl = Astro.url.href;
|
|||||||
document.addEventListener("astro:after-swap", () => {
|
document.addEventListener("astro:after-swap", () => {
|
||||||
const mode = localStorage.getItem("theme");
|
const mode = localStorage.getItem("theme");
|
||||||
const prefersDark = window.matchMedia(
|
const prefersDark = window.matchMedia(
|
||||||
"(prefers-color-scheme: dark)"
|
"(prefers-color-scheme: dark)",
|
||||||
).matches;
|
).matches;
|
||||||
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
if (mode === "dark" || (mode !== "light" && prefersDark)) {
|
||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
|
|||||||
@@ -28,34 +28,14 @@ const content = fs.readFileSync(filePath, "utf-8");
|
|||||||
const markdown = content.replace(/^---[\s\S]*?---\n/, "");
|
const markdown = content.replace(/^---[\s\S]*?---\n/, "");
|
||||||
|
|
||||||
// Parse the content into sections (handles markdown -> HTML internally)
|
// Parse the content into sections (handles markdown -> HTML internally)
|
||||||
const parsed = await parseSpecContent(markdown);
|
const parsed = await parseSpecContent(markdown, version);
|
||||||
|
|
||||||
// Read SVG content for inline embedding
|
|
||||||
const svgFilePath = path.join(
|
|
||||||
process.cwd(),
|
|
||||||
"src/content/spec",
|
|
||||||
`${version}.svg`
|
|
||||||
);
|
|
||||||
let svgContent: string | null = null;
|
|
||||||
if (fs.existsSync(svgFilePath)) {
|
|
||||||
svgContent = fs.readFileSync(svgFilePath, "utf-8");
|
|
||||||
}
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title={spec.data.title}>
|
<BaseLayout title={spec.data.title}>
|
||||||
<Fragment slot="head">
|
|
||||||
<link
|
|
||||||
rel="alternate"
|
|
||||||
type="text/markdown"
|
|
||||||
href={`/spec/git-common-flow-v${version}.md`}
|
|
||||||
title="Raw Markdown"
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
|
|
||||||
<Header version={version} versions={versions} />
|
<Header version={version} versions={versions} />
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<Hero version={version} versions={versions} svgContent={svgContent} />
|
<Hero version={version} versions={versions} svgPath={parsed.svgPath} />
|
||||||
|
|
||||||
<AboutSection
|
<AboutSection
|
||||||
introduction={parsed.introduction}
|
introduction={parsed.introduction}
|
||||||
@@ -68,7 +48,6 @@ if (fs.existsSync(svgFilePath)) {
|
|||||||
terminologyTitle={parsed.terminologyTitle}
|
terminologyTitle={parsed.terminologyTitle}
|
||||||
specification={parsed.specification}
|
specification={parsed.specification}
|
||||||
tocItems={parsed.tocItems}
|
tocItems={parsed.tocItems}
|
||||||
version={version}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FAQSection items={parsed.faq} />
|
<FAQSection items={parsed.faq} />
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import type { APIRoute } from "astro";
|
|
||||||
import { getVersionInfo } from "../utils/versions";
|
|
||||||
|
|
||||||
export const GET: APIRoute = async () => {
|
|
||||||
const { currentVersion } = await getVersionInfo();
|
|
||||||
|
|
||||||
const content = `# Common-Flow
|
|
||||||
|
|
||||||
> A Git workflow specification combining GitHub Flow with versioned releases.
|
|
||||||
|
|
||||||
Common-Flow is a sensible git workflow based on GitHub Flow, with the addition
|
|
||||||
of versioned releases, optional release branches, and without the requirement
|
|
||||||
to deploy to production all the time.
|
|
||||||
|
|
||||||
## Docs
|
|
||||||
|
|
||||||
- [Git Common-Flow Specification](/spec/git-common-flow-v${currentVersion}.md): The complete Git Common-Flow v${currentVersion} specification in Markdown format
|
|
||||||
`;
|
|
||||||
|
|
||||||
return new Response(content, {
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "text/plain; charset=utf-8",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,531 +0,0 @@
|
|||||||
---
|
|
||||||
import { getCollection } from "astro:content";
|
|
||||||
import { Icon } from "astro-icon/components";
|
|
||||||
import * as fs from "node:fs";
|
|
||||||
import * as path from "node:path";
|
|
||||||
import { createHighlighter } from "shiki";
|
|
||||||
import { unified } from "unified";
|
|
||||||
import remarkParse from "remark-parse";
|
|
||||||
import remarkRehype from "remark-rehype";
|
|
||||||
import rehypeSlug from "rehype-slug";
|
|
||||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
|
||||||
import rehypeStringify from "rehype-stringify";
|
|
||||||
import { icons as heroicons } from "@iconify-json/heroicons";
|
|
||||||
import { getIconData, iconToSVG } from "@iconify/utils";
|
|
||||||
|
|
||||||
import BaseLayout from "../../../layouts/BaseLayout.astro";
|
|
||||||
import ThemeToggle from "../../../components/ThemeToggle.astro";
|
|
||||||
import { config } from "../../../config";
|
|
||||||
|
|
||||||
// Get the link icon SVG from heroicons for use in anchor links
|
|
||||||
const linkIconData = getIconData(heroicons, "link-20-solid");
|
|
||||||
const linkIconSvg = linkIconData ? iconToSVG(linkIconData) : null;
|
|
||||||
|
|
||||||
// Parse the icon body into hast nodes for rehype
|
|
||||||
function parseIconBody(body: string): import("hast").ElementContent[] {
|
|
||||||
// Simple regex-based parser for SVG path/g elements
|
|
||||||
const elements: import("hast").ElementContent[] = [];
|
|
||||||
const tagRegex = /<(\w+)([^>]*)(?:\/>|>([\s\S]*?)<\/\1>)/g;
|
|
||||||
let match;
|
|
||||||
|
|
||||||
while ((match = tagRegex.exec(body)) !== null) {
|
|
||||||
const [, tagName, attrs, children] = match;
|
|
||||||
const properties: Record<string, string> = {};
|
|
||||||
|
|
||||||
// Parse attributes
|
|
||||||
const attrRegex = /(\w+(?:-\w+)*)="([^"]*)"/g;
|
|
||||||
let attrMatch;
|
|
||||||
while ((attrMatch = attrRegex.exec(attrs)) !== null) {
|
|
||||||
properties[attrMatch[1]] = attrMatch[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.push({
|
|
||||||
type: "element",
|
|
||||||
tagName,
|
|
||||||
properties,
|
|
||||||
children: children ? parseIconBody(children) : [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
|
||||||
const specs = await getCollection("spec");
|
|
||||||
return specs.map((spec) => ({
|
|
||||||
params: { version: spec.data.version },
|
|
||||||
props: { spec },
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const { spec } = Astro.props;
|
|
||||||
const version = spec.data.version;
|
|
||||||
|
|
||||||
// Read the markdown file
|
|
||||||
const filePath = path.join(process.cwd(), "src/content/spec", `${version}.md`);
|
|
||||||
const content = fs.readFileSync(filePath, "utf-8");
|
|
||||||
|
|
||||||
// Remove frontmatter
|
|
||||||
const markdown = content.replace(/^---[\s\S]*?---\n/, "");
|
|
||||||
|
|
||||||
// Create syntax highlighter for code view
|
|
||||||
const highlighter = await createHighlighter({
|
|
||||||
themes: ["github-light", "github-dark"],
|
|
||||||
langs: ["markdown"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const highlightedHtml = highlighter.codeToHtml(markdown, {
|
|
||||||
lang: "markdown",
|
|
||||||
themes: {
|
|
||||||
light: "github-light",
|
|
||||||
dark: "github-dark",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Build the anchor link icon content from the heroicons data
|
|
||||||
const anchorIconContent = linkIconSvg
|
|
||||||
? {
|
|
||||||
type: "element" as const,
|
|
||||||
tagName: "svg",
|
|
||||||
properties: {
|
|
||||||
className: ["anchor-icon"],
|
|
||||||
viewBox: `0 0 ${linkIconSvg.attributes.width} ${linkIconSvg.attributes.height}`,
|
|
||||||
fill: "currentColor",
|
|
||||||
"aria-hidden": "true",
|
|
||||||
},
|
|
||||||
children: parseIconBody(linkIconSvg.body),
|
|
||||||
}
|
|
||||||
: { type: "text" as const, value: "#" };
|
|
||||||
|
|
||||||
// Render markdown to HTML for preview view
|
|
||||||
const previewHtml = await unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkRehype)
|
|
||||||
.use(rehypeSlug)
|
|
||||||
.use(rehypeAutolinkHeadings, {
|
|
||||||
behavior: "append",
|
|
||||||
properties: {
|
|
||||||
className: ["anchor-link"],
|
|
||||||
ariaLabel: "Link to this section",
|
|
||||||
},
|
|
||||||
content: anchorIconContent,
|
|
||||||
})
|
|
||||||
.use(rehypeStringify)
|
|
||||||
.process(markdown)
|
|
||||||
.then((file) => String(file));
|
|
||||||
---
|
|
||||||
|
|
||||||
<BaseLayout title={`${spec.data.title} - Markdown`}>
|
|
||||||
<Fragment slot="head">
|
|
||||||
<link
|
|
||||||
rel="alternate"
|
|
||||||
type="text/markdown"
|
|
||||||
href={`/spec/git-common-flow-v${version}.md`}
|
|
||||||
title="Raw Markdown"
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
|
|
||||||
<!-- Header -->
|
|
||||||
<header
|
|
||||||
class="sticky top-0 z-50 border-b
|
|
||||||
border-gray-200 dark:border-neutral-800
|
|
||||||
backdrop-blur-xl bg-gray-50/85 dark:bg-neutral-950/85"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="max-w-6xl mx-auto px-4 sm:px-6 h-16 flex items-center
|
|
||||||
justify-between"
|
|
||||||
>
|
|
||||||
<!-- Back link and title -->
|
|
||||||
<div class="flex items-center gap-4">
|
|
||||||
<a
|
|
||||||
href={`/spec/${version}`}
|
|
||||||
class="inline-flex items-center gap-1.5 text-sm font-medium
|
|
||||||
text-gray-600 dark:text-neutral-400
|
|
||||||
hover:text-sky-600 dark:hover:text-sky-400 transition-colors"
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:arrow-left" class="w-4 h-4" />
|
|
||||||
<span class="hidden sm:inline">Back to Spec</span>
|
|
||||||
</a>
|
|
||||||
<span class="hidden sm:inline text-gray-300 dark:text-neutral-700"
|
|
||||||
>|</span
|
|
||||||
>
|
|
||||||
<span class="font-display font-bold text-lg tracking-tight">
|
|
||||||
Markdown
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="px-2 py-0.5 text-xs font-semibold rounded-full
|
|
||||||
bg-sky-100 text-sky-700
|
|
||||||
dark:bg-sky-900/50 dark:text-sky-300"
|
|
||||||
>
|
|
||||||
v{version}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Right side: Theme, GitHub -->
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<ThemeToggle />
|
|
||||||
|
|
||||||
<a
|
|
||||||
href={config.repoUrl}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="p-2 rounded-lg transition-colors
|
|
||||||
text-gray-500 dark:text-neutral-500
|
|
||||||
hover:text-gray-950 dark:hover:text-neutral-50
|
|
||||||
hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
||||||
aria-label="View on GitHub"
|
|
||||||
>
|
|
||||||
<Icon name="simple-icons:github" class="w-5 h-5" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- Main content -->
|
|
||||||
<main class="max-w-6xl mx-auto px-4 sm:px-6 py-8">
|
|
||||||
<div class="relative">
|
|
||||||
<!-- Hidden raw text for copying -->
|
|
||||||
<div id="markdown-raw" class="hidden">{markdown}</div>
|
|
||||||
<!-- Filename heading and actions -->
|
|
||||||
<div class="flex flex-col items-center mb-6">
|
|
||||||
<h1
|
|
||||||
class="font-mono font-semibold text-sm sm:text-base
|
|
||||||
text-gray-700 dark:text-neutral-300
|
|
||||||
max-w-full overflow-hidden text-ellipsis
|
|
||||||
whitespace-nowrap [direction:rtl] sm:[direction:ltr]"
|
|
||||||
>
|
|
||||||
git-common-flow-v{version}.md
|
|
||||||
</h1>
|
|
||||||
<div
|
|
||||||
class="flex flex-col sm:flex-row items-center gap-2 sm:gap-3 mt-3
|
|
||||||
w-full sm:w-auto"
|
|
||||||
>
|
|
||||||
<!-- Separator (hidden on mobile) -->
|
|
||||||
<span
|
|
||||||
class="hidden sm:inline text-gray-300 dark:text-neutral-700
|
|
||||||
order-2"
|
|
||||||
>|</span
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Copy and Download buttons -->
|
|
||||||
<div class="flex items-center gap-3 order-1 sm:order-3">
|
|
||||||
<!-- Copy button -->
|
|
||||||
<button
|
|
||||||
id="copy-btn"
|
|
||||||
type="button"
|
|
||||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm
|
|
||||||
font-medium rounded-lg transition-colors cursor-pointer
|
|
||||||
text-gray-600 dark:text-neutral-400
|
|
||||||
hover:bg-gray-100 hover:text-gray-950
|
|
||||||
dark:hover:bg-neutral-800 dark:hover:text-neutral-50"
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:clipboard-document" class="w-4 h-4" />
|
|
||||||
<span data-copy-text>Copy</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Raw button -->
|
|
||||||
<a
|
|
||||||
href={`/spec/git-common-flow-v${version}.md`}
|
|
||||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm
|
|
||||||
font-medium rounded-lg transition-colors
|
|
||||||
text-gray-600 dark:text-neutral-400
|
|
||||||
hover:bg-gray-100 hover:text-gray-950
|
|
||||||
dark:hover:bg-neutral-800 dark:hover:text-neutral-50"
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:document-text" class="w-4 h-4" />
|
|
||||||
<span>Raw</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Download button -->
|
|
||||||
<button
|
|
||||||
id="download-btn"
|
|
||||||
type="button"
|
|
||||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm
|
|
||||||
font-medium rounded-lg transition-colors cursor-pointer
|
|
||||||
text-gray-600 dark:text-neutral-400
|
|
||||||
hover:bg-gray-100 hover:text-gray-950
|
|
||||||
dark:hover:bg-neutral-800 dark:hover:text-neutral-50"
|
|
||||||
data-filename={`git-common-flow-v${version}.md`}
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:arrow-down-tray" class="w-4 h-4" />
|
|
||||||
<span>Download</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Code/Preview toggle -->
|
|
||||||
<div
|
|
||||||
id="toggle-container"
|
|
||||||
class="relative inline-flex rounded-lg p-0.5 order-2 sm:order-1
|
|
||||||
mt-2 sm:mt-0 bg-gray-100 dark:bg-neutral-800"
|
|
||||||
>
|
|
||||||
<!-- Sliding indicator -->
|
|
||||||
<div
|
|
||||||
id="toggle-indicator"
|
|
||||||
class="absolute top-0.5 h-[calc(100%-4px)] rounded-md
|
|
||||||
bg-white dark:bg-neutral-700 shadow-sm
|
|
||||||
transition-all duration-200 ease-out"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
id="toggle-preview"
|
|
||||||
type="button"
|
|
||||||
class="relative z-10 inline-flex items-center gap-1.5 px-3 py-1
|
|
||||||
text-sm font-medium rounded-md cursor-pointer
|
|
||||||
transition-colors duration-200
|
|
||||||
text-gray-900 dark:text-neutral-100"
|
|
||||||
aria-pressed="true"
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:eye" class="w-4 h-4" />
|
|
||||||
Preview
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
id="toggle-code"
|
|
||||||
type="button"
|
|
||||||
class="relative z-10 inline-flex items-center gap-1.5 px-3 py-1
|
|
||||||
text-sm font-medium rounded-md cursor-pointer
|
|
||||||
transition-colors duration-200
|
|
||||||
text-gray-600 dark:text-neutral-400
|
|
||||||
hover:text-gray-900 dark:hover:text-neutral-200"
|
|
||||||
aria-pressed="false"
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:code-bracket" class="w-4 h-4" />
|
|
||||||
Code
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Code view (hidden by default) -->
|
|
||||||
<div
|
|
||||||
id="code-view"
|
|
||||||
class="hidden [&_pre]:overflow-x-auto [&_pre]:rounded-xl [&_pre]:p-6
|
|
||||||
[&_pre]:text-sm [&_pre]:leading-relaxed
|
|
||||||
[&_pre]:border [&_pre]:border-gray-200
|
|
||||||
dark:[&_pre]:border-neutral-800"
|
|
||||||
set:html={highlightedHtml}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Preview view (visible by default) -->
|
|
||||||
<div
|
|
||||||
id="preview-view"
|
|
||||||
class="prose prose-slate dark:prose-invert max-w-none
|
|
||||||
rounded-xl p-6 border border-gray-200
|
|
||||||
dark:border-neutral-800 bg-white dark:bg-neutral-900"
|
|
||||||
set:html={previewHtml}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</BaseLayout>
|
|
||||||
|
|
||||||
<style is:global>
|
|
||||||
/* Shiki dual theme support - override inline styles in dark mode */
|
|
||||||
.dark .shiki {
|
|
||||||
color: var(--shiki-dark) !important;
|
|
||||||
background-color: var(--shiki-dark-bg) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .shiki span {
|
|
||||||
color: var(--shiki-dark) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Preview anchor links */
|
|
||||||
#preview-view :is(h1, h2, h3, h4, h5, h6) {
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
#preview-view .anchor-link {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
text-decoration: none;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 150ms ease;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#preview-view :is(h1, h2, h3, h4, h5, h6):hover .anchor-link {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#preview-view .anchor-link:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#preview-view .anchor-icon {
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
color: var(--color-slate-400);
|
|
||||||
}
|
|
||||||
|
|
||||||
#preview-view .anchor-link:hover .anchor-icon {
|
|
||||||
color: var(--color-sky-500);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark #preview-view .anchor-icon {
|
|
||||||
color: var(--color-neutral-500);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark #preview-view .anchor-link:hover .anchor-icon {
|
|
||||||
color: var(--color-sky-400);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function initPage() {
|
|
||||||
const copyBtn = document.getElementById("copy-btn");
|
|
||||||
const downloadBtn = document.getElementById("download-btn");
|
|
||||||
const rawContent = document.getElementById("markdown-raw");
|
|
||||||
const copyText = copyBtn?.querySelector("[data-copy-text]");
|
|
||||||
|
|
||||||
const toggleContainer = document.getElementById("toggle-container");
|
|
||||||
const toggleCode = document.getElementById("toggle-code");
|
|
||||||
const togglePreview = document.getElementById("toggle-preview");
|
|
||||||
const toggleIndicator = document.getElementById("toggle-indicator");
|
|
||||||
const codeView = document.getElementById("code-view");
|
|
||||||
const previewView = document.getElementById("preview-view");
|
|
||||||
|
|
||||||
if (!rawContent) return;
|
|
||||||
|
|
||||||
// Text color classes for active/inactive states
|
|
||||||
const activeTextClasses = ["text-gray-900", "dark:text-neutral-100"];
|
|
||||||
const inactiveTextClasses = [
|
|
||||||
"text-gray-600",
|
|
||||||
"dark:text-neutral-400",
|
|
||||||
"hover:text-gray-900",
|
|
||||||
"dark:hover:text-neutral-200",
|
|
||||||
];
|
|
||||||
|
|
||||||
function updateIndicator(button: HTMLElement) {
|
|
||||||
if (!toggleIndicator || !toggleContainer) return;
|
|
||||||
|
|
||||||
const containerRect = toggleContainer.getBoundingClientRect();
|
|
||||||
const buttonRect = button.getBoundingClientRect();
|
|
||||||
|
|
||||||
// Calculate position relative to container (accounting for container padding)
|
|
||||||
const left = buttonRect.left - containerRect.left;
|
|
||||||
|
|
||||||
toggleIndicator.style.left = `${left}px`;
|
|
||||||
toggleIndicator.style.width = `${buttonRect.width}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setActiveToggle(isCode: boolean) {
|
|
||||||
if (
|
|
||||||
!toggleCode ||
|
|
||||||
!togglePreview ||
|
|
||||||
!toggleIndicator ||
|
|
||||||
!codeView ||
|
|
||||||
!previewView
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (isCode) {
|
|
||||||
// Show code, hide preview
|
|
||||||
codeView.classList.remove("hidden");
|
|
||||||
previewView.classList.add("hidden");
|
|
||||||
|
|
||||||
// Update indicator position and size
|
|
||||||
updateIndicator(toggleCode);
|
|
||||||
|
|
||||||
// Update text colors
|
|
||||||
toggleCode.classList.add(...activeTextClasses);
|
|
||||||
toggleCode.classList.remove(...inactiveTextClasses);
|
|
||||||
toggleCode.setAttribute("aria-pressed", "true");
|
|
||||||
|
|
||||||
togglePreview.classList.remove(...activeTextClasses);
|
|
||||||
togglePreview.classList.add(...inactiveTextClasses);
|
|
||||||
togglePreview.setAttribute("aria-pressed", "false");
|
|
||||||
} else {
|
|
||||||
// Show preview, hide code
|
|
||||||
codeView.classList.add("hidden");
|
|
||||||
previewView.classList.remove("hidden");
|
|
||||||
|
|
||||||
// Update indicator position and size
|
|
||||||
updateIndicator(togglePreview);
|
|
||||||
|
|
||||||
// Update text colors
|
|
||||||
togglePreview.classList.add(...activeTextClasses);
|
|
||||||
togglePreview.classList.remove(...inactiveTextClasses);
|
|
||||||
togglePreview.setAttribute("aria-pressed", "true");
|
|
||||||
|
|
||||||
toggleCode.classList.remove(...activeTextClasses);
|
|
||||||
toggleCode.classList.add(...inactiveTextClasses);
|
|
||||||
toggleCode.setAttribute("aria-pressed", "false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize indicator position after layout is complete
|
|
||||||
// Use double requestAnimationFrame to ensure layout/paint is finished,
|
|
||||||
// which fixes sizing issues on iOS Safari initial page load
|
|
||||||
function initializeIndicator() {
|
|
||||||
if (togglePreview) {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
updateIndicator(togglePreview);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for fonts to load before measuring, then initialize
|
|
||||||
if (document.fonts && document.fonts.ready) {
|
|
||||||
document.fonts.ready.then(initializeIndicator);
|
|
||||||
} else {
|
|
||||||
initializeIndicator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle event listeners
|
|
||||||
toggleCode?.addEventListener("click", () => setActiveToggle(true));
|
|
||||||
togglePreview?.addEventListener("click", () => setActiveToggle(false));
|
|
||||||
|
|
||||||
function showCopiedFeedback() {
|
|
||||||
if (copyText) {
|
|
||||||
copyText.textContent = "Copied!";
|
|
||||||
setTimeout(() => {
|
|
||||||
copyText.textContent = "Copy";
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy button
|
|
||||||
if (copyBtn) {
|
|
||||||
copyBtn.addEventListener("click", async () => {
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(rawContent.textContent || "");
|
|
||||||
showCopiedFeedback();
|
|
||||||
} catch {
|
|
||||||
// Fallback for older browsers
|
|
||||||
const textarea = document.createElement("textarea");
|
|
||||||
textarea.value = rawContent.textContent || "";
|
|
||||||
textarea.style.position = "fixed";
|
|
||||||
textarea.style.opacity = "0";
|
|
||||||
document.body.appendChild(textarea);
|
|
||||||
textarea.select();
|
|
||||||
document.execCommand("copy");
|
|
||||||
document.body.removeChild(textarea);
|
|
||||||
showCopiedFeedback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download button
|
|
||||||
if (downloadBtn) {
|
|
||||||
downloadBtn.addEventListener("click", () => {
|
|
||||||
const filename = downloadBtn.dataset.filename || "common-flow.md";
|
|
||||||
const content = rawContent.textContent || "";
|
|
||||||
const blob = new Blob([content], { type: "text/markdown" });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = filename;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
document.body.removeChild(a);
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initPage();
|
|
||||||
document.addEventListener("astro:after-swap", initPage);
|
|
||||||
</script>
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import type { APIRoute, GetStaticPaths } from "astro";
|
|
||||||
import { getCollection } from "astro:content";
|
|
||||||
import * as fs from "node:fs";
|
|
||||||
import * as path from "node:path";
|
|
||||||
|
|
||||||
export const getStaticPaths: GetStaticPaths = async () => {
|
|
||||||
const specs = await getCollection("spec");
|
|
||||||
return specs.map((spec) => ({
|
|
||||||
params: { version: spec.data.version },
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GET: APIRoute = ({ params }) => {
|
|
||||||
const version = params.version;
|
|
||||||
const filePath = path.join(
|
|
||||||
process.cwd(),
|
|
||||||
"src/content/spec",
|
|
||||||
`${version}.md`
|
|
||||||
);
|
|
||||||
const content = fs.readFileSync(filePath, "utf-8");
|
|
||||||
const markdown = content.replace(/^---[\s\S]*?---\n/, "");
|
|
||||||
const filename = `git-common-flow-v${version}.md`;
|
|
||||||
|
|
||||||
return new Response(markdown, {
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "text/markdown; charset=utf-8",
|
|
||||||
"Content-Disposition": `inline; filename="${filename}"`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -8,10 +8,10 @@
|
|||||||
--color-accent: theme(colors.sky.500);
|
--color-accent: theme(colors.sky.500);
|
||||||
--color-accent-light: theme(colors.sky.400);
|
--color-accent-light: theme(colors.sky.400);
|
||||||
|
|
||||||
/* Fonts - via Astro experimental font API (fontsource provider) */
|
/* Fonts - self-hosted via fontsource */
|
||||||
--font-display: var(--font-bricolage);
|
--font-display: "Bricolage Grotesque Variable", system-ui, sans-serif;
|
||||||
--font-sans: var(--font-dm-sans);
|
--font-sans: "DM Sans Variable", system-ui, sans-serif;
|
||||||
--font-mono: var(--font-jetbrains);
|
--font-mono: "JetBrains Mono Variable", "SF Mono", Consolas, monospace;
|
||||||
|
|
||||||
/* Sizing */
|
/* Sizing */
|
||||||
--header-height: 4rem;
|
--header-height: 4rem;
|
||||||
@@ -400,11 +400,11 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.prose-spec strong {
|
.prose-spec strong {
|
||||||
color: theme(colors.neutral.700);
|
color: theme(colors.slate.950);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .prose-spec strong {
|
.dark .prose-spec strong {
|
||||||
color: theme(colors.neutral.300);
|
color: theme(colors.neutral.50);
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose-spec li {
|
.prose-spec li {
|
||||||
@@ -499,9 +499,9 @@ html {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hover color for clause anchor link */
|
/* Orange color on direct hover of the link */
|
||||||
.prose-spec .clause-link:hover {
|
.prose-spec .clause-link:hover {
|
||||||
color: theme(colors.sky.500);
|
color: theme(colors.orange.500);
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose-spec img {
|
.prose-spec img {
|
||||||
|
|||||||
@@ -8,7 +8,14 @@ import remarkRehype from "remark-rehype";
|
|||||||
import rehypeStringify from "rehype-stringify";
|
import rehypeStringify from "rehype-stringify";
|
||||||
import { getIconData, iconToSVG, iconToHTML } from "@iconify/utils";
|
import { getIconData, iconToSVG, iconToHTML } from "@iconify/utils";
|
||||||
import heroicons from "@iconify-json/heroicons/icons.json";
|
import heroicons from "@iconify-json/heroicons/icons.json";
|
||||||
import type { Root, RootContent, Heading, List, ListItem, Html } from "mdast";
|
import type {
|
||||||
|
Root,
|
||||||
|
RootContent,
|
||||||
|
Heading,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Html,
|
||||||
|
} from "mdast";
|
||||||
import type { Root as HastRoot } from "hast";
|
import type { Root as HastRoot } from "hast";
|
||||||
|
|
||||||
export interface TocItem {
|
export interface TocItem {
|
||||||
@@ -32,6 +39,7 @@ export interface SpecSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ParsedSpec {
|
export interface ParsedSpec {
|
||||||
|
svgPath: string;
|
||||||
introduction: string;
|
introduction: string;
|
||||||
summary: string;
|
summary: string;
|
||||||
terminology: string;
|
terminology: string;
|
||||||
@@ -339,7 +347,10 @@ function buildTocItems(parsed: Partial<ParsedSpec>): TocItem[] {
|
|||||||
*/
|
*/
|
||||||
export async function parseSpecContent(
|
export async function parseSpecContent(
|
||||||
markdown: string,
|
markdown: string,
|
||||||
|
version: string,
|
||||||
): Promise<ParsedSpec> {
|
): Promise<ParsedSpec> {
|
||||||
|
const svgPath = `/spec/${version}.svg`;
|
||||||
|
|
||||||
// Parse markdown to AST
|
// Parse markdown to AST
|
||||||
const tree = unified().use(remarkParse).parse(markdown) as Root;
|
const tree = unified().use(remarkParse).parse(markdown) as Root;
|
||||||
|
|
||||||
@@ -419,6 +430,7 @@ export async function parseSpecContent(
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const parsed: ParsedSpec = {
|
const parsed: ParsedSpec = {
|
||||||
|
svgPath,
|
||||||
introduction,
|
introduction,
|
||||||
summary,
|
summary,
|
||||||
terminology,
|
terminology,
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "astro/tsconfigs/strict",
|
"extends": "astro/tsconfigs/strict",
|
||||||
"include": [
|
"include": [".astro/types.d.ts", "**/*"],
|
||||||
".astro/types.d.ts",
|
"exclude": ["dist", "docs"]
|
||||||
"**/*"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"dist"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "commonflow-org",
|
|
||||||
"compatibility_date": "2026-01-12",
|
|
||||||
"assets": {
|
|
||||||
"directory": "./dist"
|
|
||||||
}
|
|
||||||
}
|
|
||||||