The Git Workflow - Add, Commit, Status

The Git Workflow - Add, Commit, Status

The Three States: Working, Staging, and Committed

Introduction

Understanding Git's three-state workflow is fundamental to mastering version control. Unlike simpler systems where you just "save" your work, Git gives you precise control over what gets saved and when. This might seem complicated at first, but it's actually one of Git's most powerful features.

This lesson will help you understand how files move through Git's workflow and why this multi-stage approach makes you a more effective developer.

The Three States Explained

Every file in your Git repository can exist in one of three states:

Modified (Working Directory) - You've changed the file, but haven't told Git you want to save those changes yet. The file exists in your working directory with unsaved modifications.

Staged (Staging Area/Index) - You've marked the modified file to be included in your next commit. Think of this as adding items to a shopping cart before checkout.

Committed (Repository) - The changes are safely stored in your Git repository's database. This is like completing the purchase—the transaction is final and recorded.

Visualizing the Workflow

Imagine you're a photographer managing photos:

Working Directory = Your camera's memory card with new photos Staging Area = A selection table where you choose which photos to publish Repository = Your published photo album

You take many photos (modify files), select the best ones for your album (stage files), then publish that curated collection (commit). You wouldn't publish every single photo you take—you carefully choose what goes into each album. Git works the same way.

The Working Directory

The working directory is simply your project folder—the files and folders you see and edit normally. When you modify a file here, Git notices but doesn't automatically do anything with that change.

Example Scenario:

You're building a website. You edit index.html to add a new navigation menu. At this point, the file is modified in your working directory. Git sees the change but hasn't captured it in history yet.

Check what's modified:

git status

Output might show:

On branch main
Changes not staged for commit:
  modified:   index.html

The file is modified but not staged. If your computer crashes right now, you'd lose those changes because they're only in your working directory—not yet protected by Git.

The Staging Area

The staging area (also called the "index") is Git's unique feature. It's a holding area where you prepare your next commit. This intermediate step gives you control over exactly what goes into each commit.

Why Have a Staging Area?

Imagine you're working on two different features: fixing a bug and adding a new feature. You've modified five files, but three relate to the bug fix and two to the new feature. The staging area lets you commit these separately, keeping your project history clean and logical.

Without staging, you'd have to commit everything at once, creating messy commits that mix unrelated changes.

Using git add

The git add command moves changes from the working directory to the staging area.

Stage a Single File:

git add index.html

Stage Multiple Specific Files:

git add index.html styles.css

Stage All Changed Files:

git add .

The dot (.) means "everything in the current directory and subdirectories."

Stage All Files of a Certain Type:

git add *.js

This stages all JavaScript files.

Stage Files Interactively:

git add -p

This shows you each change and asks if you want to stage it, giving you fine-grained control.

After staging, check status again:

git status

Output shows:

On branch main
Changes to be committed:
  modified:   index.html

The file is now staged and ready to commit. It's in your shopping cart, waiting for checkout.

The Repository (Committed State)

When you commit, Git takes everything in the staging area and creates a permanent snapshot in the repository. This snapshot gets a unique ID and becomes part of your project's history forever.

Using git commit

Basic Commit:

git commit -m "Add navigation menu to homepage"

The -m flag lets you include a message directly in the command. The message should briefly describe what changed and why.

Commit with Detailed Message:

If you need to write a longer message, omit the -m flag:

git commit

Git opens your configured text editor where you can write:

Add navigation menu to homepage

- Created responsive navigation bar
- Added links to all main sections
- Implemented mobile hamburger menu
- Fixed header positioning issues

The first line is the summary (50 characters or less), followed by a blank line, then detailed explanation if needed.

Staging and Committing in One Step:

For files already tracked by Git, you can skip staging:

git commit -am "Update contact page"

The -a flag automatically stages all modified tracked files before committing. Be careful with this—it's easy to accidentally commit changes you didn't intend to.

Note: This shortcut only works for files Git is already tracking. New files must be explicitly added with git add.

Complete Workflow Example

Let's walk through a complete example building a simple website:

Step 1: Check Status

git status

Output shows you're on the main branch with a clean working directory—no changes.

Step 2: Create New Files

echo "Welcome to my site" > index.html
echo "body { margin: 0; }" > styles.css

You've created two files in your working directory.

Step 3: Check Status Again

git status

Output shows:

Untracked files:
  index.html
  styles.css

These files exist but Git isn't watching them yet. They're in the working directory but not staged or committed.

Step 4: Stage the HTML File

git add index.html

Step 5: Check Status

git status

Output shows:

Changes to be committed:
  new file:   index.html

Untracked files:
  styles.css

Only index.html is staged. The CSS file is still untracked.

Step 6: Commit the HTML

git commit -m "Add homepage structure"

Git creates a commit containing only index.html. This commit is now permanently in your repository's history.

Step 7: Stage and Commit the CSS

git add styles.css
git commit -m "Add basic CSS styling"

Now you have two separate commits, each focused on one aspect of the work. This makes your history clear and meaningful.

Understanding File States

At any moment, your files can be in various states. Let's clarify each:

Untracked - Git doesn't know about the file. It exists in your working directory but has never been staged or committed. New files start as untracked.

Unmodified - The file is tracked by Git and hasn't changed since the last commit. Git has no work to do with this file.

Modified - The file has changed since the last commit but hasn't been staged. Changes exist only in your working directory.

Staged - The file's changes are marked for inclusion in the next commit. The file is in the staging area.

The Lifecycle

Here's how files typically move through states:

  1. Create a new file → Untracked
  2. Run git addStaged (new file)
  3. Run git commitUnmodified (committed)
  4. Edit the file → Modified
  5. Run git addStaged
  6. Run git commitUnmodified (committed)

This cycle repeats throughout your project's development.

Unstaging Files

What if you stage something by mistake? You can unstage it without losing your changes.

Unstage a Specific File:

git restore --staged index.html

This moves the file back to the working directory (modified but not staged). Your changes remain intact.

Unstage Everything:

git restore --staged .

Older Git Versions:

If you have an older Git version, the command might be:

git reset HEAD index.html

Git's status message usually tells you which command to use for your version.

Discarding Changes

Be careful with this section—these operations can permanently delete your work.

Discard Changes in Working Directory:

git restore index.html

This reverts the file to how it looked in the last commit. Your modifications are permanently lost.

Discard All Changes:

git restore .

This reverts all modified files to their last committed state. Again, this is permanent—you cannot recover discarded changes.

Always double-check before discarding changes. When in doubt, commit or stash your work first.

Viewing Changes

Before staging or committing, it's wise to review what changed.

View Unstaged Changes:

git diff

This shows line-by-line differences between your working directory and the last commit. Red lines were removed, green lines were added.

View Staged Changes:

git diff --staged

This shows what's in the staging area—changes that will go into the next commit.

View Specific File:

git diff index.html

These commands help you understand exactly what you're about to commit.

Why This Workflow Matters

The three-state workflow provides critical benefits:

Selective Commits

You can work on multiple features simultaneously but commit them separately, keeping your history clean and logical.

Review Before Committing

Staging forces you to review changes before committing. You might catch mistakes or realize you want to split changes into multiple commits.

Flexibility

You can stage some changes, continue working, then commit what you staged without committing your newer work. This flexibility is invaluable for complex projects.

Safety Net

Uncommitted changes are vulnerable. The staging and committing process ensures your work is protected in Git's database.

Common Patterns

Pattern 1: Feature Development

# Make changes to multiple files
git add feature-related-file1.js
git add feature-related-file2.js
git commit -m "Implement user authentication"
# Continue working on other changes without committing them yet

Pattern 2: Bug Fix

# Fix a bug
git add buggy-file.js
git commit -m "Fix null pointer exception in login"
# Other modified files remain uncommitted

Pattern 3: Checkpoint Commits

# After finishing a logical chunk of work
git add .
git commit -m "Complete navigation component"
# Creates a safe restore point

Best Practices

Commit Often

Small, frequent commits are better than large, infrequent ones. Each commit should represent one logical change.

Review Before Staging

Use git diff to review your changes before running git add. Catch errors early.

Stage Selectively

Don't just run git add . blindly. Think about what belongs together in a commit.

Write Good Commit Messages

Your future self will thank you. Describe what changed and why, not how (the code shows how).

Don't Commit Half-Broken Code

Each commit should leave the project in a working state when possible. This makes debugging with git bisect easier later.

Use .gitignore

Don't stage files that shouldn't be tracked (build artifacts, dependencies, environment files). Use .gitignore to automatically exclude them.

Troubleshooting Common Issues

Accidentally Staged the Wrong File

Use git restore --staged filename to unstage it.

Made a Commit Too Early

You can amend the last commit:

git commit --amend -m "Updated commit message"

Or add forgotten changes:

git add forgotten-file.js
git commit --amend --no-edit

Want to See What's Staged

Use git diff --staged to review staged changes before committing.

Confused About File States

Run git status frequently. It's your dashboard showing where everything is.

Visualizing with git status

The git status command is your best friend. It clearly shows which state each file is in:

On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes)
        modified:   styles.css

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        script.js

This output tells you:

  • index.html is staged (ready to commit)
  • styles.css is modified but not staged
  • script.js is untracked (new file)

Git even suggests the commands to use next. Always read the status output carefully.

Summary

The three-state workflow—working directory, staging area, and repository—gives you precise control over your project's history. While it adds an extra step compared to simple "save" operations, this staging area is what makes Git powerful and flexible.

Understanding these states transforms you from someone who just uses Git to someone who leverages it effectively. You can now craft meaningful commits, separate concerns, and maintain a clean project history that tells the story of your development journey.

In the next lesson, we'll explore viewing your commit history, navigating through past snapshots, and understanding the timeline of your project's evolution. The commits you create using this three-state workflow become the foundation of that history.