Version control is the backbone of modern software development: it keeps a record of changes, helps teams collaborate safely, and enables fast iteration with less risk. For beginners, the most important system to learn is Git—and the most common hosted platform is GitHub.
This guide covers core Git concepts, practical GitHub usage, and branching workflows you can use right away.
Why version control matters
- Track history: every change is recorded with author, timestamp, and message.
- Collaboration: multiple developers work on the same codebase without overwriting each other.
- Reversibility: mistakes are fixable — revert, reset, or restore changes safely.
- Experimentation: branch and test ideas in isolation.
If you’re just starting out, version control ensures you’ll never lose work and can always understand the history of a project.
Core Git concepts & abbreviations
- Repository (repo) — The project container that stores the files, history, and metadata.
- Commit — A snapshot of your files at a point in time.
- Branch — A separate line of development (e.g.,
main,feature/login). - HEAD — Pointer to the current branch or commit you’re working on.
- Remote — A hosted copy of your repository on a server like GitHub.
- Clone — Download a copy of a remote repository locally.
- Push / Pull — Send changes to the remote (
push) or fetch changes from remote (pull). - Merge — Integrate changes from one branch into another.
- Rebase — Replay commits from one branch onto another branch (rewrites history).
- Fork — Create a personal copy of someone else’s repo to publish PRs.
- PR (Pull Request) — A request to merge changes from one branch (or fork) into another.
Additional advanced terms & concepts (novice → intermediate):
- SHA / Hash — A SHA-1 hash like
3a4f2a...uniquely identifies commits. Useful for precise references in commands (reset, revert). - Fast-forward — A merge where the branch pointer simply moves forward because no diverging commits exist.
- Merge commit — A commit that combines two histories when branches diverged (creates a new commit with two parents).
- Upstream / origin —
originis the name of the remote by default.upstreamoften refers to the original repo you forked from. - Tracking branch — A local branch connected to a remote branch like
origin/main. - Stash — A local stack where you can temporarily save working changes with
git stash. - Cherry-pick — Apply a single commit from another branch onto your current branch;
git cherry-pick <hash>. - Bisect — A binary search tool (
git bisect) to find the commit that introduced a bug quickly. - Interactive rebase —
git rebase -ilets you reorder, squash or edit commits in a branch before merging. - Signed commits — Use GPG to sign commits so consumers can cryptographically verify authorship (
git commit -S).
These building blocks will help you follow commands and collaborate across teams.
Essential Git commands — quick reference (beginner-friendly)
Clone a repository:
git clone https://github.com/username/repo.git
Check status / see changes:
git status
git diff # shows unstaged changes
git diff --staged # shows staged changes
Stage & commit changes:
git add file.js
git commit -m "fix: validate user input and avoid crash"
Create a branch and switch to it:
git switch -c feature/login-form
# or older: git checkout -b feature/login-form
Push branch to remote and create a PR on GitHub:
git push -u origin feature/login-form
# then open a PR on GitHub
Merge from remote main into your branch:
git fetch origin
git merge origin/main
# or rebase onto main
git rebase origin/main
Undo mistakes:
# unstage a file
git restore --staged file.js
# throw away local changes in file
git restore file.js
# revert a commit (safe for shared history)
git revert <commit-hash>
# reset branch to a previous commit (rewrites history, use with caution)
# git reset --hard <commit-hash>
View log history:
git log --oneline --graph --decorate --all
Example: stash workflow (useful when you need to change branch but have uncommitted work)
# Save your local changes
git stash save "WIP: quick prototype"
# List stash entries
git stash list
# Apply latest stash back to working tree
git stash apply
# Drop a stash
git stash drop stash@{0}
Example: finding a regression with git bisect
# Start a bisect session
git bisect start
git bisect bad # mark current commit as bad
git bisect good v1.2.3 # mark a known-good tag or commit
# Git will checkout a commit in the middle; run tests and mark good/bad
git bisect good|bad
# When you are done, reset bisect
git bisect reset
GitHub essentials for collaboration
- Fork vs Clone: Fork is a copy hosted under your account used for contributing to projects you don’t own; clone is creating a local copy of a repo you can push to.
- Pull Requests (PRs): Central to code review and collaboration—use PRs to propose changes, request reviews, and describe context.
- Issues: Track bugs and feature requests. Link PRs to issues using keywords like
closes #123. - Actions: Automate CI/CD, run unit tests, publish a build, or run audits on PRs.
- Branch protection: Enforce reviews, passing CI, and status checks before allowing merges.
Practical GitHub features beginners should use:
- Use templates for PR description and issue creation.
- Add reviewers and labels to PRs to speed triage.
- Use
gh(GitHub CLI) to open PRs from the terminal:gh pr create.
Branching workflows: pick the right one for your team
Branching strategies define how you structure work and merge changes. Choose a workflow that fits your team’s size and release cadence.
1) Trunk-Based Development (recommended for fast-moving teams)
- Single long-lived branch (e.g.,
main) with short-lived feature branches that are merged frequently (often within hours or days). - Leverage feature toggles for partial releases.
- Pros: simpler, faster iteration, fewer long-lived merges.
- Cons: requires disciplined CI, fast PR reviews, and robust tests.
Suggested flow:
- Create a short-lived branch:
git switch -c feat/new-button. - Make small, focused commits.
- Push and open PR.
- PR passes tests and review, merge into
main, and delete branch.
2) Git Flow (recommended for teams with versioned releases)
- Long-lived branches:
main,develop, plusfeature/,release/, andhotfix/branches. - Pros: structure that’s clear for releases and hotfixes.
- Cons: heavier process; more merge overhead.
Suggested flow:
- Feature branches are created from
developand merged back intodevelop. - When ready for a release, create
release/x.yfromdevelop; after QA, mergereleaseintomainanddevelop.
Continuous Delivery & GitOps (deployment-triggered text graph)
If your team follows GitOps, deploys typically map to branch events and are automated by CI/CD pipelines:
Developer -> Git push -> CI (test/lint/build) -> Container Registry -> CD (deploy/staging -> deploy/production)
Example sequence:
- Developer pushes
feature/foobranch to origin. - CI runs tests on the PR (GitHub Actions / GitLab CI).
- On merge to
main(or create a release tag), CI builds an image, pushes it to registry, and CD deploys to staging/production.
Tip: Use main -> staging -> production branches or tags to gate what gets deployed.
3) Feature Branching (common for most teams)
- Features live in separate branches until they’re ready.
- Use PRs and automated CI to validate changes.
- Keep branches small and frequent to avoid conflicts.
Practical, beginner-friendly branching pattern (safe workflow)
- Start from clean
mainand sync to remote:
git switch main
git pull origin main
- Create a small branch for your feature:
git switch -c feat/add-login
- Make small commits with clear messages (use Conventional Commits):
git add .
git commit -m "feat(login): add validation and initial form UI"
- Push and open a PR early to get feedback:
git push -u origin feat/add-login
# open PR on GitHub, add reviewers and tests
- Keep your branch up to date:
git fetch origin
# merge or rebase main — prefer rebase for cleaner history if your team allows
git rebase origin/main
# or
git merge origin/main
- After code review and passing CI, merge and delete the branch.
gh pr merge --auto
git push origin --delete feat/add-login
Good commit messages and conventions
- Use small atomic commits that explain a single logical change.
- Consider the Conventional Commits syntax:
feat(auth): add password reset flow
fix(ui): handle empty results on search
chore(deps): bump lodash to 4.17.21
- Give a clear body when the change requires more context (why, impacts, edge cases).
Handling conflicts & common mistakes
- Conflicts occur when two branches change the same lines. Git will pause the merge and show conflict markers in files—fix and
git addthe resolved file, then continue the merge or rebase. - Undoing commits:
git revert <hash>— create a new commit that undoes a previous commit (safe for shared history).git reset --soft <hash>— move HEAD but keep changes staged (local-only history rewrite).git restore <file>— restore a file from the index or another commit.
- If you mistakenly commit to
main, revert or create a PR with the fix and avoid rewriting public history.
GitHub PR tips & code review best practices
- Keep PRs focused and small—easier to review, less risky to merge.
- Provide a clear description, link to related issue, and mention testing steps.
- Use GitHub descriptions and checklists for testing steps:
- unit tests added
- integration tests added
- updated docs
- Add reviewers who understand the area and set expectations for turnaround.
- Use CI actions to run tests, linters, and security analysis for every PR.
Recommended tools & best practices
- CLI Tools:
gh(official GitHub CLI),git(standard),deltafor nice diffs. - GUIs: GitHub Desktop, GitKraken, Fork, SourceTree for visual learners.
- Linting & commits: Husky for pre-commit hooks, lint-staged for formatting, and commitlint for enforcing commit message conventions.
- CI / CD: GitHub Actions, CircleCI, or GitLab CI for PR checks and deployment pipelines.
Useful git configuration & signing (security)
# Set your global identity
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
# Use GPG to sign commits (requires GPG setup)
git commit -S -m "feat: signed commit"
Advanced example: interactive rebase to clean up commits
# Re-order/squash/edit last 5 commits interactively
git rebase -i HEAD~5
# In the editor: replace 'pick' with 's' (squash) to squash commits or reorder lines to change order.
# Save and exit to make rebase changes.
Advanced example: cherry-pick and tags
# Copy a single commit from another branch into your current branch
git cherry-pick <commit-sha>
# Create an annotated tag for release
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
Git LFS & large files
If your repository has large media files or datasets, use Git LFS to avoid bloating history:
git lfs install
git lfs track "*.psd"
git add .gitattributes
git commit -m "chore: add LFS for psd files"
Pros & Cons: Git vs Other VCS & GitHub alternatives
Git
- Pros: Distributed, highly performant, excellent tooling & community, powerful branching and rebasing capabilities, and broad adoption.
- Cons: Complex history operations (rebase), large monorepo setups require additional tooling, steep learning curve for force-push/rewrites.
Mercurial (hg)
- Pros: Simpler mental model for some users, used in projects where simpler branching is preferred.
- Cons: Smaller ecosystem compared to Git — fewer integrations and community resources.
Centralized VCS (SVN, Perforce)
- Pros: Simpler for teams used to linear history and single central server.
- Cons: Lack of distributed features and branch flexibility; less common in modern open-source workflows.
GitHub vs GitLab vs Bitbucket
- GitHub: Best for public open-source projects and integrated community features (Issues, Actions, Marketplace, Codespaces).
- GitLab: Strong built-in CI, integrated deployment tools, robust permissions and self-host options.
- Bitbucket: Strong integration with Atlassian stack (Jira, Confluence), good for teams using those products.
Choose the right combination for your team: Git is the underlying VCS, choose the hosting service (GitHub/GitLab/Bitbucket) that aligns with tooling and compliance needs.
Common pitfalls & best practices
- Don’t rewrite published history (avoid
git push --forceon shared branches). - Use small commits and PRs for quick reviews and easier debugging.
- Keep
maingreen—always ensure tests pass or use branch protection rules. - Add
.gitignoreearly and don’t accidentally commit environment files or secrets. - Protect release branches; require PRs, code review, and passing CI checks.
Quick learning exercises (practice tasks)
- Create a repo, commit an app skeleton, and try reverting a commit.
- Make a branch, add a feature, open a PR against
main, and merge it with a squash. - Simulate a conflict by editing the same line on two branches and resolving it.
Further reading & resources
- Pro Git (book, free)
- GitHub Docs
- GitHub CLI
- Git branching model explained (GitFlow)
- Conventional Commits
More tutorials & interactive learning
- Learn Git Branching — interactive tutorial
- Atlassian Git Tutorials (Visual)
- Git Cheat Sheet (Github)
- Git Best Practices — (Microsoft)
Books & Guides
- Git under the hood — Pro Git (free book)
- Effective Git — a practical set of tips and patterns.
Quick CLI tools & helpers
- gh (GitHub CLI) — GitHub CLI for PR creation & workflows.
- tig — text-mode interface for git logs and diffs.
- git-delta (delta) — improved diffs in the terminal.
Conclusion — Start small, git better over time
Version control is an essential skill for every developer. Start with the basic commands and workflows in this guide, use GitHub for collaboration and PR-based reviews, and adopt a consistent branching strategy that fits your team. Over time, your speed and confidence will grow as you rely on version control to collaborate safely, experiment fearlessly, and ship more often.
Happy versioning! 🚀
Comments