· 5 min read
Git for every project
Why git is the version control tool we use for everything: cheap branches for refactoring and experiments, smooth collaboration, and the commands you'll use every day.
Every project we build starts the same way: git init, then the first test. Version control isn’t an extra you add once a project gets serious. It’s the safety net that lets you work boldly from the very first line.
The best guide to git is free: Pro Git, by Scott Chacon and Ben Straub. This post links to the chapters that matter most.
Why version control at all
Without version control, “undo” stops at your editor’s history and “backup” means a folder called project-final-v2-REAL. With it, you get:
- A complete history. Every change is recorded with who made it, when, and why.
- Fearless undo. Any earlier version of any file is one command away.
- Answers to “what changed?” When something breaks, you can compare the working version with the broken one line by line.
- A record of intent. Good commit messages explain why the code looks the way it does, long after everyone has forgotten.
The book’s opening chapter, About Version Control, explains how git differs from the centralized tools that came before it.
Why git
Git is distributed: every clone is a full copy of the project and its history. That means:
- It’s fast. History, diffs, commits and branches are local operations, with no server round trip.
- It works offline. Commit on a plane and push when you land.
- There’s no single point of failure. Every developer’s clone is a backup.
- It’s everywhere. GitHub, GitLab, Bitbucket, editors, IDEs and CI systems all speak git.
Branches are cheap, so use them
This is git’s real superpower. In older systems a branch was a heavyweight copy of the project, so teams avoided them. In git, a branch is just a small pointer to a commit. Creating one is instant, and switching between them takes a moment. Branches in a Nutshell shows exactly how this works.
Cheap branches change how you work:
- Refactoring becomes safe. Start a branch, restructure the code, and keep the tests green as you go. If the refactor turns out to be a bad idea, switch back and delete the branch. Nothing on the main line was ever at risk.
- Experiments cost nothing. Want to try a different library, algorithm or design? Make a branch, spike it, and compare. Keep it if it wins; throw it away if it doesn’t.
- Interruptions stop hurting. An urgent bug arrives mid-feature? Commit or stash your work, branch from main, fix the bug, and come back exactly where you left off.
- Main stays releasable. Unfinished work lives on its own branch until it’s tested and ready.
When work is ready, you bring it back with a merge or a rebase. Basic Branching and Merging and Rebasing cover both, and Branching Workflows describes common ways teams organize long-running and short-lived branches.
Managing collaboration
Git really shines when more than one person touches the code.
- Everyone works in parallel. Each developer works on their own branches without stepping on anyone else’s changes.
- Merges are routine. Git combines independent changes automatically. When two people edit the same lines, it marks the conflict clearly and asks a human to decide.
- Pull requests make review natural. Push a branch, open a pull request or merge request, and teammates review the change before it reaches main. CI runs the tests on every push.
- History tells the story.
git logandgit blameshow who changed a line and the commit message explaining why. - Bugs can be hunted down.
git bisectbinary-searches your history to find the exact commit that introduced a bug. Pair it with a failing test and it can run the search for you. See Debugging with Git.
For how teams set this up, read Distributed Workflows and Contributing to a Project.
The commands you’ll use most
You can do a great deal with a handful of commands. Here they are, grouped by task.
Start a project
git init # turn the current folder into a repository
git clone <url> # copy an existing repository, with its full historyRecord changes
git status # what's changed, staged, and untracked
git diff # unstaged changes, line by line
git diff --staged # what the next commit will contain
git add <file> # stage a file for the next commit
git add -p # stage changes hunk by hunk
git commit -m "message" # record the staged changes
More in Recording Changes to the Repository.
Look at history
git log --oneline --graph # compact history with branch structure
git show <commit> # one commit's message and changes
git blame <file> # who last changed each line, and in which commitBranch and merge
git branch # list branches
git switch -c <branch> # create a branch and switch to it
git switch <branch> # switch to an existing branch
git merge <branch> # merge a branch into the current one
git rebase main # replay the current branch on top of main
git branch -d <branch> # delete a branch that has been mergedShare with others
git remote -v # list remote repositories
git fetch # download new commits without changing your work
git pull # fetch and merge the current branch's upstream
git push -u origin <branch> # publish a branch and track it
git push # send new commits to the tracked branch
More in Working with Remotes.
Undo and set aside
git restore <file> # discard unstaged changes to a file
git restore --staged <file> # unstage a file but keep its changes
git commit --amend # fix the last commit's message or contents
git revert <commit> # make a new commit that undoes an old one
git stash # set uncommitted work aside
git stash pop # bring it back
More in Undoing Things and Stashing and Cleaning.
Where to go next
- Read the first three chapters of Pro Git. They cover everything above in more depth, with diagrams.
- Run
git help <command>for the full manual of any command. - Practice on a throwaway repository: branch, break things, merge, and undo. Git makes mistakes cheap, so make plenty while you learn.