Basic Git Commands: init, status, add, commit, log
- Create a Repository and perform the work cycle — edit, add, commit
- Read and understand the output of
git statusin every state - View the history with
git logand the changes withgit diff - Set up
.gitignorefor files that should not go into the Repository
What will we learn?
The daily work cycle with Git, command by command:
| Command | What it does |
|---|---|
git init | Creates a Repository |
git status | What is the state now? |
git add | Puts changes into Staging |
git commit | Saves a snapshot into the history |
git log | Shows the history |
git diff | Shows what changed |
And in addition: .gitignore, how to tell Git “ignore these”.
Why do we need this?
These are the commands developers run dozens of times a day. From now on, every exercise and every project in the course will be managed in Git: first because it is a professional habit, and second because in the OOP projects and in the integration project the history will save you when something breaks.
Explanation from the basics
The work cycle
1. edit files (Working Directory changes)
2. git status (see what changed)
3. git add <files> (choose what goes into the snapshot)
4. git commit -m "..." (save the snapshot)
5. repeatgit status — the most important command
git status changes nothing. It only tells you the state: what is Untracked, what is Modified, what is Staged. Golden rule: before every add and before every commit, run git status.
The Commit message
The message explains what changed and why, for whoever reads the history (including you in a month). We will go deeper into the rules in the next lesson. For now: a short sentence in English, in the imperative: "Add discount calculation", "Fix crash on empty cart".
.gitignore
Not every file should go into the Repository:
- Files that are created automatically:
__pycache__/,*.pyc. - Personal or secret information: passwords, API keys,
.envfiles. They must not reach GitHub! - Local work files: logs (
*.log), a local Database, virtual environments (venv/, we will meet them in the backend and databases topics). - System files:
.DS_Store(Mac),Thumbs.db(Windows).
A file named .gitignore in the project folder contains patterns (one line per pattern), and Git simply does not “see” files that match them.
Syntax
git init # create a repository in the current folder
git status # show the state of files
git add file.py # stage one file
git add folder/ # stage everything in a folder
git add . # stage ALL changes in the current folder (check status first!)
git commit -m "Short message" # commit staged changes with a message
git log # full history (press q to quit)
git log --oneline # compact history, one line per commit
git diff # changes NOT yet staged
git diff --staged # changes that ARE staged (will go into the commit)
git restore --staged file.py # un-stage a file (keeps your edits)An example .gitignore for a Python project:
# Python cache
__pycache__/
*.pyc
# Local data and logs
*.log
*.db
# Secrets and environments
.env
venv/
# OS files
.DS_Store
Thumbs.db# = a comment. * = “anything”. A line that ends with / = a folder.
First code example
A full work cycle, from zero. Inside kodkod6:
mkdir calculator
cd calculator
git initCreate calculator.py:
def add(a, b):
return a + bAnd now:
git status
git add calculator.py
git status
git commit -m "Add calculator with add function"
git log --onelineOutput:
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
calculator.py
nothing added to commit but untracked files present (use "git add" to track)On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: calculator.py[main (root-commit) 4e7a1c2] Add calculator with add function
1 file changed, 2 insertions(+)
create mode 100644 calculator.py4e7a1c2 (HEAD -> main) Add calculator with add functionBreaking down the code line by line
| Output | Meaning |
|---|---|
On branch main | We are on the main branch main. (Branches are an advanced topic, which we will not deal with right now.) |
No commits yet | The Repository is new, and there is no history. |
Untracked files: calculator.py | Git sees a new file, but does not track it. |
Changes to be committed: new file | After add: the file is in Staging, and will go into the next Commit. |
[main (root-commit) 4e7a1c2] | A Commit was created. root-commit = the first one in the history. 4e7a1c2 = the start of its Hash. |
1 file changed, 2 insertions(+) | A summary: one file, 2 lines were added. |
(HEAD -> main) | HEAD = “where we are now”, the last Commit on the branch main. |
Notice: git status itself suggests what to do (use "git add <file>..."). Read its hints!
Another example
A change, diff, and a second Commit. Add to calculator.py:
def subtract(a, b):
return a - bgit status
git diff
git add calculator.py
git commit -m "Add subtract function"
git loggit status:
Changes not staged for commit:
modified: calculator.pygit diff:
diff --git a/calculator.py b/calculator.py
--- a/calculator.py
+++ b/calculator.py
@@ -1,2 +1,6 @@
def add(a, b):
return a + b
+
+
+def subtract(a, b):
+ return a - bgit log:
commit 9d02b6f5e1a8c7d3b4f2e6a9c0d1e8b7f6a5c4d3 (HEAD -> main)
Author: Dana Cohen <dana@example.com>
Date: Tue Oct 6 11:20:41 2026 +0300
Add subtract function
commit 4e7a1c2b8f0d6e5a3c1b9d7f4e2a0c8b6d5f3e1a
Author: Dana Cohen <dana@example.com>
Date: Tue Oct 6 11:05:12 2026 +0300
Add calculator with add functionBreakdown:
modified:— the file is known to Git (it was in a Commit), and it changed.- In
git diff, a line that starts with+was added, a line with-was deleted, and a line with a space is context that did not change.@@ -1,2 +1,6 @@= “lines 1–2 in the old version became lines 1–6 in the new one”. git logshows from newest to oldest: the full Hash, the author, the date and the message. To leave a longgit log: theqkey.
And now .gitignore: run the code once (python -c "import calculator"), and git status will show __pycache__/ as Untracked. Create a .gitignore with __pycache__/, and git status will no longer show it. Don’t forget: git add .gitignore and a Commit. The file itself should be in the Repository.
Common mistake
Mistake 1: git add . without checking status. add . adds everything, including log files, __pycache__, and worst of all, files with passwords. First git status, first .gitignore, and only then add ..
And if you added something to Staging by mistake:
git restore --staged secrets.txtThe file leaves Staging, and the changes in it remain.
Mistake 2: a Commit without -m. git commit alone opens a text editor for the message. If you did not set core.editor, it will usually open Vim, an editor that is “hard to get out of”. If you got stuck in Vim: Esc, then type :q! and Enter (quit without saving), and then run again with -m "...".
Mistake 3: meaningless messages.
a1b2c3d fix
e4f5a6b stuff
c7d8e9f asdf
f0a1b2c finalIn a month, nobody will understand what happened in this history. Every Commit is “a letter to the future”.
Mistake 4: adding to .gitignore a file that was already committed. .gitignore affects only files that Git does not track yet. If app.log is already in the Repository, you also need to stop tracking it: git rm --cached app.log, and then a Commit.
Practice
The exercises use only what was taught in this lesson and the lessons before it. Try on your own first, and only then open the solution.
Exercise 1: A first Commit
A new folder has a file calculator.py. Write the sequence of commands that creates a Repository, checks the state, adds the file and makes a first Commit with a suitable message.
Show solution
git init
git status
git add calculator.py
git commit -m "Add calculator with add and subtract"
git statusgit init— creates a Repository.- The first
git status— shows thatcalculator.pyis Untracked. git add— moves it to the Staging Area.git commit -m— saves a snapshot with a message.git statusat the end — shows nothing to commit, working tree clean.
Exercise 2: Reading git status
Changes to be committed:
modified: calculator.py
Changes not staged for commit:
modified: README.md
Untracked files:
notes.txtFor each file — what state is it in, and what will happen to it if you now run git commit -m "Update"?
Show solution
| File | State | In the next Commit? |
|---|---|---|
calculator.py | The change is in the Staging Area | Yes |
README.md | Changed, but not added with git add | No |
notes.txt | Untracked — Git does not track it at all | No |
Only what is in the Staging Area goes into the Commit.
Exercise 3: .gitignore
A Python project has:
main.py
calculator.py
__pycache__/
secrets.txt (passwords)
app.log
README.mdWrite a suitable .gitignore file, and explain why each line is in it.
Show solution
# Python cache
__pycache__/
*.pyc
# Passwords and keys
secrets.txt
# Logs
*.log__pycache__/— files Python creates automatically. There is no reason to keep them.secrets.txt— passwords do not go into Git, ever. What goes into the history stays in it.*.log— logs change on every run and belong to the computer they ran on.
main.py, calculator.py and README.md are the project itself — they do go in.
Exercise 4: Reading git diff
-def add(a, b):
- return a - b
+def add(a, b):
+ return a + b- What do the lines that start with
-and+mean? - What is the actual change, and which Commit message suits it?
Show solution
-— a line that was there and was deleted.+— a new line that was added.- The function
addsubtracted instead of adding, and the change fixes that. A suitable message:Fix add returning a - b.
git diff shows what changed before git add — it is worth running it before every Commit, to make sure only what you intended goes in.
Exercise 5: History with git log
e91d5aa Fix VAT rounding
7b2e004 Add price calculator
a3f9c21 Initial project- Which command shows the history with one line per Commit?
- Which is the oldest Commit, and which is the latest?
- Add the function
multiplyand thendivide. How many Commits would you make, and why?
Show solution
git log --oneline.- The oldest:
a3f9c21 Initial project(at the bottom). The latest:e91d5aa Fix VAT rounding(at the top). - Two Commits — one for each function:
Add multiplyand thenAdd divide. That way every Commit is one change, and the history tells a clear story. Ifdivideturns out to be problematic, it is easy to see exactly when and what was added.
Summary
- The cycle: edit →
git status→git add→git commit -m "...". git status= “what is the state?”. Run it before every action, and read its hints.git log --oneline= history.git diff= what changed (--staged= what will go into the Commit).git add .only afterstatusand.gitignore.git restore --stagedtakes a file out of Staging..gitignore:__pycache__/, logs,.env, secrets. It goes into the Repository itself.