<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Git Advanced on Software Engineering Learning Paths</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/</link><description>Recent content in Git Advanced on Software Engineering Learning Paths</description><generator>Hugo</generator><language>en</language><atom:link href="https://kyngo.github.io/learning-paths/paths/git-advanced/index.xml" rel="self" type="application/rss+xml"/><item><title>Git Internals</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/01-internals/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/01-internals/</guid><description>&lt;h1 id="git-internals"&gt;Git Internals&lt;a class="anchor" href="#git-internals"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Understanding how Git stores and manages data transforms you from someone who memorises commands into someone who truly understands the tool. Git is fundamentally a &lt;strong&gt;content-addressable filesystem&lt;/strong&gt; with a version control interface built on top.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="the-git-directory-anatomy"&gt;The .git Directory Anatomy&lt;a class="anchor" href="#the-git-directory-anatomy"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you run &lt;code&gt;git init&lt;/code&gt;, Git creates the &lt;code&gt;.git&lt;/code&gt; directory — the entire repository lives here:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.git/
├── HEAD # Points to the current branch ref
├── config # Repository-specific configuration
├── description # Used by GitWeb (rarely relevant)
├── hooks/ # Client-side and server-side hook scripts
├── info/ # Global exclude patterns
├── objects/ # All content (blobs, trees, commits, tags)
│ ├── info/
│ └── pack/ # Packed objects for efficiency
├── refs/ # Pointers to commit objects
│ ├── heads/ # Branch tips
│ ├── tags/ # Tag references
│ └── remotes/ # Remote-tracking branches
├── index # Staging area (binary file)
└── logs/ # Reflog history&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Component&lt;/th&gt;
					&lt;th&gt;Purpose&lt;/th&gt;
					&lt;th&gt;Human-readable?&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;HEAD&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Current branch pointer&lt;/td&gt;
					&lt;td&gt;Yes — contains &lt;code&gt;ref: refs/heads/main&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;objects/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Content store (all versions of all files)&lt;/td&gt;
					&lt;td&gt;No — compressed binary&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;refs/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Named pointers to commits&lt;/td&gt;
					&lt;td&gt;Yes — contains SHA-1 hashes&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;index&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Staging area snapshot&lt;/td&gt;
					&lt;td&gt;No — binary format&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;logs/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;History of ref changes&lt;/td&gt;
					&lt;td&gt;Yes — one entry per line&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="the-four-object-types"&gt;The Four Object Types&lt;a class="anchor" href="#the-four-object-types"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Git stores everything as one of four object types, each identified by a 40-character SHA-1 hash:&lt;/p&gt;</description></item><item><title>Rebase Workflows</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/02-rebase-workflows/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/02-rebase-workflows/</guid><description>&lt;h1 id="rebase-workflows"&gt;Rebase Workflows&lt;a class="anchor" href="#rebase-workflows"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Rebase is Git&amp;rsquo;s most powerful history-editing tool. It replays commits onto a new base, creating a linear history that&amp;rsquo;s easier to read and bisect. But with great power comes great responsibility — rewriting shared history can cause serious collaboration problems.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="rebase-vs-merge"&gt;Rebase vs Merge&lt;a class="anchor" href="#rebase-vs-merge"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Both integrate changes from one branch into another, but they produce different histories:&lt;/p&gt;
&lt;pre class="mermaid"&gt;gitGraph
 commit id: &amp;#34;A&amp;#34;
 commit id: &amp;#34;B&amp;#34;
 branch feature
 commit id: &amp;#34;C&amp;#34;
 commit id: &amp;#34;D&amp;#34;
 checkout main
 commit id: &amp;#34;E&amp;#34;
 checkout feature
 commit id: &amp;#34;F&amp;#34;&lt;/pre&gt;&lt;h3 id="after-merge-git-merge-feature"&gt;After Merge (&lt;code&gt;git merge feature&lt;/code&gt;)&lt;a class="anchor" href="#after-merge-git-merge-feature"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="mermaid"&gt;gitGraph
 commit id: &amp;#34;A&amp;#34;
 commit id: &amp;#34;B&amp;#34;
 branch feature
 commit id: &amp;#34;C&amp;#34;
 commit id: &amp;#34;D&amp;#34;
 checkout main
 commit id: &amp;#34;E&amp;#34;
 checkout feature
 commit id: &amp;#34;F&amp;#34;
 checkout main
 merge feature id: &amp;#34;M&amp;#34;&lt;/pre&gt;&lt;h3 id="after-rebase-git-checkout-feature--git-rebase-main"&gt;After Rebase (&lt;code&gt;git checkout feature &amp;amp;&amp;amp; git rebase main&lt;/code&gt;)&lt;a class="anchor" href="#after-rebase-git-checkout-feature--git-rebase-main"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="mermaid"&gt;gitGraph
 commit id: &amp;#34;A&amp;#34;
 commit id: &amp;#34;B&amp;#34;
 commit id: &amp;#34;E&amp;#34;
 commit id: &amp;#34;C&amp;#39;&amp;#34;
 commit id: &amp;#34;D&amp;#39;&amp;#34;
 commit id: &amp;#34;F&amp;#39;&amp;#34;&lt;/pre&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Aspect&lt;/th&gt;
					&lt;th&gt;Merge&lt;/th&gt;
					&lt;th&gt;Rebase&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;History shape&lt;/td&gt;
					&lt;td&gt;Non-linear (preserves branches)&lt;/td&gt;
					&lt;td&gt;Linear (straight line)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Original commits&lt;/td&gt;
					&lt;td&gt;Preserved exactly&lt;/td&gt;
					&lt;td&gt;Replaced with new commits (new SHAs)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Merge commits&lt;/td&gt;
					&lt;td&gt;Creates one&lt;/td&gt;
					&lt;td&gt;None&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Conflict resolution&lt;/td&gt;
					&lt;td&gt;Once (in merge commit)&lt;/td&gt;
					&lt;td&gt;Per-commit (during replay)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Traceability&lt;/td&gt;
					&lt;td&gt;Full branch history visible&lt;/td&gt;
					&lt;td&gt;Branch topology lost&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Safety for shared branches&lt;/td&gt;
					&lt;td&gt;Safe&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Dangerous&lt;/strong&gt; — rewrites history&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="the-golden-rule-of-rebase"&gt;The Golden Rule of Rebase&lt;a class="anchor" href="#the-golden-rule-of-rebase"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Never rebase commits that have been pushed to a shared branch.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Reflog &amp; Recovery</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/03-reflog-recovery/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/03-reflog-recovery/</guid><description>&lt;h1 id="reflog--recovery"&gt;Reflog &amp;amp; Recovery&lt;a class="anchor" href="#reflog--recovery"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The reflog is Git&amp;rsquo;s safety net — a local log of every position your &lt;code&gt;HEAD&lt;/code&gt; and branch refs have pointed to. Even after a destructive operation, the reflog usually holds the key to recovery.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="what-the-reflog-tracks"&gt;What the Reflog Tracks&lt;a class="anchor" href="#what-the-reflog-tracks"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The reflog records every time a ref (HEAD, branch, etc.) changes value. Each entry contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;old and new SHA&lt;/strong&gt; of the ref&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;timestamp&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;action&lt;/strong&gt; that caused the change&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;message&lt;/strong&gt; describing what happened&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# View HEAD reflog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reflog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# or equivalently:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reflog show HEAD
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# View a specific branch&amp;#39;s reflog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reflog show main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# View with timestamps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reflog --date&lt;span class="o"&gt;=&lt;/span&gt;iso&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example output:&lt;/p&gt;</description></item><item><title>Advanced Branching</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/04-advanced-branching/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/04-advanced-branching/</guid><description>&lt;h1 id="advanced-branching"&gt;Advanced Branching&lt;a class="anchor" href="#advanced-branching"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Beyond basic branching, Git offers powerful tools for parallel development, automated debugging, selective commit application, and efficient handling of large repositories.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="worktrees--parallel-development"&gt;Worktrees — Parallel Development&lt;a class="anchor" href="#worktrees--parallel-development"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A worktree is an additional working directory linked to the same repository. Instead of stashing or committing WIP to switch context, you open another worktree:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create a new worktree for a branch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git worktree add ../project-hotfix hotfix/urgent-fix
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create a worktree with a new branch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git worktree add -b feature/new-thing ../project-feature main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# List all worktrees&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git worktree list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /home/user/project abc1234 [main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /home/user/project-hotfix def5678 [hotfix/urgent-fix]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /home/user/project-feature 9ab0123 [feature/new-thing]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Remove a worktree (after you&amp;#39;re done)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git worktree remove ../project-hotfix
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Prune stale worktree references&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git worktree prune&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="worktree-rules"&gt;Worktree Rules&lt;a class="anchor" href="#worktree-rules"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Rule&lt;/th&gt;
					&lt;th&gt;Reason&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Each worktree must be on a different branch&lt;/td&gt;
					&lt;td&gt;Git can&amp;rsquo;t have two worktrees on the same ref&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;All worktrees share the same &lt;code&gt;.git&lt;/code&gt; objects&lt;/td&gt;
					&lt;td&gt;Storage efficient — no duplicate history&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Commits in one worktree are immediately visible in others&lt;/td&gt;
					&lt;td&gt;Single object store&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Don&amp;rsquo;t &lt;code&gt;git checkout&lt;/code&gt; into a branch used by another worktree&lt;/td&gt;
					&lt;td&gt;Fails with an error&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="when-to-use-worktrees"&gt;When to Use Worktrees&lt;a class="anchor" href="#when-to-use-worktrees"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Reviewing a PR while your current branch has uncommitted work&lt;/li&gt;
&lt;li&gt;Running a long build on one branch while developing on another&lt;/li&gt;
&lt;li&gt;Comparing behaviour between two branches simultaneously&lt;/li&gt;
&lt;li&gt;Hotfixes that can&amp;rsquo;t wait for your current work to finish&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="bisect--binary-search-for-bugs"&gt;Bisect — Binary Search for Bugs&lt;a class="anchor" href="#bisect--binary-search-for-bugs"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;git bisect&lt;/code&gt; performs a binary search through history to find which commit introduced a bug:&lt;/p&gt;</description></item><item><title>Submodules &amp; Subtrees</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/05-submodules-subtrees/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/05-submodules-subtrees/</guid><description>&lt;h1 id="submodules--subtrees"&gt;Submodules &amp;amp; Subtrees&lt;a class="anchor" href="#submodules--subtrees"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When a project depends on code from another repository, Git offers two main strategies: &lt;strong&gt;submodules&lt;/strong&gt; (linked pointer to an external repo) and &lt;strong&gt;subtrees&lt;/strong&gt; (merged copy of an external repo). Each has distinct trade-offs for dependency management, monorepo architecture, and team workflows.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="submodules"&gt;Submodules&lt;a class="anchor" href="#submodules"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A submodule is a reference to a specific commit in another repository. The parent repo stores only the URL and commit SHA — not the actual files.&lt;/p&gt;</description></item><item><title>Hooks &amp; Automation</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/06-hooks-automation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/06-hooks-automation/</guid><description>&lt;h1 id="hooks--automation"&gt;Hooks &amp;amp; Automation&lt;a class="anchor" href="#hooks--automation"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Git hooks are scripts that run automatically at specific points in the Git workflow. They enable quality gates, enforced conventions, and automated workflows — all without requiring developers to remember manual steps.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="how-hooks-work"&gt;How Hooks Work&lt;a class="anchor" href="#how-hooks-work"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hooks live in &lt;code&gt;.git/hooks/&lt;/code&gt; and execute at predefined trigger points. They are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Executable scripts&lt;/strong&gt; (any language — bash, Python, Node.js, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Named after their trigger&lt;/strong&gt; (e.g., &lt;code&gt;pre-commit&lt;/code&gt;, &lt;code&gt;commit-msg&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local by default&lt;/strong&gt; — not committed to the repo (solved by frameworks like Husky)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blocking&lt;/strong&gt; — a non-zero exit code aborts the operation (for pre-* hooks)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# List available hook samples&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls .git/hooks/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# applypatch-msg.sample pre-commit.sample prepare-commit-msg.sample ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Enable a hook by removing .sample and making executable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x .git/hooks/pre-commit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="client-side-hooks"&gt;Client-Side Hooks&lt;a class="anchor" href="#client-side-hooks"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="hook-execution-timeline"&gt;Hook Execution Timeline&lt;a class="anchor" href="#hook-execution-timeline"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="mermaid"&gt;graph LR
 A[git commit] --&amp;gt; B[pre-commit]
 B --&amp;gt; C[prepare-commit-msg]
 C --&amp;gt; D[commit-msg]
 D --&amp;gt; E[post-commit]
 
 F[git push] --&amp;gt; G[pre-push]
 G --&amp;gt; H[post-push]
 
 style B fill:#e3f2fd
 style C fill:#e3f2fd
 style D fill:#e3f2fd
 style G fill:#e3f2fd&lt;/pre&gt;&lt;h3 id="pre-commit"&gt;pre-commit&lt;a class="anchor" href="#pre-commit"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Runs before the commit is created. Use for linting, formatting, and fast checks.&lt;/p&gt;</description></item><item><title>Collaboration at Scale</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/07-collaboration-at-scale/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/07-collaboration-at-scale/</guid><description>&lt;h1 id="collaboration-at-scale"&gt;Collaboration at Scale&lt;a class="anchor" href="#collaboration-at-scale"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When teams grow beyond a handful of developers, Git workflows become critical infrastructure. The right workflow reduces merge conflicts, accelerates delivery, and preserves code quality. The wrong one creates bottlenecks and frustration.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="git-workflows-compared"&gt;Git Workflows Compared&lt;a class="anchor" href="#git-workflows-compared"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="gitflow"&gt;GitFlow&lt;a class="anchor" href="#gitflow"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;main ─────────●─────────────────●──────────── (releases)
 ╲ ╱
develop ────●───●───●───●───●─●──────────── (integration)
 ╲ ╱ ╲ ╱
feature/x ────●───● ╲ ╱
 feature/y ──●&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Aspect&lt;/th&gt;
					&lt;th&gt;Details&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Branches&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;main, develop, feature/&lt;em&gt;, release/&lt;/em&gt;, hotfix/*&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Merge style&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Merge commits (no fast-forward)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Release cycle&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Planned releases with release branches&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Packaged software, mobile apps, versioned products&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Drawback&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Complex, long-lived branches, integration pain&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="github-flow"&gt;GitHub Flow&lt;a class="anchor" href="#github-flow"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;main ─────●──────●──────●──────●──────── (always deployable)
 ╲ ╱ ╲ ╱ ╲ ╱
feature ────●──● ●──● ●──●
 PR+CI PR+CI PR+CI&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Aspect&lt;/th&gt;
					&lt;th&gt;Details&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Branches&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;main + short-lived feature branches&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Merge style&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Squash or merge commit via Pull Request&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Release cycle&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Deploy on every merge to main&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;SaaS, web applications, continuous deployment&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Drawback&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Requires robust CI/CD and feature flags&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="trunk-based-development"&gt;Trunk-Based Development&lt;a class="anchor" href="#trunk-based-development"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;main ──●──●──●──●──●──●──●──●──●──── (everyone commits here)
 │ │ │ │
 small small small
 commits commits commits&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Aspect&lt;/th&gt;
					&lt;th&gt;Details&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Branches&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;main only (or very short-lived branches &amp;lt; 1 day)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Merge style&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Direct commits or same-day PRs&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Release cycle&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Continuous; feature flags gate incomplete work&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;High-performing teams, CI/CD maturity, Google/Meta-style&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Drawback&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Requires excellent test coverage and feature flags&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="ship--show--ask"&gt;Ship / Show / Ask&lt;a class="anchor" href="#ship--show--ask"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A nuanced model that categorizes changes by risk:&lt;/p&gt;</description></item><item><title>Troubleshooting</title><link>https://kyngo.github.io/learning-paths/paths/git-advanced/08-troubleshooting/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kyngo.github.io/learning-paths/paths/git-advanced/08-troubleshooting/</guid><description>&lt;h1 id="git-troubleshooting"&gt;Git Troubleshooting&lt;a class="anchor" href="#git-troubleshooting"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Every Git user eventually encounters situations that seem catastrophic — lost commits, corrupted history, massive repositories, impossible merge conflicts. This chapter provides systematic solutions for the most common problems.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="common-problems-and-solutions"&gt;Common Problems and Solutions&lt;a class="anchor" href="#common-problems-and-solutions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="undo-last-commit-keep-changes"&gt;Undo Last Commit (Keep Changes)&lt;a class="anchor" href="#undo-last-commit-keep-changes"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Undo commit but keep changes staged&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reset --soft HEAD~1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Undo commit and unstage changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reset --mixed HEAD~1 &lt;span class="c1"&gt;# default behavior of git reset HEAD~1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Undo commit and DISCARD changes (destructive!)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reset --hard HEAD~1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="recover-deleted-branch"&gt;Recover Deleted Branch&lt;a class="anchor" href="#recover-deleted-branch"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Find the commit the branch pointed to&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reflog &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;#34;branch-name&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reflog --all &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;#34;branch-name&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Recreate the branch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git branch recovered-branch abc1234&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="accidentally-committed-to-wrong-branch"&gt;Accidentally Committed to Wrong Branch&lt;a class="anchor" href="#accidentally-committed-to-wrong-branch"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Move last commit to correct branch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git branch correct-branch &lt;span class="c1"&gt;# create branch at current commit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reset --hard HEAD~1 &lt;span class="c1"&gt;# remove commit from current branch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout correct-branch &lt;span class="c1"&gt;# switch to correct branch&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="amend-last-commit"&gt;Amend Last Commit&lt;a class="anchor" href="#amend-last-commit"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Change message only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit --amend -m &lt;span class="s2"&gt;&amp;#34;corrected message&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Add forgotten files to last commit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add forgotten-file.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit --amend --no-edit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Never amend commits that have been pushed to a shared branch.&lt;/p&gt;</description></item></channel></rss>