Skip to main content

πŸ”§ Core Git Commands and Workflow

This is the lesson you'll return to most. Here you'll build the everyday Git loop β€” check, stage, commit, review β€” learn to undo mistakes without panic, and sync your work with a remote so the rest of your team can see it.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Run the core loop: status β†’ add β†’ diff β†’ commit β†’ log
  • Read the four file states from git status output, long and short form
  • Undo safely at any stage using restore, revert, and the three modes of reset
  • Recover "lost" commits with git reflog
  • Work with remotes: remote add, push, fetch, and pull

Estimated Time: 35–45 minutes  β€’  Difficulty: Beginner–Intermediate

Hands-on: Match real-world scenarios to the exact Git command that fixes them.

In This Lesson

The Everyday Git Loop

Almost all Git work is a small, repeating cycle. Master this loop and you've mastered 90% of daily Git:

flowchart LR A[Working Directory] -->|git add| B[Staging Area] B -->|git commit| C[Local Repository] C -->|git push| D[Remote Repository] D -->|git fetch / pull| C C -->|git checkout / restore| A

You edit files (working directory), stage the ones that belong together, commit them into your local history, and eventually push them to a shared remote. To bring in others' work, you fetch or pull. Every command in this lesson is one arrow on that diagram.

The Core Commands

git status β€” where am I?

Your most-used command. It reports the current branch, what's staged, what's modified, and what's untracked:

git status        # full, friendly output
git status -s     # short, two-column form

git add β€” stage changes

Move changes into the staging area for the next commit. add handles both new and modified files:

git add index.html          # one file
git add src/                 # a whole directory
git add .                    # everything under the current directory
git add -p                   # interactively pick which hunks to stage

git add -p is a hidden gem: it lets you stage part of a file, which is how you keep commits atomic when one file holds two unrelated changes.

git diff β€” what exactly changed?

Review before you commit. Removed lines show with -, added lines with +:

git diff            # unstaged changes (working dir vs. staging)
git diff --staged   # staged changes (what the next commit will contain)
git diff HEAD       # all changes since the last commit

git commit β€” record a snapshot

git commit -m "Add user authentication feature"

# Omit -m to open your editor for a longer message:
git commit

# Stage-and-commit tracked (already-known) files in one step:
git commit -am "Fix typo on the homepage"

Remember: -am does not pick up brand-new untracked files β€” those still need an explicit git add first.

git log β€” read the history

git log                       # full history, newest first
git log --oneline             # one compact line per commit
git log --oneline --graph --decorate --all   # visual branch graph
git log --stat                # files touched + line counts
git log --author="Ada" --since="2 weeks ago"  # filter

git log --oneline output:

a1b2c3d Add contact form validation
e4f5g6h Add contact page
9i8j7k6 Fix login button on mobile

Reading File States

A tracked file moves through predictable states, and git status is your window into which state each file is in:

stateDiagram-v2 [*] --> Untracked: create file Untracked --> Staged: git add Staged --> Committed: git commit Committed --> Modified: edit file Modified --> Staged: git add Modified --> Committed: git commit -a

The four states are untracked (Git doesn't know it yet), unmodified (tracked, unchanged), modified (tracked, changed), and staged (queued for the next commit). Here's how they appear in the long and short forms of status:

$ git status
Changes to be committed:
        modified:   staged-file.txt        # staged
Changes not staged for commit:
        modified:   modified-file.txt      # modified
Untracked files:
        untracked-file.txt                 # untracked

$ git status -s
M  staged-file.txt        # left column = staging area
 M modified-file.txt      # right column = working directory
?? untracked-file.txt

πŸ’‘ Decoding short status

In -s output the left column is the staging area and the right column is the working directory. So MM means a file was staged and then modified again β€” you'd need another git add to capture the newest edits.

Undoing Changes Safely

Everyone makes mistakes; Git makes them cheap to fix. The right command depends on where the change is. This map shows which command targets which area:

Which undo command targets which area git restore affects the working directory, git restore --staged affects the staging area, reset moves the branch pointer, and revert adds a new commit. Working Dir git restore <file> Staging Area git restore --staged Repository git reset (moves HEAD) git revert (new commit) Pick the command that matches where the change lives.
Figure 1 β€” Match the undo command to the area holding the change you regret.

Unstage a file (keep the edits)

git restore --staged report.txt   # modern
git reset HEAD report.txt          # older equivalent

Discard working-directory edits (destructive)

git restore report.txt

⚠️ This one cannot be undone

git restore <file> throws away uncommitted changes permanently β€” Git has no record of them to recover. Double-check the filename before you press Enter.

Amend the last commit

git commit --amend               # edit message and/or add staged changes
git commit --amend --no-edit     # keep the message, just add changes

Only amend commits you haven't pushed to a shared branch β€” amending rewrites history.

Revert vs. reset

These are often confused. The key difference: revert is safe on shared history; reset is not.

CommandWhat it doesSafe on pushed commits?
git revert <hash>Adds a new commit that undoes an old one; history is preservedβœ… Yes
git reset --soft <hash>Moves HEAD back; keeps changes staged❌ No
git reset --mixed <hash>Default; moves HEAD and unstages changes❌ No
git reset --hard <hash>Moves HEAD and discards all changes❌ No β€” and destructive

Rule of thumb: to undo a commit that others may already have, use git revert. Reserve reset for local, unpushed history.

Recover "lost" commits with reflog

Ran a --hard reset and lost work? The reflog records every position HEAD has held:

git reflog                          # find the lost commit's hash
git branch recovery abc1234         # rescue it onto a new branch

As long as you haven't run garbage collection, reflog is your safety net β€” even a hard reset is usually recoverable.

Working with Remotes

A remote is a copy of your repository hosted elsewhere β€” GitHub, GitLab, Bitbucket. Remotes are how your local commits reach your team.

Connect and inspect

git remote add origin https://github.com/you/project.git
git remote -v     # list configured remotes (fetch + push URLs)

origin is just the conventional shortname for your main remote.

Push β€” send commits up

git push -u origin main   # first push: -u sets up tracking
git push                  # afterwards, this is enough

Fetch vs. pull

Both bring down remote work, but they differ in whether they touch your files:

  • git fetch downloads new commits and updates remote-tracking branches, but leaves your working files alone β€” a "look before you leap."
  • git pull is fetch + merge: it downloads and integrates into your current branch.
git fetch origin          # inspect first
git pull origin main      # fetch + merge in one step
git pull --rebase         # replay your local commits on top for a linear history

βœ… A typical collaboration flow

git clone https://github.com/team/project.git
cd project
git checkout -b feature-login     # branch for your work
# ...edit files...
git add .
git commit -m "Implement login form"
git push -u origin feature-login  # share it, then open a pull request

In most teams you don't merge to main directly β€” you push a branch and open a pull request for review. We cover branching strategies in depth in the next lesson.

Command Cheat Sheet

Keep this handy until the commands are muscle memory.

CommandWhat it does
git statusShow working directory and staging state
git add <file> / git add .Stage one file / all changes
git diff / git diff --stagedShow unstaged / staged changes
git commit -m "msg"Commit staged changes
git commit -am "msg"Stage tracked files and commit
git log --onelineCompact commit history
git restore <file>Discard working-directory changes
git restore --staged <file>Unstage a file
git commit --amendModify the last commit
git revert <hash>New commit that undoes an old one (safe)
git reset --hard <hash>Move HEAD and discard changes (local only)
git reflogHistory of HEAD β€” recover lost commits
git remote add <name> <url>Connect a remote repository
git push -u origin <branch>Push and set upstream tracking
git fetch / git pullDownload / download-and-merge remote work

Hands-on Exercise

πŸ‹οΈ Scenario β†’ command challenge

Objective: build the instinct of reaching for the right command by matching real situations to the fix.

The scenarios

  1. You edited app.js but want to throw the changes away and go back to the last commit.
  2. You ran git add secrets.env by mistake and want to unstage it (keeping the file).
  3. You just committed but forgot to include a file; you want to fold it into that same commit.
  4. A commit you already pushed broke production and must be undone without rewriting history.
  5. A git reset --hard destroyed a commit you actually needed.
πŸ’‘ Hint

Ask yourself two questions each time: where is the change (working dir, staging, or committed) and has it been pushed? Those two answers point directly at restore, restore --staged, --amend, revert, or reflog.

βœ… Solution
# 1. Discard working-directory edits
git restore app.js

# 2. Unstage but keep the file
git restore --staged secrets.env

# 3. Add the forgotten file into the last (unpushed) commit
git add forgotten.js
git commit --amend --no-edit

# 4. Undo a PUSHED commit safely, preserving history
git revert <hash>

# 5. Recover a commit destroyed by a hard reset
git reflog                 # find the hash
git branch recovery <hash> # or: git reset --hard <hash>

Notice #4 uses revert (safe on shared history) while the others act on local state. That distinction is the single most important undo skill in Git.

Quick Quiz

🎯 Check your understanding

Question 1: What's the difference between git fetch and git pull?

Question 2: You need to undo a commit that has already been pushed to a shared branch. Which command is the safe choice?

Question 3: In git status -s, what does the left column represent?

Summary & What's Next

πŸŽ‰ Key Takeaways

  • The daily loop is status β†’ add β†’ diff β†’ commit β†’ log, pushing to a remote when ready.
  • Files are untracked, unmodified, modified, or staged; git status shows which.
  • Undo by location: restore for the working dir/staging, --amend for the last local commit.
  • revert is safe on pushed history; reset is not β€” and reflog rescues "lost" commits.
  • Remotes sync via push, fetch, and pull; fetch looks, pull integrates.

πŸ“š Further Reading

πŸš€ What's Next?

You can now manage a single line of history with confidence. Next we unlock Git's superpower β€” branching β€” and the team workflows (GitHub Flow, GitFlow, trunk-based) built on top of it.

πŸŽ‰ Fluent in the basics!

The everyday commands are yours. Let's branch out.