Git Basics: init, add, commit — Your First Repository
Before We Start
This article picks up where Part 1: What Is Git and Why Every Developer Needs It left off. If you haven't read it yet, that's okay — but make sure you have Git installed on your machine before continuing. You can verify by opening your terminal (Terminal on Mac/Linux, Git Bash or Windows Terminal on Windows) and typing:
git --version
If you see a version number like git version 2.43.0, you're good to go. If not, head back to Part 1 for installation instructions.
You should also have your name and email configured:
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
This only needs to be done once. Git attaches this information to every commit you make, so your teammates know who made each change.
The Three Stages of Git
Before we type a single command, you need to understand how Git thinks about your files. Every file in a Git project exists in one of three stages:
1. Working Directory
This is your project folder — the files you see and edit on your computer. When you create a new file, edit an existing one, or delete something, those changes happen in the working directory. Git can see these changes, but it hasn't recorded them yet.
Think of the working directory as your desk. It's where you do your actual work.
2. Staging Area (Index)
The staging area is a holding zone between your working directory and Git's permanent history. When you're happy with a change, you move it to the staging area. This tells Git: "I want to include this change in my next snapshot."
Think of the staging area as a box you're packing. You choose exactly which changes go in the box before sealing it.
Why does this step exist? Because you don't always want to save everything at once. Maybe you changed five files, but only three of those changes are related to the task you're working on. The staging area lets you group related changes together into a single, meaningful commit.
3. Repository (Commit History)
When you commit, Git takes everything in the staging area and saves it as a permanent snapshot in the repository. This snapshot gets a unique ID, a timestamp, your name, and the message you wrote. It's now part of your project's history forever.
Think of the repository as a warehouse full of sealed, labeled boxes. Each box is a commit. You can open any box at any time to see exactly what your project looked like at that moment.
The Flow
The basic Git workflow always follows this pattern:
Working Directory → Staging Area → Repository
(edit) (git add) (git commit)
That's it. Every Git workflow, no matter how complex, is built on top of this simple three-step cycle. Let's put it into practice.
Creating Your First Repository: git init
Let's build something real. We'll create a simple project and track it with Git from the very beginning.
Open your terminal and create a new folder for your project:
mkdir my-first-repo
cd my-first-repo
Right now, this is just an ordinary, empty folder. Git knows nothing about it. To turn it into a Git repository, type:
git init
You'll see a message like:
Initialized empty Git repository in /home/you/my-first-repo/.git/
That's it — your folder is now a Git repository. But what actually happened?
Git created a hidden folder called .git inside your project. This folder is where Git stores everything: the commit history, the staging area, configuration, and more. You never need to touch this folder directly — Git manages it for you. But it's good to know it's there.
You can see it by running:
ls -la
You'll see the .git directory listed alongside your other files.
Important: Never delete the .git folder. If you do, you'll lose your entire project history. The rest of your files will be fine, but all the version tracking — every commit, every branch — will be gone.
Checking the Status: git status
Before we make any changes, let's learn the most useful command in Git — the one you'll type more than any other:
git status
Right now, since we haven't created any files yet, Git will tell you:
On branch main
No commits yet
nothing to commit (create/copy files and use "git add" to track)
This tells you three things: you're on the main branch (the default), there are no commits yet, and there's nothing to commit because the folder is empty.
git status is your compass. Whenever you're unsure what's going on, type it. It will always tell you where you are, what's changed, and what Git expects you to do next.
Creating and Tracking Files: git add
Let's create our first file. You can use any text editor, but for simplicity, we'll create it from the terminal:
echo "# My First Project" > README.md
This creates a file called README.md with one line of text. Now let's check the status again:
git status
Git responds with:
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)
Git sees the new file, but it's listed as untracked. That means Git knows it exists but isn't watching it yet. It's sitting on your desk, but you haven't put it in the box.
Let's add it to the staging area:
git add README.md
Now check the status again:
git status
Output:
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
The file has moved from untracked to staged. It's in the box, ready to be sealed. But it hasn't been committed yet — we haven't saved the snapshot.
Adding Multiple Files
In real projects, you'll often have multiple files to stage. Here are the different ways to use git add:
git add filename.txt— Stages a single specific file.git add file1.txt file2.txt— Stages multiple specific files.git add .— Stages everything in the current directory that has changed. This is the most common shortcut, but use it carefully — make sure you actually want to include all changes.git add *.html— Stages all files matching a pattern (all HTML files in this case).
Saving a Snapshot: git commit
Now let's seal the box. We'll commit the staged changes with a message that describes what we did:
git commit -m "Initial commit: add README file"
Git responds with something like:
[main (root-commit) a1b2c3d] Initial commit: add README file
1 file changed, 1 insertion(+)
create mode 100644 README.md
Let's break down what happened:
- main — The branch you committed to.
- root-commit — This is the very first commit in the repository.
- a1b2c3d — The first 7 characters of the commit's unique ID (called a SHA hash). Every commit has a unique one.
- "Initial commit: add README file" — Your commit message. This is how you and your teammates will understand what this change was about.
- 1 file changed, 1 insertion(+) — A summary of what changed in this commit.
Congratulations — you've made your first commit. Your project now has a history with one entry in it.
The -m Flag
The -m flag lets you write your commit message directly in the command. If you leave it out and just type git commit, Git will open a text editor (usually Vim or Nano) where you can write a longer, multi-line message. For now, -m is the easiest approach.
Let's Make More Changes
One commit isn't much of a history. Let's build it up. Edit the README file to add more content:
echo "This is a project where I learn Git." >> README.md
And create a new file:
echo "<!DOCTYPE html><html><body><h1>Hello World</h1></body></html>" > index.html
Now check the status:
git status
Output:
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
Notice how Git distinguishes between the two files. README.md is modified — Git was already tracking it, and it sees that the content changed. index.html is untracked — it's a brand new file that Git hasn't seen before.
Let's stage both files and commit:
git add .
git commit -m "Update README and add homepage"
Now our project has two commits in its history.
Viewing Your History: git log
To see the full history of your project, type:
git log
You'll see something like:
commit b4e5f6g (HEAD -> main)
Author: Your Name <your.email@example.com>
Date: Fri Feb 14 10:30:00 2026
Update README and add homepage
commit a1b2c3d
Author: Your Name <your.email@example.com>
Date: Fri Feb 14 10:15:00 2026
Initial commit: add README file
This is your project's story, told in reverse chronological order (newest first). Each entry shows the commit ID, the author, the date, and the message.
The word HEAD next to the latest commit means "you are here." It's Git's way of pointing to the current position in your history.
If you have a long history and want a more compact view, try:
git log --oneline
Output:
b4e5f6g (HEAD -> main) Update README and add homepage
a1b2c3d Initial commit: add README file
Clean, short, and easy to scan. This is the format you'll use most often in practice.
What About Files You Don't Want to Track?
Not every file in your project should be tracked by Git. Some common examples:
- System files like .DS_Store (Mac) or Thumbs.db (Windows)
- Dependency folders like node_modules — these can contain thousands of files and can be regenerated with a single command
- Environment files like .env that contain passwords, API keys, or secret tokens
- Build output like dist/ or build/ folders
- Log files that are generated automatically
To tell Git to ignore specific files, create a file called .gitignore in the root of your project:
echo "node_modules/" > .gitignore
echo ".env" >> .gitignore
echo ".DS_Store" >> .gitignore
Now let's add and commit the .gitignore file itself:
git add .gitignore
git commit -m "Add .gitignore to exclude system and environment files"
From this point on, Git will completely ignore any files or folders listed in .gitignore. They won't show up in git status, won't be staged, and won't be committed — even if you use git add ..
Common Beginner Mistakes (and How to Avoid Them)
Here are the mistakes nearly every beginner makes. Knowing them upfront will save you frustration:
Mistake 1: Forgetting to Stage Before Committing
You edit a file, type git commit -m "fix bug", and nothing happens. Git says "nothing to commit." That's because you skipped the staging step. You need to git add first. The cycle is always: edit → add → commit.
There is a shortcut for files Git is already tracking:
git commit -am "fix bug"
The -a flag automatically stages all modified tracked files before committing. But it won't add new untracked files — you still need git add for those.
Mistake 2: Vague Commit Messages
Messages like "fix", "update", "stuff", or "asdfg" are useless. When you're debugging a problem three months from now and scrolling through the history, you'll thank yourself for writing clear messages. A good commit message answers the question: what did this change do and why?
- Bad: "update"
- Bad: "fix stuff"
- Good: "Fix login button not responding on mobile"
- Good: "Add email validation to signup form"
Mistake 3: Committing Sensitive Information
Passwords, API keys, tokens, and secrets should never be committed. Once something is in your Git history, it's very difficult to fully remove it — even if you delete the file later. Always add your .env file and other sensitive files to .gitignore before your first commit.
Mistake 4: One Giant Commit
Don't work all day and then make one massive commit with the message "full day of work." Small, focused commits are better. Each commit should represent one logical change: one bug fix, one feature, one refactor. This makes your history useful and makes it easy to undo specific changes later.
Quick Reference: The Commands You've Learned
| Command | What It Does |
|---|---|
git init |
Creates a new Git repository in the current folder |
git status |
Shows the current state of your files (modified, staged, untracked) |
git add <file> |
Moves a file to the staging area |
git add . |
Stages all changed and new files in the current directory |
git commit -m "message" |
Saves a snapshot of all staged changes with a description |
git commit -am "message" |
Stages all modified tracked files and commits in one step |
git log |
Shows the full commit history |
git log --oneline |
Shows a compact, one-line-per-commit history |