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
.gitfolder.
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_modulesand.nextfolders 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 installfails with strange file errors. - A broken repository. The service copies the hidden
.gitfolder 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.
.gitignorekeeps 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 ~/projectsThen 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-project28.4 Step 1: git init creates the repository
git initOutput:
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 -aOutput:
. .. .git .gitignore README.md css docs src
(Git Bash adds a / after folder names, such as .git/ and css/.)
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 statusOutput:
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:
mainis 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 statusOutput:
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 statusOutput:
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).
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
-mstands for message: the text in quotes describes the commit.mainis the branch;root-commitmeans this is the first commit.ffd1f1fis 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 100644just 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 statusOutput:
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 statusOutput:
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 --onelineOutput:
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/.gitkeepAfter this, git status lists docs/ as untracked, and you can add and commit it like any other file.
git add -A, git commit -a)
git add -Astages 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"(orgit commit -am "message") stages every modified or deleted tracked file and commits in one step. It does not include new (untracked) files, which still needgit 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.
(HEAD -> main) mean?
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?
- Downloads a project from GitHub
- Creates a new repository by adding a hidden
.gitfolder to the current folder - Saves a snapshot of all files
- Installs Git on your computer
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 |
Question 3 · Short answer
Name Git’s three areas and say in a few words what each one holds.
Question 4 · True or false
You should run git init every time you start working on your project.
Question 5 · Fill in the blank
In git add ., the . means ________.
Question 6 · True or false
Git tracks empty folders, so an empty docs/ folder is included in your first commit.
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?
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.
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
Question 10 · Multiple choice
Which commit message is the best?
updatesI changed some things in the CSS file because it looked badFix overlapping menu on small screensasdfgh
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(+)
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?
Question 13 · Short answer
What happens if you type git commit without -m "..."?
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?
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.
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?
Question 17 · Long answer
Why does Git have a staging area instead of committing every change automatically? Give an example where it helps.
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.
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?
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.
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.
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.
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.