Sign in
← Git: basics
10 min · easy · Lesson 2 of 6

Your first commit

init, add, commit, status, log. Why you need .gitignore.

In this lesson you'll create a repository, build your first commit, and learn to keep clutter out of history: logs, dependencies, and files with passwords. Commands for this lesson: git init, git add, git commit, git status, git log, and the .gitignore file.

Creating a repository

In an empty project folder:

git init

A hidden .git/ folder appeared. That's the repository: objects, refs, and config live inside it. If you delete it, the whole project history is gone. The project's own files stay on disk; only the versions disappear.

git init is safe to run in an already initialized folder. Git replies Reinitialized existing Git repository and leaves the history alone.

Along the way it also prints a hint about the name of the first branch (Git 2.52, shortened):

hint: Using 'master' as the name for the initial branch. This default branch name
hint: will change to "main" in Git 3.0. To configure the initial branch name
hint: to use in all of your new repositories, which will suppress this warning,
hint: call:
hint:
hint: 	git config --global init.defaultBranch <name>
...

This isn't an error. Git itself still calls the first branch master for now, and Git 3.0 plans to switch to main. The familiar main comes from GitHub and GitLab: that's the default branch for new repositories there. That's why git clone leaves you on main, while git init leaves you on master.

To make the name the same no matter where the repository came from, set it once, globally:

git config --global init.defaultBranch main

The hint will go away, and new repositories will start on main.

Who is the commit author

Every commit records the author's name and email. Git takes them from the user.name and user.email settings. Set them once before your first commit:

git config --global user.name "Ivan Ivanov"
git config --global user.email "ivan@example.com"

Skip this, and one of two things happens. Either Git refuses to commit with the error Author identity unknown and fatal: no email was given. Or it fills in your username and machine name (something like ivan@MacBook-Pro.local) and warns: Your name and email address were configured automatically. The second case is worse: the commit goes through, but with an address that means nothing to anyone. The --global flag writes the setting for every repository; without it, it only applies to the current one.

Three states of a file

In Git, a file lives in one of three places:

[ working dir ] --git add--> [ staging (index) ] --git commit--> [ repo ]

git add moves changes from the working directory into the index. git commit locks in the contents of the index as a new commit.

Why not "edit, and it commits right away": the index lets you build a commit selectively. Changed five files but only want two in the commit? Add just those two.

The basic cycle

git status                  # what changed, what's staged
git add file.md             # add one specific file
git add .                   # everything in this folder and below, check git status first
git commit -m "message"     # lock the index into a commit
git log                     # commit history
git log --oneline           # compact log
git log --oneline --graph   # with an ASCII branch graph

You'll run git status more than any other command. It shows three groups: what's staged and will go into the commit (Changes to be committed), what's modified but not staged (Changes not staged for commit), and what Git doesn't track at all (Untracked files, usually new files).

git add . is convenient, but it sweeps up everything, including .env and logs if .gitignore hasn't kept them out. So check git status before running it.

A good commit message

Your colleagues read the message, and so will you, six months from now. The minimum rules:

Don't write update, fix bug, or wip on the main branch. A log like that tells nobody anything a year from now.

.gitignore

A file at the root of the repository that lists what Git should not see.

Example:

# dependencies
node_modules/
.venv/

# build artifacts
dist/
build/
*.log

# secrets
.env
.env.local

# IDE and OS
.idea/
.DS_Store

Syntax:

The exception has a limit. If a whole folder is ignored (logs/), you can't bring a file back out of it with !logs/keep.log: Git doesn't even look inside that folder. The way that works is logs/*, followed by !logs/keep.log.

.gitignore should always be committed to the repository: the rules need to reach everyone on the team.

Check why a file is ignored with git check-ignore -v:

git check-ignore -v logs/x.log
.gitignore:2:logs/*	logs/x.log

It prints the file with the rule, the line number, and the rule itself.

Trap: a secret got into a commit

You accidentally committed .env with a password in it. Adding .env to .gitignore won't help here: .gitignore only affects untracked files. If the file is already in the repository, git status keeps showing its changes.

Remove the file from the index, but leave it on disk:

git rm --cached .env

This command stages the file's removal; the file on disk stays put. After the next commit, Git stops tracking it, and the line in .gitignore stops it from being added again.

But the file is still in earlier commits, and git log -- .env will show them. If the repository has already been pushed, treat the secret as leaked and rotate it.

Cleaning up what's already committed needs separate tools (git filter-repo, BFG). Prevention is simpler: .gitignore and a git status check before you commit.

Common mistakes

What you'll need for the tasks

The next lesson covers branches and working in parallel.

Done reading?

Mark the lesson as read to move your track progress forward.

Go through it with an AI agent

The agent explains anything unclear in plain words, gives you 2 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.

Get access for $49

Tell the agent: use MCP izi, give me lesson git-basics-02-first-commit