Skip to content
Published on

Git Mastery: Advanced Workflows Every Developer Needs — From Junior to Senior

Authors

Introduction

Git is every developer's daily companion. Yet most developers only use git add, git commit, git push and barely tap into 10% of what Git offers. This guide covers everything from Git internals to advanced workflows that you can apply immediately in your day-to-day work, whether you are a junior or a senior engineer.

Have you ever received code review feedback saying "please clean up this commit history"? Have you ever panicked when a merge conflict appeared? By the end of this article, you will handle those situations with confidence.


1. Understanding Git Internals — Objects, DAG, and the .git Directory

To truly master Git, you need to understand how it works under the hood. Git is not just a version control tool; it is a sophisticated system built on top of a content-addressable filesystem.

1.1 The Four Git Objects

There are four core object types inside Git.

Blob (Binary Large Object): Stores file contents. It does not include the filename or path — only the raw content.

# Check the hash of file contents
echo "Hello, Git!" | git hash-object --stdin
# Result: e.g. af5626b4a114abcb82d63db7c8082c3c4756e51b

# Verify the object type
git cat-file -t af5626b
# Result: blob

# View the content
git cat-file -p af5626b
# Result: Hello, Git!

Tree: Represents a directory structure. It references blobs and other trees to build a snapshot of the filesystem.

# Inspect the tree of the latest commit
git cat-file -p HEAD^{tree}
# 100644 blob a906cb2a4a904a15...    README.md
# 040000 tree 99f1a6d12cb4b6f1...    src
# 100644 blob 47c6340d6459e058...    package.json

Commit: A snapshot at a point in time. It points to a tree object and includes the author, commit message, and parent commit references.

# Inspect a commit's internals
git cat-file -p HEAD
# tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
# parent 8bd3ad5e1234567890abcdef1234567890abcdef
# author John Doe <john@example.com> 1711100000 +0900
# committer John Doe <john@example.com> 1711100000 +0900
#
# feat: add user authentication

Tag: A named reference to a specific commit. Used for release version management.

# Create an annotated tag
git tag -a v1.0.0 -m "Release version 1.0.0"

# Inspect the tag object
git cat-file -p v1.0.0

1.2 SHA-1 Hashing and Content Addressing

Git identifies every object by its SHA-1 hash. Identical content always produces the same hash, which naturally prevents duplicate storage.

# Same content = same hash
echo "same content" | git hash-object --stdin
echo "same content" | git hash-object --stdin
# Both results are identical

The implication is significant: even if 100 branches contain the same file, Git stores it only once.

1.3 DAG (Directed Acyclic Graph) — The Commit Graph

Git's commit history forms a DAG (Directed Acyclic Graph). Each commit points to its parent(s), and no cycles exist.

    A---B---C---D  (main)
         \
          E---F---G  (feature)
               \
                H---I  (hotfix)

Understanding this structure makes merge, rebase, and cherry-pick operations intuitive.

# View the log as a graph
git log --oneline --graph --all --decorate

# Cleaner output
git log --oneline --graph --all --format="%h %s (%ar)"

1.4 Anatomy of the .git Directory

.git/
  HEAD          # Pointer to the current branch
  config        # Repository-specific settings
  refs/
    heads/      # Local branches (each file = a commit hash)
    tags/       # Tags
    remotes/    # Remote branch tracking
  objects/      # All Git objects (blob, tree, commit, tag)
    pack/       # Compressed object pack files
  hooks/        # Git hook scripts
  index         # Staging area (binary)
# Check what HEAD points to
cat .git/HEAD
# ref: refs/heads/main

# See the commit that main points to
cat .git/refs/heads/main
# a1b2c3d4e5f6...

# Check object store size
git count-objects -vH

2. Branching Strategies — Choosing the Right Workflow for Your Team

2.1 Git Flow

A traditional branching model proposed by Vincent Driessen in 2010.

main ─────────────────────────────── (production)
  └── develop ────────────────────── (development integration)
        │        │
        │   feature/login ────────── (feature development)
        └── release/1.0 ──────────── (release preparation)
              └── hotfix/bug-123 ──── (emergency fix)

Pros: Clear release management, production stability guaranteed Cons: Too many branches, frequent merge conflicts, poor fit with CI/CD

# Initialize Git Flow (git-flow extension)
git flow init

# Start feature development
git flow feature start user-auth

# Complete feature development
git flow feature finish user-auth

2.2 GitHub Flow

A simple branching model used by GitHub.

main ────────────────────────────────
  │              │
  └── feature ───┘ (PR + merge)

Rule: main is always deployable. Work on feature branches, merge via PR.

# 1. Create a branch
git checkout -b feature/add-search

# 2. Work and commit
git add .
git commit -m "feat: add search functionality"

# 3. Push
git push -u origin feature/add-search

# 4. Create PR (GitHub CLI)
gh pr create --title "Add search functionality" --body "..."

# 5. Merge after review
gh pr merge --squash

2.3 Trunk-Based Development

Used by large-scale teams at Google, Meta, and others. All developers integrate frequently into main (the trunk), either directly or through very short-lived branches.

main ──A──B──C──D──E──F──G──H──I──
            \─/     \─/
         (1-2 days)(1-2 days)

Core principles:

  • Branch lifespan is at most 1-2 days
  • Integrate into main multiple times per day
  • Feature flags manage incomplete features
  • A robust CI/CD pipeline is mandatory

2.4 Strategy Comparison

AspectGit FlowGitHub FlowTrunk-Based
ComplexityHighLowMedium
Branch lifespanLong (weeks-months)Medium (days-weeks)Short (hours-days)
Release cadenceScheduled releasesOn-demand deploysContinuous deployment
Team size10+ people2-15 peopleAny size
CI/CD dependencyLowMediumHigh
Recommended forMobile apps, packagesSaaS, web appsLarge organizations

2.5 Branch Naming Conventions

# Feature development
feature/JIRA-123-add-login
feature/user-profile-page

# Bug fixes
bugfix/JIRA-456-fix-null-pointer
fix/login-redirect-loop

# Hotfixes
hotfix/security-patch-xss
hotfix/v1.2.1

# Releases
release/1.0.0
release/2026-q1

# Experimental / maintenance
experiment/new-search-algo
chore/update-dependencies

3. The Rebase Master Class

3.1 Rebase vs Merge — When to Use Which

Merge: Preserves the history of both branches while combining them.

git checkout main
git merge feature/login
# A merge commit is created
    A---B---C---D---M  (main, merge commit M)
         \         /
          E---F---G  (feature)

Rebase: Replays commits on top of a different base.

git checkout feature/login
git rebase main
# Feature commits are replayed on top of main
    A---B---C---D  (main)
                 \
                  E'---F'---G'  (feature, replayed)

3.2 Interactive Rebase — The Complete Guide

# Interactively edit the last 5 commits
git rebase -i HEAD~5

Your editor will open with something like this:

pick a1b2c3d feat: add user model
pick d4e5f6g fix: typo in user model
pick h7i8j9k feat: add user controller
pick l0m1n2o WIP: debugging
pick p3q4r5s feat: add user routes

Available commands:

CommandShorthandDescription
pickpUse the commit as-is
rewordrChange the commit message only
editeModify the commit (can change files)
squashsMerge with previous commit, edit message
fixupfMerge with previous commit, discard message
dropdRemove the commit

Real-world example — cleaning up messy history:

pick a1b2c3d feat: add user model
fixup d4e5f6g fix: typo in user model
pick h7i8j9k feat: add user controller
drop l0m1n2o WIP: debugging
pick p3q4r5s feat: add user routes

Result: 5 commits become 3 clean commits.

3.3 The Autosquash Workflow

Using the fixup! prefix allows automatic cleanup.

# Original commit
git commit -m "feat: add user model"

# Later, when a fix is needed
git commit --fixup HEAD
# Or target a specific commit
git commit --fixup a1b2c3d

# Automatic cleanup
git rebase -i --autosquash main

3.4 The Golden Rule of Rebase

Never rebase shared branches (main, develop). Rebase changes commit hashes, which causes conflicts with everyone else's local repositories.

# Safe rebase (personal feature branch)
git checkout feature/my-task
git rebase main

# Dangerous rebase (never do this!)
git checkout main
git rebase feature/something  # Forbidden!

4. 20 Real-World Scenarios — Problem-Solving Recipes

Scenario 1: Wrong Commit Message

# Fix the most recent commit message (not yet pushed)
git commit --amend -m "feat: add user authentication"

# Open editor to edit message
git commit --amend

Scenario 2: Committed to the Wrong Branch

# Situation: committed to feature branch instead of main
# Method 1: cherry-pick
git checkout main
git cherry-pick abc1234
git checkout feature/wrong-branch
git reset --hard HEAD~1

# Method 2: stash
git reset --soft HEAD~1
git stash
git checkout correct-branch
git stash pop
git commit -m "correct commit message"

Scenario 3: Undoing After Push — revert vs reset

# Safe method: revert (creates a new commit, preserves history)
git revert abc1234
git push

# Dangerous method: reset + force push (rewrites history)
git reset --hard HEAD~1
git push --force-with-lease
# force-with-lease protects against overwriting others' commits

revert vs reset comparison:

Aspectrevertreset
HistoryPreserved (new commit added)Rewritten (commits removed)
SafetySafeDangerous
Shared branchesOK to useDo not use
UndoingCan revert the revertRecovery via reflog only

Scenario 4: Merge Conflict Resolution Strategies

# When a conflict occurs
git merge feature/login
# CONFLICT (content): Merge conflict in src/auth.js

# Check conflicted files
git status

# Conflict marker structure
# <<<<<<< HEAD
# Code from current branch
# =======
# Code from the merging branch
# >>>>>>> feature/login

# After manual resolution
git add src/auth.js
git commit -m "resolve merge conflict in auth module"

Strategies for minimizing merge conflicts:

# 1. Sync with main frequently
git fetch origin
git rebase origin/main

# 2. Commit and merge in small increments
# 3. Establish clear file ownership (CODEOWNERS)
# 4. Configure merge tools
git config --global merge.tool vimdiff
git mergetool

Scenario 5: Bug Tracking with git bisect

# Start bisect
git bisect start

# Mark current state as bad (has bug)
git bisect bad

# Mark a known good commit
git bisect good v1.0.0

# Git checks out a middle commit — test and decide
git bisect good  # or git bisect bad

# Repeat until the exact bad commit is found
# Result: abc1234 is the first bad commit

# End bisect
git bisect reset

Automated bisect with test scripts:

# Test script failure = bad, success = good
git bisect start HEAD v1.0.0
git bisect run npm test
# Automatically finds the bug-introducing commit!

Scenario 6: Accidentally Committed a Large File

# Method 1: git-filter-repo (recommended)
pip install git-filter-repo
git filter-repo --path large-file.zip --invert-paths

# Method 2: BFG Repo-Cleaner
java -jar bfg.jar --delete-files large-file.zip
git reflog expire --expire=now --all
git gc --prune=now --aggressive

# Prevention: .gitignore
echo "*.zip" >> .gitignore
echo "*.tar.gz" >> .gitignore
echo "node_modules/" >> .gitignore

Scenario 7: Staging Parts of a File — git add -p

# Selectively stage changes by hunk
git add -p src/utils.js

# For each hunk:
# y - stage this hunk
# n - skip this hunk
# s - split into smaller hunks
# e - manually edit
# q - quit

Scenario 8: Urgent Hotfix While Working — stash + worktree

# Method 1: stash
git stash push -m "WIP: feature work"
git checkout main
git checkout -b hotfix/critical-bug
# Work on the hotfix...
git checkout feature/my-work
git stash pop

# Method 2: worktree (the better approach!)
git worktree add ../hotfix-workspace main
cd ../hotfix-workspace
git checkout -b hotfix/critical-bug
# Work on the hotfix...
cd ../main-workspace
git worktree remove ../hotfix-workspace

Scenario 9: Squashing Multiple Commits into One

# Method 1: interactive rebase
git rebase -i HEAD~4
# Change first to pick, rest to squash

# Method 2: soft reset
git reset --soft HEAD~4
git commit -m "feat: complete user authentication"

# Method 3: merge --squash
git checkout main
git merge --squash feature/user-auth
git commit -m "feat: add user authentication system"

Scenario 10: Submodule Management

# Add a submodule
git submodule add https://github.com/org/shared-lib.git libs/shared

# Clone with submodules
git clone --recurse-submodules https://github.com/org/project.git

# Update submodules
git submodule update --remote --merge

# Run command across all submodules
git submodule foreach 'git checkout main && git pull'

Scenario 11: Recover a Deleted Branch

# Find the last commit of the deleted branch in reflog
git reflog
# abc1234 HEAD@{5}: checkout: moving from deleted-branch to main

# Recover the branch
git checkout -b recovered-branch abc1234

Scenario 12: Checkout a Specific File from Another Branch

# Get a specific file from the main branch
git checkout main -- src/config.js

# Get a file from a specific commit
git checkout abc1234 -- src/config.js

Scenario 13: Changing Commit Dates

# Change the last commit date to now
GIT_COMMITTER_DATE="$(date)" git commit --amend --date="$(date)"

# Set a specific date (during rebase)
GIT_COMMITTER_DATE="2026-03-22T10:00:00" git commit --amend --date="2026-03-22T10:00:00"

Scenario 14: Code Tracking with git blame

# See who last modified each line
git blame src/auth.js

# Check a specific line range
git blame -L 10,20 src/auth.js

# Ignore whitespace changes
git blame -w src/auth.js

# Track code movement
git blame -M src/auth.js
git blame -C src/auth.js

Scenario 15: Advanced git log

# File change history (follows renames)
git log --follow -p -- src/auth.js

# Find commits that added/removed a specific string (pickaxe)
git log -S "API_KEY" --oneline

# Filter by author
git log --author="John" --oneline --since="2026-01-01"

# Include statistics
git log --stat --oneline -10

# Diff between commits
git log -p --oneline -3

Scenario 16: Managing Multiple Remotes

# Add multiple remotes
git remote add upstream https://github.com/original/repo.git
git remote add deploy git@deploy-server:app.git

# Sync with upstream (forked project)
git fetch upstream
git rebase upstream/main

# Clean up remote branches
git remote prune origin
git fetch --prune

Scenario 17: Release Management with Tags

# Create an annotated tag
git tag -a v2.0.0 -m "Release 2.0.0: new payment system"

# Tag a specific commit
git tag -a v1.5.0 abc1234 -m "Hotfix release"

# Push tags
git push origin v2.0.0
git push origin --tags

# Delete a tag
git tag -d v2.0.0-beta
git push origin --delete v2.0.0-beta

Scenario 18: Automation with Git Hooks

# .husky/pre-commit
#!/bin/sh
npx lint-staged

# .husky/commit-msg
#!/bin/sh
npx commitlint --edit "$1"

# .husky/pre-push
#!/bin/sh
npm test

Scenario 19: Creating and Applying Patches

# Create a patch
git diff > my-changes.patch
git format-patch -3  # Create patch files from the last 3 commits

# Apply a patch
git apply my-changes.patch
git am *.patch  # Apply patches created by format-patch

Scenario 20: git reflog — The Last Resort

# View the reflog (HEAD movement history)
git reflog

# Recover after an accidental reset --hard
git reflog
# abc1234 HEAD@{2}: commit: important work
git reset --hard abc1234

# Recover an accidentally dropped stash
git fsck --unreachable | grep commit
git stash apply abc1234

5. Conventional Commits + Semantic Versioning

5.1 Conventional Commits Format

type(scope): description

[optional body]

[optional footer(s)]

Type reference:

TypeDescriptionExample
featNew featurefeat: add login page
fixBug fixfix: resolve null pointer in auth
docsDocumentationdocs: update API documentation
styleCode style (formatting, etc.)style: fix indentation
refactorRefactoringrefactor: extract auth middleware
perfPerformance improvementperf: optimize database queries
testAdding/modifying teststest: add unit tests for auth
buildBuild system changesbuild: update webpack config
ciCI configurationci: add GitHub Actions workflow
choreMiscellaneous taskschore: update dependencies

Breaking Change notation:

feat(api)!: change authentication endpoint

BREAKING CHANGE: /auth/login is now /api/v2/auth/login

5.2 Commitlint + Husky Setup

# Install packages
npm install -D @commitlint/cli @commitlint/config-conventional husky

# Configure commitlint
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

# Initialize Husky
npx husky init
echo 'npx commitlint --edit "$1"' > .husky/commit-msg

5.3 Automated Changelog Generation

# Install conventional-changelog
npm install -D conventional-changelog-cli

# Generate CHANGELOG.md
npx conventional-changelog -p angular -i CHANGELOG.md -s
{
  "scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
    "release": "standard-version"
  }
}

5.4 Semantic Release — Full Automation

npm install -D semantic-release
{
  "release": {
    "branches": ["main"],
    "plugins": [
      "@semantic-release/commit-analyzer",
      "@semantic-release/release-notes-generator",
      "@semantic-release/changelog",
      "@semantic-release/npm",
      "@semantic-release/github",
      "@semantic-release/git"
    ]
  }
}

Versions are determined automatically based on commit types:

  • fix: -> PATCH (1.0.0 -> 1.0.1)
  • feat: -> MINOR (1.0.0 -> 1.1.0)
  • BREAKING CHANGE -> MAJOR (1.0.0 -> 2.0.0)

6. GitHub Actions CI/CD

6.1 Basic Workflow

name: CI Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]

    steps:
      - uses: actions/checkout@v4

      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - run: npm ci
      - run: npm run lint
      - run: npm test
      - run: npm run build

6.2 PR Check Workflow

name: PR Checks

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci

      - name: Lint
        run: npm run lint

      - name: Type Check
        run: npx tsc --noEmit

      - name: Unit Tests
        run: npm test -- --coverage

      - name: Build
        run: npm run build

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          file: ./coverage/lcov.info

6.3 Auto-Labeling

name: Auto Label

on:
  pull_request:
    types: [opened, edited]

jobs:
  label:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/labeler@v5
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
# .github/labeler.yml
frontend:
  - changed-files:
      - any-glob-to-any-file: 'src/components/**'

backend:
  - changed-files:
      - any-glob-to-any-file: 'src/api/**'

documentation:
  - changed-files:
      - any-glob-to-any-file: 'docs/**'

tests:
  - changed-files:
      - any-glob-to-any-file: '**/*.test.*'

6.4 Dependabot Configuration

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: 'npm'
    directory: '/'
    schedule:
      interval: 'weekly'
      day: 'monday'
    open-pull-requests-limit: 10
    labels:
      - 'dependencies'
    groups:
      dev-dependencies:
        dependency-type: 'development'
      production-dependencies:
        dependency-type: 'production'

  - package-ecosystem: 'github-actions'
    directory: '/'
    schedule:
      interval: 'weekly'

6.5 Deployment Workflow

name: Deploy

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci
      - run: npm run build

      - name: Deploy to Production
        run: |
          echo "Deploying version $GITHUB_REF_NAME"
          # Actual deployment commands here

7. Monorepo Strategies

7.1 Monorepo vs Multirepo

AspectMonorepoMultirepo
Code sharingEasyRequires package publishing
Dependency managementUnifiedIndividual
CI/CDComplex (selective builds)Simple (per repository)
Code reviewFull context availableDistributed across repos
Permission managementComplexPer-repository settings
Notable usersGoogle, Meta, MicrosoftNetflix, Spotify

7.2 Tool Comparison — Nx vs Turborepo vs Lerna

# Initialize Nx
npx create-nx-workspace@latest my-workspace

# Initialize Turborepo
npx create-turbo@latest

# Example project structure
my-monorepo/
  apps/
    web/          # Next.js web app
    mobile/       # React Native app
    api/          # Express API server
  packages/
    ui/           # Shared UI components
    utils/        # Shared utilities
    config/       # Shared configuration
  turbo.json
  package.json

7.3 CODEOWNERS Configuration

# .github/CODEOWNERS

# Default reviewers for the entire project
* @team-lead

# Frontend
/apps/web/        @frontend-team
/packages/ui/     @frontend-team

# Backend
/apps/api/        @backend-team
/packages/utils/  @backend-team

# DevOps
/.github/         @devops-team
/docker/          @devops-team
*.yml             @devops-team

7.4 Selective Builds and Tests

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"]
    },
    "lint": {}
  }
}
# Build only changed packages
npx turbo run build --filter=...[HEAD^1]

# Build a specific app
npx turbo run build --filter=web

# Build including dependencies
npx turbo run build --filter=web...

8. Git Performance Optimization

8.1 Shallow Clone

# Clone only the latest commit (useful for CI/CD)
git clone --depth 1 https://github.com/org/repo.git

# Fetch full history later if needed
git fetch --unshallow

8.2 Partial Clone

# Clone without blobs (downloaded on demand)
git clone --filter=blob:none https://github.com/org/repo.git

# Exclude trees as well (fastest clone)
git clone --filter=tree:0 https://github.com/org/repo.git

8.3 Sparse Checkout

# Enable sparse checkout
git sparse-checkout init --cone

# Checkout specific directories only
git sparse-checkout set apps/web packages/ui

# Add another directory
git sparse-checkout add apps/api

# Check current configuration
git sparse-checkout list

8.4 Git LFS (Large File Storage)

# Install and initialize Git LFS
git lfs install

# Track large files
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "assets/videos/*"

# Check .gitattributes
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text

# Check LFS status
git lfs ls-files
git lfs status

8.5 Git Maintenance (Automated Housekeeping)

# Enable automatic maintenance
git maintenance start

# Manual garbage collection
git gc --aggressive

# Check object compression status
git count-objects -vH

# Clean up stale references
git remote prune origin
git reflog expire --expire=30.days

8.6 Scalar — Managing Massive Repositories (Microsoft)

# Register with Scalar (included in Git 2.38+)
scalar register

# Or clone fresh
scalar clone https://github.com/org/massive-repo.git

# Scalar automatically configures:
# - Partial clone
# - Sparse checkout
# - Background maintenance
# - Filesystem monitor
# - Commit graph

9. AI + Git (2025-2026)

9.1 AI Commit Message Generation

# Auto-generate commit messages with Claude Code
claude commit

# GitHub Copilot CLI
gh copilot suggest "write a commit message for these changes"

# aicommits tool
npm install -g aicommits
aicommits

9.2 AI Code Review

GitHub Copilot for Pull Requests automatically analyzes PRs and generates review comments. It identifies potential bugs, performance issues, and security vulnerabilities.

# Enable GitHub Copilot auto-review (in repository settings)
# Settings > Code review > Copilot code review > Enable

9.3 Claude Code and Git Workflows

Claude Code directly assists with Git operations.

# Request a review of staged changes
claude "review my staged changes"

# Write a commit message
claude "write a conventional commit message for my changes"

# Generate a PR description
claude "write a PR description for the current branch"

# Resolve merge conflicts
claude "help me resolve the merge conflicts in src/auth.js"

9.4 Automated PR Descriptions

name: Auto PR Description

on:
  pull_request:
    types: [opened]

jobs:
  describe:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Generate PR description
        uses: anthropics/claude-code-action@v1
        with:
          prompt: |
            Analyze the diff of this PR and generate a clear description
            including what changed, why, and any risks.

Knowledge Check Quiz

Quiz 1: Git Objects

Q: In which object are filenames stored — Blob or Tree?

A: Filenames are stored in the Tree object.

Blobs store only the raw file contents. Filenames and path information are managed by Tree objects. This design means that even if a file is renamed, Git can reuse the same blob as long as the content is unchanged.

# See filenames in a tree object
git cat-file -p HEAD^{tree}
# 100644 blob a906cb...    README.md  <-- Filename lives in the Tree!

Quiz 2: Rebase Safety

Q: Which of the following is a safe rebase operation? (A: rebase feature on main, B: rebase main on feature, C: Both)

A: B is safe.

The golden rule of rebase is "never rebase shared branches." main is a shared branch, so rebasing on main is dangerous. However, feature is a personal branch, so replaying its commits on top of the latest main is safe.

Quiz 3: Reset Modes

Q: What are the differences between the three reset modes (--soft, --mixed, --hard)?

A:

  • --soft: Moves HEAD only. Staging area and working directory are untouched. Use when you just want to undo a commit.
  • --mixed (default): Moves HEAD + resets staging area. Working directory is untouched. Use when you want to undo a commit and unstage.
  • --hard: Moves HEAD + resets staging area + resets working directory. All changes are discarded. (Dangerous!)
# Example: undo the last 3 commits but keep the code
git reset --soft HEAD~3
# Changes are now staged and ready to be recommitted

Quiz 4: Cherry-pick Conflicts

Q: How do you resolve a conflict during cherry-pick?

A: Resolve it the same way as a merge conflict.

git cherry-pick abc1234
# CONFLICT occurs

# 1. Fix the conflicted file
# 2. Stage it
git add resolved-file.js

# 3. Continue cherry-pick
git cherry-pick --continue

# Or abort the cherry-pick
git cherry-pick --abort

Quiz 5: Selective CI in a Monorepo

Q: In a monorepo, if only frontend code changed, should you also run backend tests?

A: It depends on dependencies.

If the frontend does not depend on any backend packages, there is no need to run backend tests. This is the core value of "affected analysis" provided by tools like Nx and Turborepo.

# Nx: test only projects affected by changes
npx nx affected --target=test

# Turborepo: build only changed packages and dependents
npx turbo run build --filter=...[HEAD^1]

However, if a shared package (utils, config, etc.) was modified, you must test all projects that depend on it.


References

Official Documentation

  1. Git Official Docs — The definitive reference
  2. GitHub Docs — GitHub feature guides
  3. Pro Git Book — Free online book

Branching Strategies

  1. Trunk Based Development — Official TBD site
  2. GitHub Flow Guide
  3. A successful Git branching model — Original Git Flow article

CI/CD

  1. GitHub Actions Docs
  2. Semantic Release — Automated versioning
  3. Conventional Commits — Commit conventions

Monorepo

  1. Nx Docs
  2. Turborepo Docs
  3. Monorepo Tools — Tool comparison

Performance

  1. Git LFS — Large file management
  2. Scalar — Massive repositories
  3. git-filter-repo — History cleanup

Deep Dives

  1. Oh Shit, Git!?! — Git mistake recovery guide
  2. Learn Git Branching — Visual Git learning
  3. Git Internals (PDF) — Git internal architecture

Conclusion

Git is not just a tool — it is core infrastructure that shapes development culture. A clean commit history reflects a team's collaboration capability, and an effective branching strategy determines deployment stability.

You do not need to learn everything in this article at once. Start by understanding the principles behind commands you use daily, then gradually adopt more advanced techniques. Interactive rebase and bisect, in particular, are tools that dramatically boost productivity once you learn them.

Remember: a good commit history is a letter to your future self and your colleagues. Why not start with Conventional Commits today?