Day 5 — Git: init, add, commit#
Goal: Master the hands-on commands for creating repositories, staging changes, and making commits — the commands you’ll use every single day.
git init — Create a New Repository#
# Create a project directory and initialize Git:
mkdir my-project
cd my-project
git init
# Initialized empty Git repository in /home/you/my-project/.git/What git init creates#
ls -la .git/
# HEAD ← points to current branch
# config ← repository-level settings
# hooks/ ← scripts that run on events (commit, push, etc.)
# objects/ ← where Git stores file contents and commits
# refs/ ← branch and tag pointersYou never need to touch
.git/directly. Git commands manage it for you.
Configure your identity (one-time setup per machine)#
git config --global user.name "Your Full Name"
git config --global user.email "[email protected]"
# Verify:
git config --list
# user.name=Your Full Name
# [email protected]🧠 Knowledge Check#
Q1: What does git init actually do when you run it in a project folder?
- A) It uploads the folder to GitHub
- B) It creates a hidden
.gitfolder that tracks your project’s version history - C) It stages all your files for a commit
- D) It deletes all untracked files
Answer
B — git init turns a regular folder into a Git repository by creating the .git directory to store its data.
git add — Stage Changes#
git add moves changes from the working tree to the staging area (also called the “index”).
Staging specific files#
git add README.md # stage one file
git add main.py test_main.py # stage multiple files
git add src/ # stage an entire directoryStaging everything#
git add . # stage all changes in current dir and below
git add -A # stage all changes in the entire repoInteractive staging (-p / --patch)#
This lets you review and select specific changes within a file:
git add -p
# Git shows each change (hunk) and asks:
# Stage this hunk [y,n,q,a,d,s,e,?]?
# y = yes, stage this change
# n = no, skip this change
# s = split into smaller hunks
# q = quit (stop staging)Use
-pwhen: You’ve made multiple unrelated changes in one file and want to put them in separate commits.
Unstaging (removing from staging area)#
git restore --staged README.md # unstage one file
git restore --staged . # unstage everything🧠 Knowledge Check#
Q1: You made changes to 5 files, but you only want to stage main.py and utils.py for your next commit. What command(s) should you run?
- A)
git add . - B)
git add main.py utils.py - C)
git commit main.py utils.py - D)
git stage *
Answer
B — Specifying the files after git add lets you selectively stage only those files.
git commit — Save a Snapshot#
git commit creates a permanent snapshot of everything in the staging area.
Basic commit#
git commit -m "feat: add user authentication"Commit with a longer message#
git commit
# This opens your default editor (vim/nano) where you can write:
# Line 1: short summary (50 chars or less)
# Line 2: (blank)
# Line 3+: detailed explanationSet your default editor#
# Use nano (easiest for beginners):
git config --global core.editor "nano"
# Or VS Code:
git config --global core.editor "code --wait"Shortcut: add + commit in one step#
# Stage all TRACKED files and commit (skips untracked files):
git commit -am "fix: correct calculation in parser"Note:
-aonly stages files Git already knows about. New files must begit add-ed first.
Amend the last commit#
# Fix the commit message:
git commit --amend -m "feat: better commit message"
# Add a forgotten file to the last commit:
git add forgotten-file.py
git commit --amend --no-edit⚠️ Don’t amend commits that are already pushed to GitHub (unless you’re the only person using the branch).
The Full Init → Add → Commit Workflow#
Here’s a complete example from scratch:
# 1. Create a project
mkdir ~/tds-bootcamp/day-5
cd ~/tds-bootcamp/day-5
# 2. Initialize Git
git init
# 3. Create .gitignore FIRST
cat > .gitignore << 'EOF'
.venv/
__pycache__/
*.pyc
.env
EOF
# 4. Create your files
echo "# Day 5 — Git Practice" > README.md
cat > main.py << 'PYEOF'
"""Simple greeting module."""
def greet(name: str) -> str:
return f"Hello, {name}!"
if __name__ == "__main__":
print(greet("TDS"))
PYEOF
# 5. Check what Git sees
git status
# Untracked files:
# .gitignore
# README.md
# main.py
# 6. Stage everything
git add .
# 7. Verify what's staged
git status
# Changes to be committed:
# new file: .gitignore
# new file: README.md
# new file: main.py
# 8. Commit
git commit -m "feat: initial project setup"
# 9. Verify
git log --oneline
# abc1234 (HEAD -> main) feat: initial project setupMaking More Commits#
# Make a change:
cat >> main.py << 'PYEOF'
def farewell(name: str) -> str:
return f"Goodbye, {name}!"
PYEOF
# Check what changed:
git diff
# +
# +def farewell(name: str) -> str:
# + return f"Goodbye, {name}!"
# Stage and commit:
git add main.py
git commit -m "feat: add farewell function"
# Check the log:
git log --oneline
# def5678 (HEAD -> main) feat: add farewell function
# abc1234 feat: initial project setupViewing History#
# Compact history:
git log --oneline
# Detailed history:
git log
# Show what changed in each commit:
git log -p
# Show stats (files changed, insertions/deletions):
git log --stat
# Show specific commit:
git show abc1234
# Show who changed each line of a file:
git blame main.pyQ&A#
Q: What happens if I run git init in a folder that's already a Git repo?
A: Nothing bad — Git just says “Reinitialized existing Git repository.” It won’t delete your history or anything. It’s safe to run git init multiple times.
Q: What is the difference between git add . and git add -A?
A:
git add .— stages all changes in the current directory and belowgit add -A— stages all changes in the entire repository, regardless of where you are
In practice, if you’re in the root of your repo, they are the same.
Q: Can I commit without a message?
A: No — Git requires a message. If you run git commit without -m, it opens an editor for you to write one. If you close the editor without typing anything, Git aborts the commit.
Pro tip: Use git commit -m "message" for quick commits.
Q: I accidentally committed a file I shouldn't have (like .env). How do I remove it?
A:
# Remove from Git tracking (but keep the file on disk):
git rm --cached .env
# Add to .gitignore so it doesn't happen again:
echo ".env" >> .gitignore
# Commit the fix:
git add .gitignore
git commit -m "chore: remove .env from tracking"⚠️ If .env contained secrets and was pushed to GitHub, consider those secrets compromised. Rotate them.
Q: What does git commit -am do?
A: -a automatically stages all modified tracked files before committing. -m provides the message inline. Combined: -am stages modified files and commits in one step.
Important: -a does NOT stage new (untracked) files. You must git add new files explicitly.
Exercises#
Exercise 1: Create a complete project
Create a new Git repository with three files across two commits:
Solution
mkdir -p /tmp/git-init-practice
cd /tmp/git-init-practice
git init
# Commit 1: Project setup
echo "# My Tool" > README.md
echo ".venv/" > .gitignore
git add README.md .gitignore
git commit -m "feat: initial project setup"
# Commit 2: Add code
echo 'print("hello world")' > main.py
git add main.py
git commit -m "feat: add main script"
# Verify:
git log --onelineExpected log:
def5678 (HEAD -> main) feat: add main script
abc1234 feat: initial project setupExercise 2: Selective staging
Create two files, but commit them in separate commits:
cd /tmp/git-init-practice
echo "# API docs" > docs.md
echo "import sys" > utils.pySolution
# Commit only docs.md:
git add docs.md
git commit -m "docs: add API documentation"
# Commit only utils.py:
git add utils.py
git commit -m "feat: add utility functions"
# Verify:
git log --onelineEach file is in its own commit with a descriptive message.
Exercise 3: Amend a commit
Make a commit, then fix the message:
cd /tmp/git-init-practice
echo "# test" > test.py
git add test.py
git commit -m "add tset file" # oops, typo!How to fix it
git commit --amend -m "test: add test file"
git log --oneline -1
# Now shows: test: add test file--amend replaces the last commit with a corrected version.
Exercise 4: Use git diff
cd /tmp/git-init-practice
# Modify main.py:
echo 'print("goodbye world")' >> main.py
# What does git diff show?
git diffExpected diff output
diff --git a/main.py b/main.py
--- a/main.py
+++ b/main.py
@@ -1 +1,2 @@
print("hello world")
+print("goodbye world")
The + line shows what was added. Stage it and check git diff --staged to see the same diff for staged changes.
Exercise 5: MCQ
Q1: What does git init create?
- A) A new file called
git - B) A
.git/directory that stores version history - C) A GitHub repository
- D) A virtual environment
Answer
B — git init creates a hidden .git/ directory in your project. This is where Git stores all its data (commits, branches, configuration). It does NOT create a GitHub repository — that’s a separate step.
Q2: You’ve edited three files. You want to commit only one of them. What do you do?
- A)
git commit -am "message" - B)
git add specific-file.pythengit commit -m "message" - C)
git add .thengit commit -m "message" - D)
git push
Answer
B — Stage only the file you want with git add specific-file.py, then commit. Options A and C would include all modified files.
Q3: What does git restore --staged file.py do?
- A) Deletes file.py from disk
- B) Moves file.py from staging area back to working tree (unstages it)
- C) Reverts file.py to its last committed version
- D) Removes file.py from the Git repository
Answer
B — It unstages the file without changing its contents. The file still has your modifications in the working tree; it’s just no longer queued for the next commit.
Clean up:
rm -rf /tmp/git-init-practice