Back to blog

Git fundamentals

I used Git for a year before I actually understood it. This article is what I wish someone had explained to me on day one.

March 18, 202612 min read
GitVersion ControlBeginnerCommand Line
Git fundamentals
The Three Areas - Files flow from Working Directory through Staging to Repository
The Three Areas - Files flow from Working Directory through Staging to Repository

I used Git for a year before I actually understood it.

I memorized commands. git add ., git commit -m "fix", git push. It worked. Until it didn't. Then I'd panic, Google the error, and copy-paste solutions I didn't understand.

Sound familiar?

This article is what I wish someone had explained to me on day one.


What is Git, really?

Git is a version control system. But that definition doesn't help.

Here's a better one: Git is a system that takes snapshots of your project over time.

Every time you commit, Git saves the entire state of your project at that moment. Not just the changes, the whole thing. It's like saving a video game: you can always go back to any previous save.

These snapshots are linked together, forming a timeline of your project.

HEAD is just a pointer to where you are right now. Usually, it points to your latest commit.

<details> <summary>🔍 Going deeper: how Git actually stores data</summary>

Git doesn't store differences between files (like SVN). It stores complete snapshots. But it's smart: if a file hasn't changed, Git just keeps a reference to the previous version.

Each commit has a unique SHA-1 hash (e.g., a1b2c3d). This hash is computed from the content, so two identical commits will have the same hash.

That's why Git is so fast at navigating history: everything is indexed by these hashes.

</details>

The three areas

This is the mental model that changed everything for me.

Git has three areas:

  1. Working directory: The files you see and edit
  2. Staging area (index): Files you've marked to include in your next commit
  3. Repository: The history of all commits

When you edit a file, it changes in your working directory. Git notices, but doesn't do anything yet.

When you run git add, you move those changes to the staging area. You're saying "I want these changes in my next commit."

When you run git commit, Git takes everything in the staging area and creates a snapshot.


Your first commands

git init

Creates a new Git repository in the current folder.

mkdir my-project
cd my-project
git init

This creates a hidden .git folder. That's where Git stores everything.

[!WARNING] Never touch the .git folder manually. If you delete it, you lose all history.

git status

Shows you what's going on. Use it constantly.

git status

It tells you:

  • Which files have changed
  • Which changes are staged
  • Which branch you're on

This is your best friend. When in doubt, git status.

[!TIP] Make it a habit to run git status before and after every command. You'll always know where you stand.

git add

Moves changes from working directory to staging area.

# Add a specific file
git add index.html

# Add all files in current directory
git add .

# Add all changes (including deletions)
git add -A

I use git add . most of the time. But sometimes you want to commit only some files, that's when you add them individually.

git commit

Creates a snapshot from the staging area.

git commit -m "Add login page"

The -m flag lets you write a message inline. Without it, Git opens your editor.

A good commit message:

  • Starts with a verb (Add, Fix, Update, Remove)
  • Is short (50 characters or less)
  • Explains what, not how
# ❌ Bad
git commit -m "changes"
git commit -m "fixed stuff"
git commit -m "WIP"

# ✅ Good
git commit -m "Add user authentication"
git commit -m "Fix login redirect loop"
git commit -m "Remove unused dependencies"

git log

Shows the commit history.

git log

This shows every commit with its hash, author, date, and message.

For a cleaner view:

git log --oneline

This shows one commit per line. Much easier to scan.

git diff

Shows what changed.

# Changes in working directory (not staged)
git diff

# Changes in staging area (will be in next commit)
git diff --staged

The .gitignore file

Some files shouldn't be tracked: dependencies, build outputs, secrets.

Create a .gitignore file at the root of your project:

# Dependencies
node_modules/

# Build output
dist/
build/

# Environment variables (secrets!)
.env
.env.local

# OS files
.DS_Store
Thumbs.db

# IDE
.idea/
.vscode/

Git will ignore any file matching these patterns.

[!NOTE] If you already committed a file, adding it to .gitignore won't remove it. You need to untrack it first:

git rm --cached .env
git commit -m "Remove .env from tracking"

Remote repositories

So far, everything is local. To share your code, you need a remote.

git remote

Links your local repo to a remote (usually GitHub).

git remote add origin https://github.com/username/my-project.git

origin is just a name. It's convention. You could call it github or banana. But stick with origin.

git push

Sends your commits to the remote.

git push origin main

Before your first push, check:

  • You have a remote configured (git remote -v)
  • You're on the right branch (git branch)
  • Your changes are committed (git status)

First time, you might need:

git push -u origin main

The -u sets the upstream, so next time you can just git push.

git pull

Gets commits from the remote.

git pull origin main

This fetches changes and merges them into your local branch.

git clone

Downloads a remote repository.

git clone https://github.com/username/my-project.git

This creates a folder with the project and all its history.


Common mistakes and how to fix them

"I committed to the wrong branch"

# Undo the last commit, keep the changes
git reset --soft HEAD~1

# Switch to the correct branch
git checkout correct-branch

# Commit again
git commit -m "Your message"

"I need to change my last commit message"

git commit --amend -m "New message"

Only do this if you haven't pushed yet.

"I added a file I shouldn't have"

# Remove from staging, keep the file
git reset HEAD filename

# Or remove from tracking entirely
git rm --cached filename

"I want to undo all my local changes"

# Discard all changes in working directory
git checkout -- .

# Or with newer Git
git restore .

[!WARNING] This is destructive. Those changes are gone forever. Make sure you really want to discard them.


The cheat sheet

CommandWhat it does
git initCreate a new repository
git statusSee what's going on
git add .Stage all changes
git commit -m "msg"Create a snapshot
git log --onelineSee commit history
git diffSee unstaged changes
git pushSend to remote
git pullGet from remote
git clone urlDownload a repository

The takeaway

"Commit early, commit often." -- Git mantra

Git is not magic. It's a system for taking snapshots and navigating between them.

Once you understand the three areas (working directory → staging → repository), everything else makes sense.

Next article, we'll talk about branches, the feature that makes Git truly powerful.


This is part 1 of my "Git & GitHub in 10 articles" series.

Questions? Hit me up on LinkedIn or check out more on my blog.