Basic Git Commands: init, status, add, commit, log

Lesson goals
  • Create a Repository and perform the work cycle — edit, add, commit
  • Read and understand the output of git status in every state
  • View the history with git log and the changes with git diff
  • Set up .gitignore for files that should not go into the Repository

What will we learn?

The daily work cycle with Git, command by command:

CommandWhat it does
git initCreates a Repository
git statusWhat is the state now?
git addPuts changes into Staging
git commitSaves a snapshot into the history
git logShows the history
git diffShows 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. repeat

git 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, .env files. 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 init

Create calculator.py:

def add(a, b):
    return a + b

And now:

git status
git add calculator.py
git status
git commit -m "Add calculator with add function"
git log --oneline

Output:

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.py
4e7a1c2 (HEAD -> main) Add calculator with add function

Breaking down the code line by line

OutputMeaning
On branch mainWe are on the main branch main. (Branches are an advanced topic, which we will not deal with right now.)
No commits yetThe Repository is new, and there is no history.
Untracked files: calculator.pyGit sees a new file, but does not track it.
Changes to be committed: new fileAfter 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 - b
git status
git diff
git add calculator.py
git commit -m "Add subtract function"
git log

git status:

Changes not staged for commit:
        modified:   calculator.py

git 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 - b

git 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 function

Breakdown:

  • 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 log shows from newest to oldest: the full Hash, the author, the date and the message. To leave a long git log: the q key.

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.txt

The 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 final

In 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 status
  • git init — creates a Repository.
  • The first git status — shows that calculator.py is Untracked.
  • git add — moves it to the Staging Area.
  • git commit -m — saves a snapshot with a message.
  • git status at 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.txt

For each file — what state is it in, and what will happen to it if you now run git commit -m "Update"?

Show solution
FileStateIn the next Commit?
calculator.pyThe change is in the Staging AreaYes
README.mdChanged, but not added with git addNo
notes.txtUntracked — Git does not track it at allNo

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.md

Write 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
  1. What do the lines that start with - and + mean?
  2. What is the actual change, and which Commit message suits it?
Show solution
  1. - — a line that was there and was deleted. + — a new line that was added.
  2. The function add subtracted 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
  1. Which command shows the history with one line per Commit?
  2. Which is the oldest Commit, and which is the latest?
  3. Add the function multiply and then divide. How many Commits would you make, and why?
Show solution
  1. git log --oneline.
  2. The oldest: a3f9c21 Initial project (at the bottom). The latest: e91d5aa Fix VAT rounding (at the top).
  3. Two Commits — one for each function: Add multiply and then Add divide. That way every Commit is one change, and the history tells a clear story. If divide turns 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 after status and .gitignore. git restore --staged takes a file out of Staging.
  • .gitignore: __pycache__/, logs, .env, secrets. It goes into the Repository itself.

Official documentation