Hands-on playground · Learn / Practise / Test

GitWorkflow

From your first commit to running Git on large projects. Read the notes, try the labs, explore each branching strategy on an interactive map, then test yourself.

01 · Git basics

How Git thinks

A commit is a full snapshot of your project, linked to the commit before it.

DistributedEvery clone is a complete repository with full history. You can commit, branch and diff offline.
Content-addressedEach commit is named by a hash of its content and parents, so history can't change silently.
Cheap branchesA branch is a tiny file pointing at one commit. Creating one costs nothing.

Where your changes live

Working directoryFiles you are editing right now
add
Staging areaWhat goes into the next commit
commit
Local repositoryYour commits, on your machine
push
RemoteShared with the team (origin)
Going the other way
git restore <file>
Discard edits in the working directory
git restore --staged
Unstage a file but keep your edits
git fetch / git pull
Bring the team's commits down to you

Try it: the Three Areas lab lets you move files through each stage.

The everyday commands

Start or copy a repository git init · git clone <url>
See what changed git status · git diff
Stage only the hunks you mean git add -p
Record a snapshot git commit
Read the history git log --oneline --graph --all
Create and switch to a branch git switch -c feature/login
Get the team's latest work git fetch · git pull --rebase
Share your branch git push -u origin feature/login

A branch is just a pointer

main and feature/login are labels that point at commits.

HEAD is where you are: the branch you have checked out (shown as HEAD→).

Committing moves the current label forward. Nothing is copied.

Merge or rebase?

git merge

  • Joins two histories with a merge commit
  • Keeps the true record; never rewrites commits
  • Use for shared branches and PR merges

git rebase

  • Replays your commits on top of the latest main
  • Linear history, but creates new commit hashes
  • Use to update your own branch before a PR
02 · Branching strategies

Four common strategies

Strategy How it works Best for Watch out for
Git Flow main + develop, plus feature, release and hotfix branches Versioned releases, several supported versions Heavy process; long-lived branches drift
GitHub Flow main is always deployable; short feature branches merged by pull request Web apps and services with continuous deployment Needs solid CI and fast reviews
Trunk-based Everyone integrates into main at least daily; feature flags hide unfinished work High-velocity teams and monorepos Requires feature flags and strong tests
Release branches Cut release/x.y from main; fixes land on main and are cherry-picked back Products where customers run older versions Back-porting discipline

Walk through each one step by step on the interactive flow map.

Choosing a strategy

If

You deploy many times a day and run one version in production

Use
GitHub Flow or trunk-based
If

You ship versioned releases and support older versions

Use
Git Flow or release branches
If

Many teams share one large repo or monorepo

Use
Trunk-based + feature flags + CODEOWNERS

Name branches so they track

Prefix Purpose Example
feature/ New functionality feature/PAY-142-upi-refunds
fix/ Bug fix in the normal flow fix/PAY-187-null-currency
hotfix/ Urgent production patch hotfix/1.4.1-login-timeout
release/ Stabilise a version release/1.5.0
chore/ Tooling, dependencies, docs chore/bump-node-22

Rules: lowercase and hyphens · include the ticket key · one purpose per branch · delete after merge

03 · Commit conventions

Conventional Commits

<type>(<scope>): <subject>

<body: what changed and why>

<footer: BREAKING CHANGE / Refs>
  • Subject in the imperative: “add”, not “added”
  • About 50 characters, no trailing period
  • Body explains why; the diff already shows what
  • Enforce it with commitlint in a commit-msg hook
feat a new feature
fix a bug fix
docs documentation only
style formatting, no logic change
refactor restructure, same behaviour
perf performance improvement
test adding or fixing tests
build build system, dependencies
ci pipeline configuration
chore other maintenance
revert undoes an earlier commit

Messages your team can use

Avoid
fixed stuff
WIP
update
changes after review
final fix (really)
Prefer
fix(auth): refresh token before expiry check
feat(payments): add UPI refund endpoint
perf(search): cache tokenizer per index
refactor(api): extract rate-limit middleware
docs(readme): document local Docker setup
fix(auth): refresh token before expiry check

Tokens expiring mid-request caused 401s on slow networks.
Refresh when less than 60 s remain instead of after expiry.

Refs: AUTH-311

Clean up before you share

$ git rebase -i origin/main
pick 3f2a1c feat(cart): add coupon field
fixup 9b7d20 fix typo
pick c41e8a test(cart): cover coupon rules
squash 77ab03 more tests
reword 1d09f4 wip

Five noisy commits become three that each make sense on their own.

git commit --fixup <sha>then rebase -i --autosquash folds it in
git add -pstage hunks to keep commits atomic
pull.rebase = trueno “Merge branch main” noise
push --force-with-leasesafe after a rebase; never plain --force
squash or rebase mergekeeps main linear and readable
04 · Git at scale

When the repository gets heavy

Problem Tool Command
Large binaries: models, datasets, design files, videos Git LFS git lfs track "*.psd" "*.onnx"
Clone takes ages because of years of history Partial clone git clone --filter=blob:none <url>
You only work in one part of a monorepo Sparse checkout git sparse-checkout set services/api
CI only needs the latest code Shallow clone git clone --depth 1 <url>
Build outputs and generated files committed .gitignore dist/ build/ *.log → artifact store

Monorepo or many repos?

Monorepo

Gains

Atomic changes across services · one CI setup · shared tooling and code

Costs

Needs sparse checkout, CODEOWNERS and path-filtered CI to stay fast

Polyrepo

Gains

Small, fast repos · independent release cycles · clear ownership

Costs

Cross-repo changes need coordination; shared library versions drift

Keeping Git fast

git maintenance start

Background prefetch, commit-graph and repacking, so fetch and log stay quick

core.fsmonitor = true

A file-system watcher makes git status fast on huge working trees

feature.manyFiles = true

Smaller index and untracked cache for repositories with many files

scalar clone <url>

Ships with Git: partial clone, sparse checkout and maintenance in one step

05 · Problems & fixes

Everyday accidents

Problem

I committed to main instead of my branch

Fix
git branch feature/x
git reset --hard origin/main
git switch feature/x

Only if main isn't pushed yet

Problem

My last commit is missing a file

Fix
git add missed.ts
git commit --amend --no-edit

Already pushed? Make a new commit instead

Problem

I lost commits after a reset or rebase

Fix
git reflog
git branch rescue HEAD@{2}

Reflog keeps every move of HEAD for about 90 days

Team-level incidents

Problem

An API key was pushed to the repo

Fix
git filter-repo --path .env \
  --invert-paths
git push --force-with-lease

Rotate the key first. Add gitleaks to pre-commit.

Problem

A 3-week-old branch conflicts everywhere

Fix
git fetch origin
git rebase origin/main

Sync daily, split into smaller PRs, enable rerere.

Problem

v1.5 broke something. Which commit?

Fix
git bisect start
git bisect bad v1.5.0
git bisect good v1.4.0
git bisect run npm test

Binary search finds it in a few steps.

06 · Conflicts & tracking

Six habits that prevent conflicts

01

Small PRs, merged fast

A few hundred lines, reviewed within a day

02

Sync every day

Rebase on main each morning; small conflicts stay small

03

Clear ownership

CODEOWNERS and module boundaries limit overlapping edits

04

Auto-format everything

Prettier, Black or gofmt in pre-commit: no whitespace fights

05

Defuse hot files

Split giant configs; generate changelogs in CI, not by hand

06

Reuse resolutions

rerere replays a conflict fix you already made once

From ticket to release

Ticket
PAY-142The why
Branch
feature/PAY-142Linked by name
Commits
Refs: PAY-142Typed messages
Pull request
Closes PAY-142Review + CI
Release
v1.5.0Tag + changelog
Protect main

Required reviews and status checks; no direct or force pushes

Tag every release

Semantic versions, so any build maps to an exact commit

Automate the changelog

release-please or semantic-release read your commit types

Small branches.
Clear messages.
Merge often.

A clean history isn't a tool you install. It's a habit the whole team keeps.

git config --global pull.rebase true

No more accidental merge commits

Adopt Conventional Commits

Add commitlint to one repo and see how it feels

Protect main

Require a review and green CI before merge

Lab 1 · The three areas

Move changes from your editor to the team

Lab 2 · Branch sandbox

Type real Git commands, watch the graph

Scenarios
main-line commit branch commit unreachable (reflog only)
$
Lab 3 · Merge vs rebase

Same starting point, two different histories

git merge

On main. Merging joins both histories with a new merge commit; no existing commit changes.

git rebase

On feature/login. Rebasing replays your commits on top of main. Watch the hashes change.

Interactive map · Branching strategies

Walk through each workflow

Which one fits your team?

Pick the situation that sounds like you. The map switches to the recommended strategy.

If

You deploy many times a day and run one version in production

GitHub Flow or trunk-based
If

You ship versioned releases and support older versions

Git Flow or release branches
If

Many teams share one large repo or monorepo

Trunk-based + feature flags + CODEOWNERS
Rules & conventions

Test yourself

Rules lab

Check your own messages and branch names

Commit message checker

Type a subject line and see how it scores against the conventions.

Branch name checker

Prefix, lowercase-and-hyphens, ticket key or version.