28  28. Your First Repository: init, status, add, commit

On this page you turn a folder into a Git repository and save your first snapshots. You’ll learn the four commands you will type more than any others: git init, git status, git add, and git commit.

Before you start, make sure Git is installed and configured (see Installing and Configuring Git).

28.1 The three areas

Git thinks of your project in three areas:

  WORKING DIRECTORY               STAGING AREA                  REPOSITORY (.git)
  the files you see     ------>   the changes you      ------>  the saved commits
  and edit               git add  picked for the     git commit (the history)
                                  next commit
  • The working directory is your normal project folder. You edit files here with any text editor.
  • The staging area (also called the index) is a waiting area for the changes you want in your next commit.
  • The repository holds the commits: the snapshots you’ve saved. It lives in the hidden .git folder.

An analogy: the staging area is a shopping cart. You put items in the cart (git add), you can take some out again, and nothing is final until you check out (git commit). The cart lets you commit some of your changes and leave others for later. For example, you can commit a finished fix to README.md while a half-done change to index.html waits for another commit.

28.2 Where to keep your projects

Don’t keep code projects in Documents or Desktop, or in any folder that Dropbox, OneDrive, iCloud or Google Drive syncs. On many computers Documents and Desktop are synced without you knowing: Windows often backs them up to OneDrive, and macOS can store them in iCloud. A folder such as ~/projects, directly in your home folder, isn’t synced by any of them unless you set that up. GitHub will be your backup: every commit you push is stored there.

A sync service uploads every file in the folder, every time it changes. That causes problems for code projects:

  • Too many files. A web project’s node_modules and .next folders hold tens of thousands of files that change whenever you install packages or run the app. The service keeps uploading them: installs get slow, and your cloud storage fills up.
  • Locked files. While the service uploads a file, it can lock it, so the development server or npm install fails with strange file errors.
  • A broken repository. The service copies the hidden .git folder one file at a time. If two computers change it, you can get “conflicted copy” files or a corrupted repository. To move work between computers, push and pull (see Cloning and Pulling).
  • Secrets in the cloud. .gitignore keeps files like .env.local (your API keys) out of GitHub, but the sync service uploads them anyway.

To check whether a folder is synced:

Open System Settings, click your name at the top of the sidebar, then iCloud, then Drive (iCloud Drive on some versions). If Desktop & Documents Folders is on, iCloud syncs Desktop and Documents. In Finder, those folders then appear under iCloud in the sidebar.

In File Explorer, look at the Status column and the address bar. Files in a folder that OneDrive syncs show OneDrive’s status icons (a cloud or a green check mark), and the folder’s path often contains OneDrive, for example C:\Users\YOUR-NAME\OneDrive\Documents. OneDrive’s settings (Settings → Sync and back up → Manage back up) show which folders it backs up.

Dropbox can be told to ignore a folder, but a folder outside Dropbox is simpler.

28.3 Get the practice project

Keep all your code projects in one folder named projects in your home folder. Create it in the terminal (-p: no error if it already exists):

mkdir -p ~/projects

Then download the Git practice project (zip) and unzip it into that folder:

In Finder, double-click the zip file in Downloads: macOS unzips it into a folder named git-tutorial-project. Press Cmd+Shift+H to open your home folder in a new Finder window, open projects, and drag the git-tutorial-project folder into it.

In File Explorer, right-click the zip file in Downloads and choose Extract All…. As the destination, type C:\Users\YOUR-NAME\projects (with your Windows user name) and click Extract.

You get this small website project:

git-tutorial-project/
├── .gitignore        <- hidden file: tells Git which files to ignore (see the .gitignore chapter)
├── README.md
├── css/
│   └── style.css
├── docs/             <- an empty folder
└── src/
    └── index.html

Open a terminal and move into the project folder:

cd ~/projects/git-tutorial-project

28.4 Step 1: git init creates the repository

git init

Output:

Initialized empty Git repository in /Users/maria/projects/git-tutorial-project/.git/

git init creates the hidden .git folder, and from now on this folder is a repository. You run git init once per project, never again. Check that .git is there with ls -a:

ls -a

Output:

.  ..  .git  .gitignore  README.md  css  docs  src

(Git Bash adds a / after folder names, such as .git/ and css/.)

Run git init in the project folder, not your home folder

Always cd into the project folder first. Running git init in your home directory turns your whole home folder (Desktop, Documents, …) into one giant repository. If you ever do that by mistake, see Question 16 below.

28.5 Step 2: git status tells you what’s going on

git status is the command you’ll use most. Run it whenever you’re unsure what state your project is in.

git status

Output:

On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    .gitignore
    README.md
    css/
    src/

nothing added to commit but untracked files present (use "git add" to track)

How to read it:

  • On branch main: main is the name of your project’s main line of history (branches come later, in Branches and Merging).
  • No commits yet: no snapshots have been saved.
  • Untracked files: Git sees these files, but isn’t tracking them yet.
  • The lines in parentheses are hints that tell you what to do next.
  • docs/ is missing because it’s empty. Git does not track empty folders (more below).

28.6 Step 3: git add puts changes in the staging area

Add one file:

git add README.md
git status

Output:

On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    .gitignore
    css/
    src/

README.md moved to Changes to be committed: it’s in the staging area. You can list several files (git add README.md src/index.html), or add everything at once with ., which means “this folder and everything in it”:

git add .
git status

Output:

On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   .gitignore
    new file:   README.md
    new file:   css/style.css
    new file:   src/index.html

On Windows, git add may also print warnings such as warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it. They’re about invisible line-ending characters and are harmless (see Installing and Configuring Git).

Check before you add everything

git add . stages every change in the folder that isn’t ignored. Run git status first, so you don’t commit something you didn’t mean to (such as a file with a password; see .gitignore and Keeping Secrets Out of Git).

28.7 Step 4: git commit saves the snapshot

git commit -m "Add starter files for portfolio site"

Output:

[main (root-commit) ffd1f1f] Add starter files for portfolio site
 4 files changed, 39 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 README.md
 create mode 100644 css/style.css
 create mode 100644 src/index.html
  • -m stands for message: the text in quotes describes the commit.
  • main is the branch; root-commit means this is the first commit.
  • ffd1f1f is the start of the commit’s ID. Yours will be different, because the ID depends on your name, the date, and the time.
  • 4 files changed, 39 insertions(+): four new files with 39 lines in total. (create mode 100644 just means “new regular file”; you can ignore it.)

If you forget -m, Git opens your text editor so you can type the message. Type it, save, and close the editor (in nano: Ctrl+O, Enter, Ctrl+X).

Now the working directory matches the last commit:

git status

Output:

On branch main
nothing to commit, working tree clean

28.8 Step 5: edit, add, commit (the everyday loop)

Add a line to the end of README.md (in your text editor, or with >>, which appends to a file):

echo "It will have a home page and a contact page." >> README.md
git status

Output:

On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

Git noticed that a tracked file was modified. Stage it and commit:

git add README.md
git commit -m "Describe planned pages in README"

Output:

[main b90f840] Describe planned pages in README
 1 file changed, 1 insertion(+)

Your project now has two snapshots. git log --oneline lists them, newest first (the next page covers history in detail):

git log --oneline

Output:

b90f840 (HEAD -> main) Describe planned pages in README
ffd1f1f Add starter files for portfolio site

This is the loop you’ll repeat all day:

edit files  -->  git status  -->  git add  -->  git commit  -->  (repeat)

28.9 Writing good commit messages

Your future self (and anyone else who reads the history) will rely on these messages.

  • Write a short summary, about 50 characters or less.
  • Start with a verb in the imperative: “Add”, “Fix”, “Update”, “Remove”. A handy test: the message should complete the sentence “If applied, this commit will …”.
  • Say what changed (and why, if it isn’t obvious).
  • Make each commit one logical change, and commit often.
Good Bad
Add contact form to home page stuff
Fix broken link to style.css changes
Update README with setup steps asdf

28.10 Git doesn’t track empty folders

The empty docs/ folder never appeared in git status and isn’t in the commit. Git tracks files; a folder is included only when it contains at least one tracked file. If you want to keep an empty folder in a repository, the usual trick is to put an empty placeholder file in it. Many people name it .gitkeep (a convention, not a Git feature):

touch docs/.gitkeep

After this, git status lists docs/ as untracked, and you can add and commit it like any other file.

  • git add -A stages all changes in the whole repository, even when you are in a subfolder. git add . stages the changes in the current folder and below. From the top folder of the repository they do the same thing.
  • git commit -a -m "message" (or git commit -am "message") stages every modified or deleted tracked file and commits in one step. It does not include new (untracked) files, which still need git add.

These save typing, but they also make it easier to commit something by accident. While you’re learning, git status, git add, git commit is the safer habit.

main is a branch: a name that points to the newest commit in a line of history. HEAD means “where you are now”. HEAD -> main says you are on the main branch, and that branch points to commit b90f840. When you commit, main moves forward to the new commit, and HEAD moves with it.

Practice Questions

Easy

Question 1 · Multiple choice

What does git init do?

  1. Downloads a project from GitHub
  2. Creates a new repository by adding a hidden .git folder to the current folder
  3. Saves a snapshot of all files
  4. Installs Git on your computer

b. git init turns the current folder into a repository by creating the hidden .git folder. Downloading a project is git clone (a), saving a snapshot is git commit (c), and git init doesn’t install anything (d).

Question 2 · Matching

Match each command with what it does.

Command What it does
1. git init A. saves the staged changes as a new commit
2. git status B. lists the commits, one per line
3. git add README.md C. turns the current folder into a repository
4. git commit -m "..." D. shows which files are untracked, modified, or staged
5. git log --oneline E. puts the changes in README.md into the staging area

1 → C, 2 → D, 3 → E, 4 → A, 5 → B.

Question 3 · Short answer

Name Git’s three areas and say in a few words what each one holds.

  • Working directory: the files you see and edit.
  • Staging area (index): the changes you’ve chosen for the next commit.
  • Repository: the saved commits (the history), stored in .git.

Question 4 · True or false

You should run git init every time you start working on your project.

False. git init is run once, to create the repository. After that you just cd into the folder and use git status, git add, and git commit.

Question 5 · Fill in the blank

In git add ., the . means ________.

The current folder (and everything inside it). So git add . stages all changes in the current folder and its subfolders, except ignored files.

Question 6 · True or false

Git tracks empty folders, so an empty docs/ folder is included in your first commit.

False. Git tracks files, not folders. An empty folder is never committed. To keep it, put a placeholder file in it (commonly named .gitkeep) and commit that file.

Medium

Question 7 · Predict the output

Maria’s working tree is clean. She creates a new file with touch contact.html and runs git status. Which section of the output lists contact.html?

Untracked files. The file is new, and Git hasn’t been told to track it yet. The output ends with nothing added to commit but untracked files present (use "git add" to track).

Question 8 · Write the command

Write the commands to stage only README.md and css/style.css and then commit them with the message Update README and page styles.

git add README.md css/style.css
git commit -m "Update README and page styles"

Question 9 · Read the output

Which files will be included if Maria runs git commit -m "Update site" now?

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

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   src/index.html

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

Only README.md, because it is the only file under Changes to be committed (the staging area). src/index.html is modified but not staged, and notes.txt is untracked. Neither is included unless she runs git add on them first.

Question 10 · Multiple choice

Which commit message is the best?

  1. updates
  2. I changed some things in the CSS file because it looked bad
  3. Fix overlapping menu on small screens
  4. asdfgh

c. It is short, starts with an imperative verb, and says what changed. (a) and (d) say nothing useful. (b) is long, vague (“some things”), and not written in the imperative style.

Question 11 · Read the output

Explain each part of this output:

[main (root-commit) ffd1f1f] Add starter files for portfolio site
 4 files changed, 39 insertions(+)
  • main: the branch the commit was made on.
  • root-commit: this is the first commit in the repository.
  • ffd1f1f: the start of the new commit’s unique ID.
  • Add starter files for portfolio site: the commit message.
  • 4 files changed, 39 insertions(+): the commit added four files containing 39 lines in total.

Question 12 · Scenario

Maria finished a fix in README.md but is halfway through a change in src/index.html. She wants to commit only the README fix. What should she type?

git add README.md
git commit -m "Fix typo in README"

Because only README.md is staged, the commit contains only the README fix. The change to src/index.html stays in the working directory for a later commit. This is exactly what the staging area is for. (Avoid git add . here, because it would stage both files.)

Question 13 · Short answer

What happens if you type git commit without -m "..."?

Git opens your configured text editor (for example nano) so you can type the commit message. When you save and close the editor, the commit is created. (If you close it without writing a message, Git cancels the commit.)

Hard

Question 14 · Find the bug

Maria created contact.html and typed:

git commit -m "Add contact page"

Git printed a status listing contact.html under Untracked files, ending with:

nothing added to commit but untracked files present (use "git add" to track)

What went wrong, and how does she fix it?

She skipped the staging step. git commit only saves what’s in the staging area, and contact.html was never added. Fix:

git add contact.html
git commit -m "Add contact page"

Question 15 · Find the bug

Sam opens Git Bash and types git status. He gets:

fatal: not a git repository (or any of the parent directories): .git

Give two possible reasons and how to fix each one.

  1. He is in the wrong folder. A new terminal starts in the home directory, not in the project. Fix: cd into the project folder (for example cd ~/projects/git-tutorial-project) and run git status again.
  2. The folder isn’t a repository yet. Fix: cd into the project folder and run git init (only once).

pwd and ls -a help him check where he is and whether a .git folder exists.

Question 16 · Scenario

Sam accidentally ran git init in his home directory. Now git status lists Desktop/, Documents/, Downloads/ and more as untracked. What happened, and how can he undo it? What must he be careful about?

git init turned his whole home directory into a repository by creating ~/.git. To undo it, he deletes only that hidden folder:

rm -rf ~/.git

He must type this exactly: rm -rf deletes without asking and there is no trash can. Deleting ~/.git removes only the accidental repository; his files are not touched. (If he had already been using a real repository directly in his home folder, its history would be lost too. That’s one more reason to keep each project in its own folder.)

Question 17 · Long answer

Why does Git have a staging area instead of committing every change automatically? Give an example where it helps.

The staging area lets you decide exactly what goes into each commit, so every commit can be one clean, logical change with a clear message. Example: you fixed a typo in README.md and are halfway through redesigning src/index.html. You stage and commit only README.md (“Fix typo in README”), and the unfinished redesign stays out of the history until it works. It also gives you a chance to review (with git status) before saving, and to leave out files that should never be committed.

Question 18 · Scenario

Maria committed her whole project, including an empty images/ folder. Later she copies the repository to another computer and the images/ folder is missing. Explain why, and how she could have kept the folder.

Git doesn’t track empty folders, so images/ was never part of any commit. She could have created a placeholder file in it (for example touch images/.gitkeep), then run git add images/.gitkeep and committed. A folder that contains a tracked file is recreated wherever the repository is copied.

Question 19 · Predict the output

Maria adds the line line A to the end of README.md and runs git add README.md. Then she adds another line, line B, and runs git commit -m "Add line A" (without running git add again). Which of the two lines are in the commit? What will git status show afterwards?

Only line A is in the commit. git add stages the file as it is at that moment; later edits are not staged automatically. Before the commit, git status would even list README.md twice: under “Changes to be committed” and under “Changes not staged for commit”. After the commit, git status shows README.md as modified under “Changes not staged for commit”, because line B is still only in the working directory. She needs another git add and git commit to save it.

Question 20 · Scenario

Sam keeps his projects in Documents, which OneDrive syncs. “It’s a free backup,” he says. Give three problems this can cause for a web project, and say where he should keep it instead and what backs it up.

Any three of:

  1. OneDrive keeps uploading the tens of thousands of files in node_modules and .next: installs get slow and his cloud storage fills up.
  2. OneDrive can lock files while it uploads them, so npm install or the development server fails with strange file errors.
  3. If he uses two computers, OneDrive copies the .git folder file by file, which can create conflicted copies or a corrupted repository.
  4. OneDrive uploads .env.local with his secret keys, even though .gitignore keeps it off GitHub.

He should keep the project in a folder that isn’t synced, such as ~/projects. GitHub is the backup: every commit he pushes is stored there.

Challenge

Question 21 · Hands-on

Create a brand-new repository from scratch: make a folder named recipes, turn it into a repository, and make three commits (for example: add README.md; add pancakes.txt; add a line to pancakes.txt). Use git status before every git add and git commit. Finish with git log --oneline.

One possible solution:

cd ~/projects
mkdir recipes
cd recipes
git init
echo "# My recipes" > README.md
git status
git add README.md
git commit -m "Add README"
echo "Pancakes: flour, milk, eggs" > pancakes.txt
git status
git add pancakes.txt
git commit -m "Add pancake recipe"
echo "Cook 2 minutes per side" >> pancakes.txt
git status
git add pancakes.txt
git commit -m "Add cooking time to pancake recipe"
git log --oneline

git log --oneline should list three commits, newest first, with your own commit IDs.

Question 22 · Hands-on

In the practice project, make Git keep the empty docs/ folder. Use git status to check each step, and finish with git log --oneline.

cd ~/projects/git-tutorial-project
touch docs/.gitkeep
git status
git add docs/.gitkeep
git commit -m "Keep empty docs folder"
git log --oneline

After touch, git status lists docs/ under Untracked files. The commit output includes create mode 100644 docs/.gitkeep, and the new commit appears at the top of git log --oneline.

Question 23 · Hands-on

Starting from a clean working tree, make git status show all three sections at once: “Changes to be committed”, “Changes not staged for commit”, and “Untracked files”. Write down the commands you used and explain why each file ended up in its section. Then commit only the staged change.

One possible solution:

echo "More details soon." >> README.md
git add README.md
echo "/* footer styles */" >> css/style.css
touch todo.txt
git status
git commit -m "Add note to README"
  • README.md is under Changes to be committed because it was added.
  • css/style.css is under Changes not staged for commit because it is tracked and was modified, but not added.
  • todo.txt is under Untracked files because Git has never tracked it.

The commit contains only the README change. Afterwards git status still shows the other two files.

© 2025-2026 Y. Rosenthal. All rights reserved.