Resources / Guide
Git basics: the everyday workflow
Most git guides start by listing thirty commands. That's the wrong end. You need a handful to do real work — and they all click once you understand the one thing those lists skip: where your code actually lives while git tracks it. Here's the loop you'll run every day.
This is the workflow I'd hand to someone joining a team, or to a solo developer who's been saving project-final-v3 folders and is ready to stop. No history rewriting, no advanced tricks — just the loop you'll run every day.
The mental model: four places your code lives
When git is tracking a project, a file can be in four states. This is the whole foundation, so it's worth thirty seconds.
- Working directory — the actual files on your disk, the ones you edit. This is just your folder.
- Staging area (also called the index) — a holding pen for changes you've decided belong in your next save. You put changes here on purpose.
- The repository — the permanent history of saved snapshots (commits) living in the hidden
.gitfolder. Once something's committed, it's safe. - The remote — a copy of that history hosted somewhere shared (GitHub, GitLab, Azure DevOps). This is how your work reaches teammates and theirs reaches you.
Work flows in one direction: you edit in the working directory, move changes into the staging area, save them into the repository as a commit, then push that commit to the remote. Every command below is just moving changes from one of those places to the next.
Starting out: clone or init
If the project already exists on a remote, you clone it — that copies the whole history down and wires up the remote connection in one step:
git clone https://github.com/yourteam/project.git
If you're starting something brand new locally, you init it instead, then connect a remote later:
git init
Most of the time on a team, you're cloning. You do this once per project.
The everyday loop: status, add, commit, push
This is the cycle you'll run dozens of times a day. Four commands.
See what's changed. Start here whenever you're unsure of anything. git status is the command you'll run most, and it always tells you which files changed and what state they're in:
git status
Stage the changes you want to save. git add moves changes from the working directory into the staging area. You can add specific files or everything at once:
git add Program.cs # one file
git add . # everything that changed
Staging exists so you can choose what goes into a commit. If you fixed a bug and tweaked some unrelated formatting, you can stage and commit them separately, so each commit is one coherent change. That discipline pays off later when you're reading history.
Commit — save a snapshot. git commit takes everything staged and writes it into history as one permanent snapshot, with a message describing what it is:
git commit -m "Fix null reference when order has no line items"
Write the message for the person reading it in six months (often you). "Fix bug" tells them nothing; "Fix null reference when order has no line items" tells them exactly what changed and why. A good rule: finish the sentence "This commit will…".
Push — send it to the remote. Commits are local until you push. git push uploads your commits to the shared remote so teammates can see them:
git push
That's the loop: status → add → commit → push, over and over. Everything else is built on it.
Pulling: getting everyone else's work
While you've been working, your teammates have been pushing their own commits. git pull brings their work down into your local copy:
git pull
Pull often — at the start of your day and before you start something new. The longer your copy drifts from the remote, the more your changes and theirs diverge, and the more likely you are to hit a merge conflict (two people editing the same lines). Conflicts aren't disasters; git pauses and asks you to pick which version wins, you edit the file to resolve it, then commit. But frequent pulling keeps them small and rare.
Branches: working without stepping on anyone
So far everything's been on the main line of development (usually called main or master). On a team, you don't commit half-finished work directly there — main is supposed to stay working and deployable. Instead you make a branch: your own parallel line where you can commit freely without affecting anyone until you're ready.
A branch is cheap — it's just a movable label pointing at a commit. Create one for each piece of work:
git checkout -b feature/order-export
That makes a new branch called feature/order-export and switches you onto it. Now your add / commit loop happens on that branch, isolated. When the feature's done, you push the branch up:
git push -u origin feature/order-export
The -u (just the first time) links your local branch to the remote one, so future pushes are a plain git push.
The everyday version of this: pull main, branch off it, do your work in small commits, push the branch. One branch per feature or fix keeps things tidy and makes the next step — review — clean.
Pull requests: how work gets reviewed and merged in
Here's where teams differ from solo work. You could just merge your branch into main yourself, but on a team you almost never do. Instead you open a pull request (a "PR"; GitLab calls it a "merge request" — same thing).
A pull request is a proposal: "here are the commits on my branch, please review them and merge them into main." It's not a git command — you open it on your hosting platform (GitHub, Azure DevOps, etc.), usually with a button that appears right after you push a branch. The PR exists for three reasons:
- Review. Teammates read your changes, comment, and request tweaks before the code lands. This is the main event — it's how quality stays up and how knowledge spreads across the team.
- Automated checks. Most teams run the build and tests automatically on every PR. If something's broken, you find out before it hits
main, not after. - A record. The PR becomes a permanent, linkable discussion of why a change was made — far more context than the commits alone.
The flow is: push your branch → open a PR targeting main → reviewers comment → you push fixes to the same branch (the PR updates automatically) → once it's approved and checks pass, someone clicks Merge.
Merging: your branch joins the main line
Merging is the act of taking the commits from your branch and combining them into main. When you click "Merge" on an approved PR, that's what happens — main now contains your work, and the feature branch can be deleted.
You don't need the advanced details yet (the different kinds of merge are their own topic), just the shape of it: your isolated branch of commits becomes part of the shared history everyone builds on. After a merge, everyone else picks up your work the next time they git pull.
That closes the circle. Your teammate's merged PR is exactly the "everyone else's work" that your next git pull brings down.
Your daily routine, start to finish
Put together, a normal day looks like this:
git pull # get the latest main
git checkout -b feature/whatever # branch for today's work
# ... edit files ...
git status # what changed?
git add . # stage it
git commit -m "Clear, specific message" # save a snapshot
# ... repeat edit/add/commit as you go ...
git push -u origin feature/whatever # send the branch up
# open a pull request, get it reviewed, merge it
That's the whole everyday workflow. Six or seven commands, one clear loop, and a mental model of four places code lives that explains every one of them. Everything else in git — undoing changes, rewriting messy commits, untangling a gnarly conflict — is a tool you reach for occasionally, layered on top of this. Get comfortable with the loop first, and the rest is much easier to learn when you actually need it.
Getting a team set up on git the right way?
Branch conventions, pull-request workflow, the CI checks that run on every PR — I help teams stand up the version-control and deployment habits that keep main shippable. If you want a hand, let's talk.