Skip to main content
    Courses/Git/Git Basics: Clone, Add, Commit

    Lesson 2 • Beginner

    Git Basics: Clone, Add, Commit 🌿

    By the end of this lesson you'll be able to run the everyday Git workflow with confidence — clone a project, check its status, stage and commit your changes, read the history and diffs, and keep junk out of your repo with .gitignore.

    What You'll Learn in This Lesson

    • Clone an existing repository with git clone
    • Read your working state with git status
    • Stage changes with git add (one file, ., and -A)
    • Save snapshots with clear git commit -m messages
    • Inspect history with git log --oneline --graph
    • Compare changes with git diff (working vs staged)

    1️⃣ git clone — Download a Project

    git clone downloads an entire repository — every file, the full history, and all branches — from GitHub (or any remote server) onto your machine. It's how you start working on a project that already exists. Read this worked example, then try it for real on a public repo.

    Worked example: git clone
    # git clone copies an entire repository (files, history, and
    # all branches) from a remote server down to your machine.
    git clone https://github.com/user/project.git
    
    # Clone into a custom folder name instead of "project"
    git clone https://github.com/user/project.git my-folder
    
    # After cloning, the remote connection "origin" is already set up
    cd project
    git remote -v
    Output
    Cloning into 'project'...
    remote: Enumerating objects: 156, done.
    remote: Counting objects: 100% (156/156), done.
    remote: Compressing objects: 100% (98/98), done.
    Receiving objects: 100% (156/156), 2.40 MiB | 4.10 MiB/s, done.
    Resolving deltas: 100% (54/54), done.
    
    origin  https://github.com/user/project.git (fetch)
    origin  https://github.com/user/project.git (push)
    Run these commands in your own terminal to clone a real public repository.

    2️⃣ git status — What Has Changed?

    git status is the command you'll run most often. It tells you which files you've changed, which are staged (ready to commit), and which are untracked (brand-new files Git isn't watching yet). When you're unsure what Git is about to do, run git status first — every time.

    Worked example: git status
    # git status is the command you'll run most. It answers:
    # "What have I changed, and what is staged for the next commit?"
    git status
    
    # Tip: the short format is faster to scan once you know it.
    # M = modified, A = added, ?? = untracked (Git isn't tracking it yet)
    git status --short
    Output
    On branch main
    Your branch is up to date with 'origin/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)
            modified:   style.css
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            notes.txt
    Edit a file in any Git repo, then run these in your own terminal.

    3️⃣ git add & git commit — The Daily Loop

    The add-commit cycle is the heartbeat of Git, and you'll repeat it dozens of times a day. Staging with git add chooses which changes go into the next snapshot; git commit -m saves that snapshot with a message. Staging separately from committing is what lets you split your work into clean, logical commits.

    Worked example: git add & git commit
    # The daily loop:  edit  ->  git add  ->  git commit.
    # "Staging" = choosing which changes go into the NEXT snapshot.
    
    # Three ways to stage:
    git add index.html        # stage ONE specific file
    git add .                 # stage everything changed in this folder & below
    git add -A                # stage everything changed in the WHOLE repo
                              #   (including deletions, even outside this folder)
    
    # Save the staged snapshot with a short, clear message:
    git commit -m "Fix navbar spacing on mobile"
    
    # Stage and commit the next change separately for a clean history:
    git add style.css
    git commit -m "Add dark mode colours"
    Output
    [main a1b2c3d] Fix navbar spacing on mobile
     1 file changed, 6 insertions(+), 2 deletions(-)
    
    [main d4e5f6g] Add dark mode colours
     1 file changed, 12 insertions(+), 1 deletion(-)
    Run these in a real Git repository in your own terminal.

    Your turn. The script below stages and commits two edited files — fill in the three blanks marked ___ using the hints, then run it.

    🎯 Your turn: stage and commit
    # 🎯 YOUR TURN — replace each ___ then run it in your terminal.
    # Scenario: you edited TWO files and want them in ONE commit.
    
    # 1) Stage BOTH changed files at once (everything in this folder)
    git ___                       # 👉 the command that stages every change ( . )
    
    # 2) Double-check what is staged before you commit
    git ___                       # 👉 the command that shows what changed
    
    # 3) Commit with a clear, present-tense message
    git commit -m "___"           # 👉 e.g. "Add contact form and validation"
    
    # ✅ Expected output (example):
    #    [main 7c3d9a1] Add contact form and validation
    #     2 files changed, 24 insertions(+), 3 deletions(-)
    Replace each ___, then run it and check your output against the expected lines in the comments.

    4️⃣ git log — Read the History

    git log shows your commits, newest first. The raw log is verbose, so almost everyone reaches for --oneline (one commit per line) and adds --graph to draw the branch and merge structure. Together they give you a quick map of how the project got to where it is.

    Worked example: git log --oneline --graph
    # git log shows the commit history, newest first.
    # The full log is verbose, so most people use --oneline:
    git log --oneline
    
    # Add --graph to draw the branch/merge structure as ASCII art:
    git log --oneline --graph
    
    # Combine flags for a readable project map:
    git log --oneline --graph --all
    Output
    d4e5f6g Add dark mode colours
    a1b2c3d Fix navbar spacing on mobile
    x9y8z7w Add user profile page
    m3n4o5p Set up React Router
    j7k8l9q Initial commit
    
    *   9f2e1c8 Merge branch 'feature/profile'
    |\
    | * x9y8z7w Add user profile page
    |/
    * m3n4o5p Set up React Router
    * j7k8l9q Initial commit
    Run these in any repo with a few commits to see your own history.

    5️⃣ git diff — See Exactly What Changed

    git diff shows the actual lines you changed — red for removed, green for added. The key distinction: plain git diff shows changes you haven't staged yet, while git diff --staged shows what your next commit will contain. Reviewing the staged diff before committing is the single best habit for avoiding mistakes.

    Worked example: git diff vs git diff --staged
    # git diff shows your changes line by line:
    #   - red lines (-) were removed,  green lines (+) were added.
    
    git diff              # WORKING tree vs staged  (changes you have NOT staged)
    git diff --staged     # STAGED  vs last commit  (what the commit will contain)
    
    # Typical flow: review the diff, then stage, then review the staged diff:
    git diff              # "did I leave a debug line in?"
    git add style.css
    git diff --staged     # "yes, this is exactly what I want to commit"
    Output
    diff --git a/style.css b/style.css
    index 83db48f..f7e1a2c 100644
    --- a/style.css
    +++ b/style.css
    @@ -1,3 +1,4 @@
     body {
    -  background: white;
    +  background: #1a1a2e;
    +  color: #e0e0e0;
     }
    Edit a file, then run both commands in your own terminal to compare.

    6️⃣ .gitignore — Keep Junk Out

    A .gitignore file lists paths Git should never track — dependencies like node_modules/, build output, OS junk, and (critically) secret files like .env. Put it in your repo root, one pattern per line. Files matched here simply stop appearing in git status, so you can't commit them by accident.

    Worked example: a typical .gitignore
    # A .gitignore file lists paths Git should NEVER track.
    # Put it in the repo root. One pattern per line. Comments start with #.
    
    # Dependencies — huge, reinstallable, never commit these:
    node_modules/
    
    # Build output:
    dist/
    build/
    
    # Secrets & environment files (API keys, passwords):
    .env
    .env.local
    
    # OS / editor junk:
    .DS_Store
    *.log
    
    # Ignore everything in /tmp BUT keep one file:
    tmp/*
    !tmp/.gitkeep
    Output
    # After adding the .gitignore above, untracked junk disappears:
    $ git status --short
     M index.html
    ?? .gitignore
    
    # node_modules/, .env and *.log are no longer listed — Git is ignoring them.
    Create a .gitignore in a repo root and watch ignored files disappear from git status.

    Your turn. Finish the .gitignore below so Git stops tracking the dependencies folder, a secrets file, and log files. Fill in each ___ line.

    🎯 Your turn: write a .gitignore
    # 🎯 YOUR TURN — finish this .gitignore file.
    # You ran "git status" and saw node_modules/ and secret.env listed as untracked.
    # Stop Git from EVER tracking them.
    
    # 1) Ignore the whole dependencies folder
    ___                           # 👉 the folder name, with a trailing slash
    
    # 2) Ignore the secrets file so your API key never gets committed
    ___                           # 👉 the exact file name: secret.env
    
    # 3) Ignore every .log file anywhere in the project
    ___                           # 👉 a wildcard: *.log
    
    # ✅ Expected: after saving, "git status --short" no longer lists
    #    node_modules/, secret.env, or any .log file.
    Replace each ___ with a pattern, save the file, then re-run git status --short to confirm.

    Common Errors (and the fix)

    • Committing without staging — "nothing to commit, working tree clean" or an empty commit: editing a file does not stage it. You must run git add first, then git commit. Run git status to confirm your files are under "Changes to be committed".
    • Committing secrets or node_modules (no .gitignore): a blind git add . with no .gitignore sweeps up your .env keys and thousands of node_modules files. Add a .gitignore before your first commit. If it's too late, untrack with git rm -r --cached node_modules and rotate any leaked secret immediately.
    • Vague commit messages — "update", "fix stuff", "asdf": these tell future-you nothing when you're hunting a bug through history. Write what changed: git commit -m "Fix login redirect on expired session".
    • "Please tell me who you are": on a new machine Git needs your identity. Run git config --global user.name "Your Name" and git config --global user.email "you@example.com" once.

    Pro Tips

    • 💡 Run git status before every add and commit — it's free and saves you from staging the wrong thing.
    • 💡 Commit early, commit often. Small, focused commits are far easier to review, revert, and understand than one giant "did everything" commit.
    • 💡 Review the staged diff with git diff --staged right before you commit to catch stray debug lines.
    • 💡 Add your .gitignore first thing in a new project, before the first commit — it's much harder to remove tracked junk later.

    📋 Quick Reference

    CommandPurpose
    git clone URLDownload a repository
    git statusSee what's changed / staged / untracked
    git add fileStage one file
    git add .Stage everything in this folder & below
    git add -AStage every change in the whole repo
    git commit -m "msg"Save a snapshot
    git log --oneline --graphView compact history with branches
    git diffChanges not yet staged
    git diff --stagedChanges the next commit will contain
    .gitignoreList paths Git should never track

    Frequently Asked Questions

    Q: What's the difference between git add and git commit?

    git add stages changes — it puts them in a holding area (the 'staging area') for the next snapshot. git commit then saves everything staged as one permanent point in history with a message. Staging lets you commit only some of your changes at a time.

    Q: When should I use git add . versus git add -A?

    git add . stages changes in the current folder and everything below it. git add -A stages every change in the whole repository, including file deletions and changes outside your current folder. For a small project at the root they behave almost the same; -A is the safest 'stage absolutely everything'.

    Q: What's the difference between git diff and git diff --staged?

    git diff shows changes in your working files that you have NOT staged yet. git diff --staged (also --cached) shows what you HAVE staged — i.e. exactly what the next commit will contain. Review both before committing.

    Q: Do I commit my .gitignore file?

    Yes. The .gitignore file itself should be tracked and committed so everyone on the team ignores the same things (node_modules, .env, build output). It's one of the few config files you always want in version control.

    Q: I already committed node_modules or a secret by mistake — now what?

    Add the path to .gitignore, then stop tracking it with 'git rm -r --cached node_modules' (or the file) and commit. For a leaked secret, also rotate/revoke the key immediately — anyone who pulled the repo already has the old value, since Git keeps full history.

    Q: What makes a good commit message?

    A short imperative summary of WHAT changed and, ideally, WHY — for example 'Fix login redirect on expired session'. Aim for around 50 characters in the summary. Avoid vague messages like 'update', 'fix stuff', or 'asdf'; they're useless when you're hunting through history later.

    Mini-Challenge: Your First Solo Commit Cycle

    No blanks this time — just a brief and an outline. Run the full status → add → diff → commit → log loop yourself, then check your output against the example in the comments. This is exactly the rhythm you'll use on every project.

    🎯 Mini-Challenge: run the full loop
    # 🎯 MINI-CHALLENGE: your first solo commit cycle
    #
    # Starting point: a fresh folder with an index.html you just edited.
    #
    # 1. Check what Git currently sees (which files are changed / untracked?).
    # 2. Stage index.html (only that file — not everything).
    # 3. View the staged diff to confirm it's what you expect.
    # 4. Commit it with a clear message describing WHAT changed.
    # 5. View the history as a one-line graph to see your commit.
    #
    # ✅ Expected: git log --oneline shows your new commit at the top, e.g.
    #    b7f2c10 Build the homepage hero section
    
    # your commands here
    Work through the steps in a real repo. Aim to do it without scrolling back up.

    🎉 Lesson Complete!

    • git clone downloads a whole repo — files, history, and branches
    • git status shows what's changed, staged, and untracked — run it constantly
    • git add (file, ., -A) stages; git commit -m saves a snapshot
    • git log --oneline --graph maps your history; git diff / --staged show line-by-line changes
    • .gitignore keeps secrets, node_modules, and build junk out of your repo
    • Next lesson: Branching & Merging — work on features in isolation, then combine them

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service