mirror of
https://github.com/jimeh/commonflow.org.git
synced 2026-02-19 05:46:40 +00:00
522 lines
62 KiB
HTML
522 lines
62 KiB
HTML
<!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/"><title>Git Common-Flow 1.0.0-rc.5 | 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.5 | 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/"><!-- Twitter --><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Git Common-Flow 1.0.0-rc.5 | 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.N5gX3U6n.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.5</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="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.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="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 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"> About </a><a href="#spec" class="nav-link inline-flex items-center 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"> Spec </a><a href="#faq" class="nav-link inline-flex items-center 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"> 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.5</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="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.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="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 block py-2 text-gray-600 dark:text-neutral-400
|
|
hover:text-sky-600" data-nav-link data-section-id="about"> About </a><a href="#spec" class="nav-link block py-2 text-gray-600 dark:text-neutral-400
|
|
hover:text-sky-600" data-nav-link data-section-id="spec"> Spec </a><a href="#faq" class="nav-link block py-2 text-gray-600 dark:text-neutral-400
|
|
hover:text-sky-600" data-nav-link data-section-id="faq"> 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.5</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="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.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="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.5 </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.5.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"><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 most commonly 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> <!-- 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"><ul>
|
|
<li>The "master" branch is the mainline branch with latest changes, and must not
|
|
be broken.</li>
|
|
<li>Changes (features, bugfixes, etc.) are done on "change branches" created from
|
|
the master branch.</li>
|
|
<li>Rebase change branches <a href="https://i.imgur.com/1RS8x2d.png">early and often</a>.</li>
|
|
<li>When a change branch is stable and ready, it is merged back in to master.</li>
|
|
<li>A release is just a git tag who's name is the exact release version string
|
|
(e.g. "2.11.4").</li>
|
|
<li>Release branches can be used to avoid change freezes on master. They are not
|
|
required, instead they are available if you need them.</li>
|
|
</ul></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="https://creativecommons.org/licenses/by/4.0/">Creative Commons - CC BY 4.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="#spec-tldr" 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="spec-tldr"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 1. </span> <span>TL;DR</span> </a><a href="#spec-the-master-branch" 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="spec-the-master-branch"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 2. </span> <span>The Master Branch</span> </a><a href="#spec-change-branches" 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="spec-change-branches"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 3. </span> <span>Change Branches</span> </a><a href="#spec-pull-requests" 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="spec-pull-requests"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 4. </span> <span>Pull Requests</span> </a><a href="#spec-versioning" 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="spec-versioning"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 5. </span> <span>Versioning</span> </a><a href="#spec-releases" 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="spec-releases"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 6. </span> <span>Releases</span> </a><a href="#spec-short-term-release-branches" 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="spec-short-term-release-branches"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 7. </span> <span>Short-Term Release Branches</span> </a><a href="#spec-long-term-release-branches" 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="spec-long-term-release-branches"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 8. </span> <span>Long-term Release Branches</span> </a><a href="#spec-bug-fixes-rollback" 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="spec-bug-fixes-rollback"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 9. </span> <span>Bug Fixes & Rollback</span> </a><a href="#spec-git-best-practices" 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="spec-git-best-practices"> <span class="shrink-0 w-6 text-gray-400 dark:text-neutral-600"> 10. </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="#spec-tldr" 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="#spec-the-master-branch" 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="#spec-change-branches" 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="#spec-pull-requests" 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="#spec-versioning" 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="#spec-releases" 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="#spec-short-term-release-branches" 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>Short-Term Release Branches</span> </a><a href="#spec-long-term-release-branches" 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>Long-term Release Branches</span> </a><a href="#spec-bug-fixes-rollback" 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>Bug Fixes & Rollback</span> </a><a href="#spec-git-best-practices" 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"> 10. </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. Is
|
|
effectively just a git tag named after the version of the release.</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="spec-tldr">TL;DR
|
|
<ol>
|
|
<li>Do not break the master branch.</li>
|
|
<li>A release is a git tag.</li>
|
|
</ol>
|
|
</li>
|
|
<li id="spec-the-master-branch">The Master Branch
|
|
<ol>
|
|
<li>A branch named "master" MUST exist and it MUST be referred to as the
|
|
"master branch".</li>
|
|
<li>The master branch MUST always be in a non-broken state with its test
|
|
suite passing.</li>
|
|
<li>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>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="spec-change-branches">Change Branches
|
|
<ol>
|
|
<li>Each change (feature, bugfix, etc.) MUST be performed on separate
|
|
branches that SHOULD be referred to as "change branches".</li>
|
|
<li>All change branches MUST have descriptive names.</li>
|
|
<li>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.</li>
|
|
<li>You SHOULD regularly push your work to the same named branch on the
|
|
remote server.</li>
|
|
<li>You SHOULD create separate change branches for each distinctly different
|
|
change. You SHOULD NOT include multiple unrelated changes into a single
|
|
change branch.</li>
|
|
<li>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>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>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".</li>
|
|
<li>If there is a truly valid technical reason to not use rebase when
|
|
updating change branches, then you can 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, pick one and stick to it.</li>
|
|
</ol>
|
|
</li>
|
|
<li id="spec-pull-requests">Pull Requests
|
|
<ol>
|
|
<li>To merge a change branch into its merge target, you MUST open a "pull
|
|
request" (or equivalent).</li>
|
|
<li>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.</li>
|
|
<li>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.</li>
|
|
<li>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>To get feedback, help, or generally just discuss a change branch with
|
|
others, it is RECOMMENDED you create a 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.</li>
|
|
</ol>
|
|
</li>
|
|
<li id="spec-versioning">Versioning
|
|
<ol>
|
|
<li>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 to
|
|
indicate it is a version that is being referred to.</li>
|
|
<li>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".</li>
|
|
<li>It is OPTIONAL, but RECOMMENDED to also keep the version string
|
|
hard-coded somewhere in the project code-base.</li>
|
|
<li>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.</li>
|
|
<li>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.</li>
|
|
<li>It is OPTIONAL, but RECOMMENDED that that the version string follows
|
|
Semantic Versioning (<a href="http://semver.org/">http://semver.org/</a>).</li>
|
|
</ol>
|
|
</li>
|
|
<li id="spec-releases">Releases
|
|
<ol>
|
|
<li>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".</li>
|
|
<li>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". It is however RECOMMENDED
|
|
that you do not use a "v" prefix. You MUST NOT use a mixture of "v"
|
|
prefixed and non-prefixed tags. Pick one form and stick to it.</li>
|
|
<li>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.</li>
|
|
<li>When using version bump commits, the release tag MUST be placed on the
|
|
version bump commit.</li>
|
|
<li>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 master
|
|
branch.</li>
|
|
<li>The version bump commit SHOULD 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 SHOULD read: "Bump version to
|
|
2.11.4"</li>
|
|
<li>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>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 MUST start on the third line.</li>
|
|
</ol>
|
|
</li>
|
|
<li id="spec-short-term-release-branches">Short-Term Release Branches
|
|
<ol>
|
|
<li>Any branch that has a name starting with "release-" SHOULD be referred to
|
|
as a "release branch".</li>
|
|
<li>Any release branch which has a name ending with a specific version
|
|
string, MUST be referred to as a "short-term release branch".</li>
|
|
<li>Use of short-term release branches are OPTIONAL, and intended to be used
|
|
to create a specific versioned release.</li>
|
|
<li>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>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".</li>
|
|
<li>When using a short-term release branch to create a release, the release
|
|
tag and if used, version bump commit, MUST be placed directly on the
|
|
short-term release branch itself.</li>
|
|
<li>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>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 master branch.</li>
|
|
</ol>
|
|
</li>
|
|
<li id="spec-long-term-release-branches">Long-term Release Branches
|
|
<ol>
|
|
<li>Any release branch which has a name ending with a non-specific 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.</li>
|
|
<li>Use of long-term release branches are OPTIONAL, and intended 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>A long-term release branch MUST have a name with a non-specific version
|
|
number. For example a long-term release branch for creating new 2.9.x
|
|
releases MUST be named "release-2.9".</li>
|
|
<li>Long-term release branches for maintenance releases of older versions
|
|
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" from the "2.9.7" release tag. The security fix release will
|
|
then end up being version "2.9.8".</li>
|
|
<li>To create a new release from a long-term release branch, you MUST follow
|
|
the same process as a release from the master branch, except the
|
|
long-term release branch takes the place of the master branch.</li>
|
|
<li>A long-term release branch should be treated with the same respect as the
|
|
master branch. It is effectively the master branch for the release series
|
|
in question. Meaning it MUST always be in a non-broken state, MUST NOT be
|
|
force pushed to, etc.</li>
|
|
</ol>
|
|
</li>
|
|
<li id="spec-bug-fixes-rollback">Bug Fixes & Rollback
|
|
<ol>
|
|
<li>You MUST NOT under any circumstances force push to the master branch or
|
|
to long-term release branches.</li>
|
|
<li>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>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="spec-git-best-practices">Git Best Practices
|
|
<ol>
|
|
<li>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>You SHOULD never blindly commit all changes with "git commit -a". It is
|
|
RECOMMENDED you use "git add -i" or "git add -p" to add individual
|
|
changes to the staging area so you are fully aware of what you are
|
|
committing.</li>
|
|
<li>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>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>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>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> <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 class="border-b border-gray-200 dark:border-neutral-800" data-faq-item> <button class="flex justify-between items-center w-full py-6 text-left
|
|
font-display text-lg font-semibold cursor-pointer
|
|
transition-colors
|
|
text-gray-950 dark:text-neutral-50
|
|
hover:text-sky-600" aria-expanded="false" data-faq-trigger> <span class="pr-4">Why use Common-Flow instead of Git Flow, and how does it differ?</span> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-5 h-5 flex-shrink-0 transition-transform duration-200" data-faq-icon="true" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out" data-faq-content> <div class="overflow-hidden"> <div class="pb-6 text-gray-600 dark:text-neutral-400 prose-spec"><p>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:</p>
|
|
<ul>
|
|
<li>You create change branches instead of feature branches, without the need of a
|
|
"feature/" or "change/" prefix in the branch name.</li>
|
|
<li>Change branches are typically created from and merged back into "master"
|
|
instead of "develop".</li>
|
|
<li>Creating a release is done by simply creating a git tag, typically on the
|
|
master branch.</li>
|
|
</ul>
|
|
<p>In detail, the main differences between Git Flow and Common-Flow are:</p>
|
|
<ul>
|
|
<li>There is no "develop" branch, there is only a "master" branch which contains
|
|
the latest work. In Git Flow the master 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.</li>
|
|
<li>There are no "feature" or "hotfix" branches, there's only "change"
|
|
branches. Any branch that is not master and introduces changes is a change
|
|
branch. Change branches also don't have a enforced naming convention, they
|
|
just have to have a "descriptive name". This makes things simpler and allows
|
|
more flexibility.</li>
|
|
<li>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
|
|
"master" works for you, great, do that.</li>
|
|
</ul></div> </div> </div> </div><div class="border-b border-gray-200 dark:border-neutral-800" data-faq-item> <button class="flex justify-between items-center w-full py-6 text-left
|
|
font-display text-lg font-semibold cursor-pointer
|
|
transition-colors
|
|
text-gray-950 dark:text-neutral-50
|
|
hover:text-sky-600" aria-expanded="false" data-faq-trigger> <span class="pr-4">Why use Common-Flow instead of GitHub Flow, and how does it differ?</span> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-5 h-5 flex-shrink-0 transition-transform duration-200" data-faq-icon="true" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out" data-faq-content> <div class="overflow-hidden"> <div class="pb-6 text-gray-600 dark:text-neutral-400 prose-spec"><p>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.</p>
|
|
<p>If a deployment/release for you is just getting the latest code in the master
|
|
branch out, without caring about bumping version numbers or anything, then
|
|
GitHub Flow is a good fit for you, and you probably don't need the extras of
|
|
Common-Flow.</p>
|
|
<p>However if your deployments/releases have specific version numbers, then
|
|
Common-Flow gives you a simple set of rules of how to create and manage
|
|
releases, on top of what GitHub Flow already does.</p></div> </div> </div> </div><div class="border-b border-gray-200 dark:border-neutral-800" data-faq-item> <button class="flex justify-between items-center w-full py-6 text-left
|
|
font-display text-lg font-semibold cursor-pointer
|
|
transition-colors
|
|
text-gray-950 dark:text-neutral-50
|
|
hover:text-sky-600" aria-expanded="false" data-faq-trigger> <span class="pr-4">What does "descriptive name" mean for change branches?</span> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-5 h-5 flex-shrink-0 transition-transform duration-200" data-faq-icon="true" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out" data-faq-content> <div class="overflow-hidden"> <div class="pb-6 text-gray-600 dark:text-neutral-400 prose-spec"><p>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:</p>
|
|
<ul>
|
|
<li>add-2fa-support</li>
|
|
<li>fix-login-issue</li>
|
|
<li>remove-sort-by-middle-name-functionality</li>
|
|
<li>update-font-awesome</li>
|
|
<li>change-search-behavior</li>
|
|
<li>improve-pagination-performance</li>
|
|
<li>tweak-footer-style</li>
|
|
</ul>
|
|
<p>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.</p>
|
|
<p>You can also add ticket numbers to the branch name if your team/org has that as
|
|
part of it's 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.</p></div> </div> </div> </div><div class="border-b border-gray-200 dark:border-neutral-800" data-faq-item> <button class="flex justify-between items-center w-full py-6 text-left
|
|
font-display text-lg font-semibold cursor-pointer
|
|
transition-colors
|
|
text-gray-950 dark:text-neutral-50
|
|
hover:text-sky-600" aria-expanded="false" data-faq-trigger> <span class="pr-4">How do we release an emergency hotfix when the master branch is broken?</span> <svg width="1em" height="1em" viewBox="0 0 24 24" class="w-5 h-5 flex-shrink-0 transition-transform duration-200" data-faq-icon="true" data-icon="heroicons:chevron-down"> <use href="#ai:heroicons:chevron-down"></use> </svg> </button> <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out" data-faq-content> <div class="overflow-hidden"> <div class="pb-6 text-gray-600 dark:text-neutral-400 prose-spec"><p>This should ideally never happen, however if it does you can do one of the
|
|
following:</p>
|
|
<ul>
|
|
<li>Review why the master branch is broken and revert the changes that caused the
|
|
issues. Then apply the hotfix and release.</li>
|
|
<li>Or use a short-term release branch created from the latest release tag instead
|
|
of the master branch. Apply the hotfix to the release branch, create a release
|
|
tag on the release branch, and then merge it back into master.</li>
|
|
</ul>
|
|
<p>In this situation, it is recommended you try to revert the offending changes
|
|
that's preventing a new release from master. But if that proves to be a
|
|
complicated task and you're short on time, a short-term release branch gives you
|
|
a instant fix to the situation at hand, and let's you resolve the issues with
|
|
the master branch when you have more time on your hands.</p></div> </div> </div> </div> </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> |