Git Get Started (First Repository)

Every Git project starts the same way: an ordinary folder on your computer becomes a repository the moment you run one command inside it. From that point on, Git can track every change you make, let you rewind to any earlier version, and share your work with others through services like GitHub. This lesson walks through creating your very first repository, telling Git who you are, and making your first commit — while explaining exactly what Git is doing behind the scenes.

Overview: How a Git Repository Works

A Git repository is really just a hidden database sitting inside a folder. When you run git init, Git creates a subfolder named .git that contains everything Git needs: a place to store file snapshots, a record of branches, and configuration. The folder you see (your source files) is called the working directory. Nothing you do there is tracked by Git until you explicitly tell it to.

Git moves changes through three areas:

  • Working directory — the actual files on disk that you edit.
  • Staging area (the index) — a holding area where you list exactly which changes should go into the next snapshot. This is what git add populates.
  • Repository — the permanent history stored inside .git/objects, written to by git commit.

Internally, Git stores three kinds of objects, and every one of them is identified by a SHA-1 hash computed from its content:

  • Blob — the raw contents of a single file (no filename, just bytes).
  • Tree — a snapshot of a directory: a list of filenames/modes pointing at blobs (for files) and other trees (for subdirectories).
  • Commit — a pointer to one tree (the full snapshot at that moment), plus metadata: author, committer, timestamp, commit message, and a pointer to the parent commit (or no parent, for the very first commit).

A branch, such as main, is nothing more than a small file containing a commit hash — a movable pointer. HEAD is itself usually a pointer to a branch (a "symbolic reference"), so when you commit, Git writes the new commit object and then moves the branch that HEAD points to forward to it. This is why branching and switching in Git are so fast: no files are copied, only pointers move.

Before your first commit can carry meaningful history, Git needs to know who you are — every commit permanently records an author name and email. You set this once with git config, and it’s separate from creating the repository itself.

git init vs. git clone

There are two ways to get a repository: git init creates a brand-new, empty one (what this lesson covers), while git clone copies an existing repository — history and all — from somewhere else, such as GitHub. You’ll use git clone constantly once you’re collaborating, but every repository, including the ones you clone, began life with a git init somewhere.

Syntax

git init [<directory>]
git config --global user.name "<your name>"
git config --global user.email "<your email>"
git status
git add <file>...
git commit -m "<message>"
git log
Command / Flag Meaning
git init Creates a new, empty repository in the current directory (or the given one).
git init <directory> Creates the directory if needed and initializes the repository inside it.
--initial-branch=<name> Sets the name of the first branch created by this init call (rarely needed once init.defaultBranch is configured).
git config --global Applies a setting for your whole user account, used by every repository unless overridden.
git config --local Applies a setting only to the current repository (the default when you omit a scope flag while inside a repo).
git status Shows the current branch, staged changes, unstaged changes, and untracked files.
git add <file> Copies the current content of a file into the staging area (the index).
git commit -m "..." Records everything currently staged as a new permanent snapshot, with the given message.

Examples

Example 1: Creating your first repository

mkdir hello-git
cd hello-git
git init

Output:

Initialized empty Git repository in /home/you/hello-git/.git/

Git created a new .git folder inside hello-git. The project folder itself is completely unchanged — no files were added or modified — but it is now a repository Git knows how to track. Because no commit has been made yet, the main branch doesn’t technically exist as a real pointer yet; HEAD just refers to a branch name that will be created the moment you commit.

Example 2: Setting your identity

git config --global user.name "Ada Lovelace"
git config --global user.email "ada@example.com"
git config --global init.defaultBranch main
git config --list --global

Output:

user.name=Ada Lovelace
user.email=ada@example.com
init.defaultBranch=main

These settings are stored in a plain text file at ~/.gitconfig and apply to every repository on your machine. Setting init.defaultBranch to main means every future git init will name its first branch main instead of the older default master. If you need a different name or email for one specific project (say, a work email), run the same commands with --local instead of --global from inside that repository — local settings override global ones.

Example 3: Making your first commit

echo "# Hello Git" > README.md
git status
git add README.md
git commit -m "docs: add project README"
git log --oneline

Output:

On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	README.md

nothing added to commit but untracked files present (use "git add" to track)
[main (root-commit) 3f2c1a9] docs: add project README
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
3f2c1a9 docs: add project README

The first git status shows README.md as untracked — Git sees the file but isn’t following it yet. After git add, the file’s content is staged. git commit then writes a blob for the file’s contents, a tree that records "README.md points at this blob", and a commit object pointing at that tree with no parent (it’s the root commit). Git also creates the main branch pointer for the first time here, pointing it at the new commit, and moves HEAD along with it.

How It Works Step by Step

Tracing exactly what happens across these examples:

  • git init creates .git/objects (empty, for blobs/trees/commits), .git/refs/heads (empty, for branches), and a .git/HEAD file containing ref: refs/heads/main — a pointer to a branch that doesn’t exist as a file yet.
  • git add README.md reads the file’s bytes, hashes them with SHA-1, compresses the result with zlib, and writes it as a blob object under .git/objects/<first-2-hash-chars>/<remaining-38-chars>. It then records an entry for README.md — its mode, its blob hash, and its path — in the index file, .git/index.
  • git commit reads the index, builds a tree object describing the staged snapshot, writes a commit object referencing that tree (with author/committer copied from your user.name/user.email config and the current timestamp), and finally writes the commit’s hash into .git/refs/heads/main — which is the moment the main branch starts to really exist.
  • git log simply follows the chain: read what HEAD points to, read that branch ref, read the commit object it names, and walk backward through each commit’s parent pointer.

Common Mistakes

Mistake 1: Committing without configuring identity

git commit -m "initial commit"

Output:

Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

Modern Git refuses to guess your identity for you. The fix is exactly what the error suggests — run the two git config --global commands from Example 2 once, and every future commit on the machine will carry that identity automatically.

Mistake 2: Forgetting to stage before committing

A very common beginner error is editing a file, then running git commit -m "..." directly, expecting the edit to be included:

echo "new line" >> README.md
git commit -m "update readme"

Output:

On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
	modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

The commit is rejected because nothing was staged — editing a tracked file does not automatically add it to the index. Run git add README.md (or git commit -a -m "..." to stage all already-tracked, modified files) before committing.

Mistake 3: Initializing a repository in the wrong place

Running git init in your home directory, or inside a folder that’s already a subfolder of another Git repository, creates a mess: either Git starts tracking your entire home folder, or you end up with a confusing nested repository. Always run pwd and confirm you’re in the intended project root, and run git status first if you’re unsure whether you’re already inside a repository — if it prints repository info instead of "not a git repository", you’re already inside one.

Best Practices

  • Run pwd before git init to confirm you’re in the right folder — undoing an accidental init in the wrong place just means deleting its .git folder, but it’s easy to avoid entirely.
  • Set user.name and user.email globally once, right after installing Git, so you’re never blocked mid-commit.
  • Set init.defaultBranch main globally so you never have to rename a branch from master to main after the fact.
  • Create a .gitignore file before your first commit so build artifacts, dependency folders, and secrets are never accidentally tracked in the first place.
  • Write your first commit message like any other — a short, imperative summary such as chore: initial commit or docs: add project README, following the Conventional Commits style (type: description).
  • Run git status often; it’s the cheapest way to know exactly what Git will do before you commit.

Practice Exercises

  • Exercise 1: Create a folder named my-first-repo, initialize it, and set a local identity (different name/email than your global one) using git config --local. Confirm it took effect with git config --local --list.
  • Exercise 2: Inside that repository, create three files. Stage only two of them and commit. Run git status afterward and confirm the third file still shows as untracked.
  • Exercise 3: Temporarily unset your identity with git config --global --unset user.email, then try to commit and observe the error message. Restore your email and successfully commit, to see the difference firsthand.

Summary

  • git init turns a folder into a repository by creating a hidden .git directory — it doesn’t touch or track any files by itself.
  • Git has three working areas: the working directory, the staging area (index), and the repository itself; git add and git commit move changes between them.
  • Internally, Git stores content as blobs, snapshots as trees, and history as commits, each identified by a SHA-1 hash; a branch is just a movable pointer to a commit.
  • Set user.name and user.email with git config --global before your first commit — every commit permanently embeds this identity.
  • The first commit in a repository has no parent and is what actually creates the main branch pointer.
  • git status and git log are your two most important tools for seeing exactly what state your repository is in.