Practice: Your first repo
Self-check questions
Section titled “Self-check questions”Answer each in your own words first, then open the answer to check.
Q1. Explain the three-area model (working directory, staging area, repository) to someone who has never used git. Use the manual-tracking exercise from the lesson as an analogy.
Show answer
The three-area model maps directly onto the manual-tracking exercise. The working directory is your project folder where you actually edit files (like having the file open and saving changes). The staging area is like assembling the next “version N” copy in a draft folder before you finalize it: you can stage some changes, change your mind, unstage them, edit more, then stage again. The repository is the history folder where the finalized version-N copies all live, permanently and recoverably.
Q2. A teammate runs git add . in a project that contains a node_modules/ folder (50 MB of dependencies) and an .env file (with API keys). What two things go wrong, and how would a .gitignore have prevented both?
Show answer
Two things go wrong:
- The
node_modules/folder bloats the repository (50 MB committed, then re-downloaded by everyone who clones). Performance and storage suffer; the repo becomes slow to clone. - The
.envwith API keys is now in commit history. Even if it is later removed, the keys are recoverable from history forever; they must be considered compromised and rotated.
A .gitignore containing node_modules and .env would have caused git add . to silently skip both, preventing both problems before they happened.
Q3. A developer says: “I committed a file by accident. It is in the staging area. How do I get it out?” You have not yet learned the un-stage command, but using the three-area model, where does the file need to move from and to?
Show answer
Using the three-area model, the staged file needs to move FROM the staging area BACK INTO the working directory (without losing the edits). The command for this is git restore --staged <file> or older form git reset HEAD <file>, both undo the staging without touching the file itself. We cover this in L4.
Q4. Write a .gitignore for a Python project that should ignore: compiled bytecode (any .pyc file), the virtual environment folder (venv/), editor files from VSCode (.vscode/), and a local config file with credentials (config.local.json).
Show answer
# Python compiled bytecode*.pyc
# Virtual environmentvenv/
# Editor files.vscode/
# Local config with credentialsconfig.local.jsonQ5. A new developer asks: “Why do I have to run git add AND git commit? Why isn’t it one command?” Answer in two sentences using the staging-area-as-draft mental model.
Show answer
Splitting git add and git commit into two steps lets you assemble exactly which changes belong in the next snapshot before saving it. Without the split, you would either commit every modified file (losing the ability to make separate commits for separate logical changes) or commit nothing, with no middle ground for “save these three files but hold off on the fourth one I am still working on.”
Hands-on exercise
Section titled “Hands-on exercise”Do these steps in a real terminal. Use a sandbox folder if you want to throw it away after.
- Create a folder called
git-practice.cdinto it. - Run
git init. Confirm withgit status. - Create a file called
hello.txtwith the contentsHello, git.. Save it. - Run
git status. Observe thathello.txtis listed as untracked. - Stage the file with
git add hello.txt. Rungit statusagain. Observe the change in classification. - Commit with
git commit -m "Add hello.txt". Observe the output. - Run
git status. Observe “working tree clean.” - Edit
hello.txt: add a second lineGoodbye, manual tracking.. Save. - Run
git status. Observehello.txtis now classified as modified (not untracked, because it has been tracked since the first commit). - Stage and commit the change with a fresh message.
- Create a
.gitignorecontaining the single linesecrets.txt. - Create
secrets.txtwith any content. Rungit status. Observe thatsecrets.txtdoes not appear. - Stage and commit your
.gitignore.
By the end, you have a repository with three commits and a working .gitignore. You have lived the commit cycle.
Scenario reflections
Section titled “Scenario reflections”Scenario A. A teammate creates a new project, makes a few commits, and then realizes they never created a .gitignore. Their node_modules/ folder is now in commit history. Without using any command you have not learned yet, why is this a problem, and what would you recommend they do going forward to prevent it on the next project?
Show answer
The problem with node_modules/ in history is that it bloats the repository (the 50-200 MB of dependencies gets re-downloaded on every clone, every fetch, every CI run, indefinitely). The recommendation: on every new project, create the .gitignore BEFORE the first git add, this is a one-line habit (git init && touch .gitignore && echo "node_modules" > .gitignore, or just paste in a template). For the existing project with node_modules already committed, removing it from history is non-trivial (we cover this in L4); the immediate mitigation is adding .gitignore and removing the tracked copy with git rm --cached -r node_modules/.
Scenario B. A developer is working on three unrelated changes at the same time (file A, file B, file C). They want to commit each change as a separate snapshot so the history is readable. Without using any command you have not learned yet, how does the staging area help them do this?
Show answer
The staging area lets the developer stage file A only, commit it (“Fix navigation bug”), then stage file B only, commit it (“Update docs”), then stage file C only, commit it (“Refactor parser”). The working directory had all three changes throughout, but the staging-area-as-draft mechanism let them be committed separately. Each commit is one logical change; the history reads cleanly.
Scenario C. A project has a .gitignore that contains node_modules/ (with trailing slash). A developer using a shared dependency setup has node_modules as a symlink. They run git add . and accidentally commit the symlink. Why did the .gitignore not catch it, and what is the one-character change that would have prevented the issue?
Show answer
The trailing-slash pattern (node_modules/) tells git: “match a directory called node_modules and everything inside it.” Symlinks are not directories in the filesystem sense; they are special files that point to directories. The trailing slash excludes them from matching. The one-character change is removing the trailing slash: node_modules (bare name) matches both directories AND symlinks named node_modules. This is the canonical fix and matches the gotcha from the lesson.
Flashcards
Section titled “Flashcards”Q. What command initializes a git repository?
git init. You run it once per project, in the root folder.
Q. What does `git status` do?
It reports the state of the working directory, staging area, and repository. It does not change anything. It is the most useful command for orienting yourself.
Q. What is the difference between the working directory and the staging area?
The working directory is what is on disk right now (your actual files as you edit them). The staging area is a holding space where you assemble the next snapshot before committing.
Q. How do you stage a file for the next commit?
git add <filename>. Or git add . to stage everything in the current directory (use carefully).
Q. How do you take a snapshot of staged changes?
git commit -m "your message". The message is required; git will reject empty messages.
Q. What does 'working tree clean' mean?
The working directory matches the most recent commit. There are no uncommitted changes. This is the calm state.
Q. What is `.gitignore`?
A file in the root of the repository that lists patterns git should ignore. Files matching ignored patterns will not appear in git status and will not be staged by git add ..
Q. Why use the bare name in `.gitignore` (e.g., `node_modules`) instead of the trailing-slash form (`node_modules/`)?
The bare name matches both directory and symlink forms. The trailing-slash form only matches directories, so a symlinked node_modules would slip past the pattern.
Q. What should always go in `.gitignore`?
Compiled output (build/, dist/), dependencies (node_modules/), editor files (.idea/, .vscode/), secrets (.env), and OS artifacts (.DS_Store, Thumbs.db).
Q. What is the daily commit cycle?
Edit files, then git add, then git commit, then git status (to confirm clean state). Repeat per logical chunk of work.