Getting Started with Git: Create Your First Repository

Git becomes easier when you stop treating it as a list of commands and start seeing it as a workflow. A file is created or changed in the working directory, selected through the staging area, and recorded as part of the repository history.

This guide turns that model into a complete practical exercise. You will create a small project, initialize a repository, inspect file states, prepare changes, create commits, ignore generated files, compare revisions, and verify that the repository is clean.

The goal is not to memorize commands. It is to understand what changes inside Git after every command you run.

What You Will Build

We will create a small command-line project called Task Notes. It will begin with a README file and a simple text-based task list.

The final project structure will look like this:

task-notes/
├── .gitignore
├── README.md
├── notes/
│   └── tasks.txt
└── src/
    └── app.txt

During the exercise, you will learn how to:

  • Create a new project directory.

  • Initialize a Git repository.

  • Inspect the hidden .git directory.

  • Read the output of git status.

  • Understand untracked, tracked, modified, staged, and committed states.

  • Stage individual files and groups of files.

  • Create focused commits.

  • Use git diff before committing.

  • Ignore temporary and sensitive files.

  • Remove a file from Git tracking without deleting the local copy.

  • View a compact project history.

  • Confirm that the working tree is clean.

Prerequisites

Before continuing, verify that Git is installed and that your identity is configured:

git --version
git config --get user.name
git config --get user.email

The name and email commands should return the identity you want written into new commits.

If either value is missing, configure it:

git config --global user.name "Jane Developer"
git config --global user.email "jane@example.com"

Also confirm the default initial branch name:

git config --get init.defaultBranch

If no value appears, you can initialize the project explicitly with git init -b main, or configure the global default:

git config --global init.defaultBranch main

Two Ways to Get a Git Repository

There are two main ways to begin working with a Git repository:

  1. Initialize Git inside a new or existing local project.

  2. Clone an existing repository from another location.

This guide focuses on the first method because it exposes the full workflow from an ordinary folder to the first commit.

Cloning will be covered later when remote repositories and collaboration are introduced.

Step 1: Create the Project Directory

macOS, Linux, or Git Bash

mkdir task-notes
cd task-notes

PowerShell

New-Item -ItemType Directory task-notes
Set-Location task-notes

At this moment, task-notes is only a normal directory. Git is not tracking it.

Check the current location:

pwd

In PowerShell, Get-Location provides the same information:

Get-Location

Make sure you are inside the intended project directory before initializing Git. Running git init in the wrong directory can cause Git to track files you did not intend to include.

Step 2: Initialize the Repository

Run:

git init -b main

A successful result will indicate that an empty Git repository was initialized.

If your Git version or environment does not support the -b option, run:

git init

Then verify the initial branch name:

git branch --show-current

Before the first commit, some commands may describe the branch as unborn because the branch name exists conceptually but does not yet point to a commit.

What git init Actually Does

git init creates a hidden directory named .git inside the project. This directory contains the internal data Git needs to manage the repository.

It includes structures for:

  • Objects representing project content and commits.

  • References to branches and tags.

  • Repository-specific configuration.

  • The staging area, also called the index.

  • Logs and metadata used by Git operations.

The visible project files remain in the working directory. Git stores repository metadata separately inside .git.

Inspect the Hidden Directory

On macOS, Linux, or Git Bash:

ls -la

On PowerShell:

Get-ChildItem -Force

You should see .git.

Do not manually edit or delete files inside .git unless you understand Git internals and have a recovery plan. Removing that directory removes the repository history and configuration from the working folder.

Can git init Be Run Again?

Running git init inside an existing repository normally reinitializes the repository without deleting its commit history. However, repeatedly running it is unnecessary and does not create a new nested repository unless you run it inside a separate subdirectory.

Step 3: Check the Initial Repository Status

Run:

git status

The result should show that you are on the initial branch, no commits exist yet, and there is currently nothing to commit.

git status is one of the most important daily commands. It answers questions such as:

  • Which branch am I on?

  • Which files are untracked?

  • Which tracked files were modified?

  • Which changes are staged for the next commit?

  • Is the working tree clean?

Run it frequently. It is a safe inspection command and does not modify files or repository history.

Short Status Output

Git also provides a compact form:

git status --short

At this stage it should produce no output because the directory contains no project files.

Step 4: Create the First Project File

macOS, Linux, or Git Bash

cat > README.md <<'EOF'
# Task Notes

A small project for practicing the basic Git workflow.

## Features

- Store task notes
- Organize project files
- Practice meaningful Git commits
EOF

PowerShell

@"
# Task Notes

A small project for practicing the basic Git workflow.

## Features

- Store task notes
- Organize project files
- Practice meaningful Git commits
"@ | Set-Content README.md

Now run:

git status

Git should place README.md under Untracked files.

What Is an Untracked File?

An untracked file exists in the working directory but is not yet part of Git’s tracked history.

Git notices that the file exists, but it will not automatically include it in a commit.

This is an important safety feature. A project directory may contain temporary files, logs, generated output, credentials, or personal editor settings. Git requires you to deliberately choose which new files become tracked.

The compact status output represents an untracked file with two question marks:

git status --short

Expected output:

?? README.md

Step 5: Stage the README File

Run:

git add README.md

Then inspect the status again:

git status

The file should now appear under Changes to be committed.

In short format:

A  README.md

The letter A means the file has been added to the staging area.

What git add Means

git add has two closely related roles:

  • It begins tracking a new file.

  • It updates the staged version of a tracked file.

The command does not create a commit. It prepares the exact content that the next commit will record.

A useful mental model is:

Working Directory
       |
       | git add README.md
       v
   Staging Area
       |
       | git commit
       v
Repository History

The Staging Area Is a Snapshot, Not a File List

Beginners often imagine the staging area as a list of filenames. More precisely, it contains the versions of files selected for the next commit.

This distinction matters. A file can be staged and then modified again. Git will keep the staged version for the next commit while the newer edit remains unstaged in the working directory.

You will see this behavior later in the exercise.

Step 6: Review the Staged Change

Run:

git diff --staged

You may also see the equivalent form:

git diff --cached

The output shows what the next commit will contain relative to the current commit. Because this repository has no previous commit, Git displays the entire new file as added content.

Use this command before important commits. It helps detect:

  • Accidental debug code.

  • Unrelated changes.

  • Credentials or private information.

  • Formatting noise.

  • Files that were staged by mistake.

git status tells you which paths are staged. git diff --staged shows the actual line-level content.

Step 7: Create the First Commit

Run:

git commit -m "Create project README"

The -m option provides the commit message directly on the command line.

A successful commit creates the first recorded snapshot in the repository.

Check the status:

git status

Expected result:

On branch main
nothing to commit, working tree clean

The exact wording may vary slightly by Git version, but the meaning is the same: the working directory and staging area match the latest commit.

What the First Commit Contains

The commit stores:

  • The staged version of README.md.

  • The author and committer identity.

  • The date and time.

  • The message Create project README.

  • A unique commit identifier.

  • A reference to the project snapshot.

The first commit has no parent commit because it begins the project history.

Step 8: View the Commit History

Run:

git log

The output shows the commit identifier, author, date, and message.

For a compact history:

git log --oneline

Example:

7a93c2e Create project README

Your identifier will be different.

Inspect the most recent commit and its changes:

git show --stat
git show --oneline

The first commit proves that Git is installed, configured, and able to record history correctly.

Step 9: Add Project Directories and Files

macOS, Linux, or Git Bash

mkdir -p notes src

cat > notes/tasks.txt <<'EOF'
[ ] Learn git status
[ ] Learn git add
[ ] Learn git commit
EOF

cat > src/app.txt <<'EOF'
Task Notes Application
Version: 0.1.0
EOF

PowerShell

New-Item -ItemType Directory notes, src

@"
[ ] Learn git status
[ ] Learn git add
[ ] Learn git commit
"@ | Set-Content notes/tasks.txt

@"
Task Notes Application
Version: 0.1.0
"@ | Set-Content src/app.txt

Run:

git status --short

Depending on how Git summarizes untracked directories, you may see:

?? notes/
?? src/

Git tracks files, not empty directories. A directory appears in repository history only through tracked content inside it.

Staging One File, a Directory, or the Current Tree

You can stage a specific file:

git add notes/tasks.txt

You can stage all relevant changes inside a directory:

git add src/

You can stage changes under the current directory:

git add .

You can also stage updates across the repository with:

git add -A

For a beginner, the important difference is not memorizing every variation. It is avoiding blind staging.

After a broad command such as git add ., always review:

git status
git diff --staged

Broad staging is convenient, but it can include files you did not intend to commit.

Step 10: Create a Focused Second Commit

Stage only the task list:

git add notes/tasks.txt

Check status:

git status --short

You should see the task file staged while the source directory remains untracked.

Review the staged content:

git diff --staged

Commit it:

git commit -m "Add initial learning tasks"

Now stage and commit the application description separately:

git add src/app.txt
git commit -m "Add application version information"

This creates two focused commits instead of one broad commit containing unrelated ideas.

View the history:

git log --oneline

Example:

ca52d10 Add application version information
34e8c91 Add initial learning tasks
7a93c2e Create project README

Why Focused Commits Matter

A commit should represent one understandable unit of work.

Focused commits are easier to:

  • Review.

  • Explain.

  • Test.

  • Search in history.

  • Revert when a problem occurs.

  • Move between branches later.

A single commit named update project that changes documentation, application logic, formatting, and configuration provides little useful history.

A better history explains how the project evolved through deliberate steps.

Step 11: Modify an Existing Tracked File

Add a new section to README.md.

macOS, Linux, or Git Bash

cat >> README.md <<'EOF'

## Usage

Open `notes/tasks.txt` and update the task status.
EOF

PowerShell

@"

## Usage

Open `notes/tasks.txt` and update the task status.
"@ | Add-Content README.md

Run:

git status --short

Expected result:

 M README.md

The position of the letter matters in short status output. Here, the change exists in the working directory but has not been staged.

Step 12: Inspect Unstaged Changes

Run:

git diff

Without additional options, git diff shows changes in the working directory that are not currently staged.

It compares:

Working Directory vs Staging Area

By contrast:

git diff --staged

compares:

Staging Area vs Latest Commit

This distinction is fundamental.

CommandWhat It Shows
git statusA summary of file states
git diffUnstaged line-level changes
git diff --stagedStaged line-level changes for the next commit
git log --onelineA compact commit history
git showDetails of a commit or another Git object

Step 13: See Staged and Unstaged Versions of the Same File

Stage the current README:

git add README.md

Now add one more line without staging it.

macOS, Linux, or Git Bash

echo "" >> README.md
echo "This project is used for Git practice." >> README.md

PowerShell

"" | Add-Content README.md
"This project is used for Git practice." | Add-Content README.md

Run:

git status --short

You should see:

MM README.md

The first M means a modified version is staged. The second M means the working directory contains an additional unstaged modification.

Inspect each layer:

# Shows the additional unstaged line
git diff

# Shows the earlier staged README change
git diff --staged

This demonstrates why the staging area is a snapshot. Running git add README.md captured the file as it existed at that moment. Later edits did not automatically update the staged version.

To include the latest working version in the commit, stage the file again:

git add README.md

Now:

git diff

should show no unstaged difference, while:

git diff --staged

shows the complete README update.

Commit it:

git commit -m "Document basic project usage"

Step 14: Create a .gitignore File

Projects often generate files that should not enter version control, such as logs, temporary output, local environment files, dependency directories, and editor caches.

Create some files that should remain local.

macOS, Linux, or Git Bash

mkdir logs
echo "Temporary application output" > logs/app.log
echo "APP_SECRET=do-not-commit" > .env
echo "Temporary notes" > scratch.tmp

PowerShell

New-Item -ItemType Directory logs
"Temporary application output" | Set-Content logs/app.log
"APP_SECRET=do-not-commit" | Set-Content .env
"Temporary notes" | Set-Content scratch.tmp

Check the status:

git status --short

Git should report the new untracked paths.

Create .gitignore.

macOS, Linux, or Git Bash

cat > .gitignore <<'EOF'
# Local environment secrets
.env
.env.*

# Application logs
logs/
*.log

# Temporary files
*.tmp

# Common operating-system files
.DS_Store
Thumbs.db
EOF

PowerShell

@"
# Local environment secrets
.env
.env.*

# Application logs
logs/
*.log

# Temporary files
*.tmp

# Common operating-system files
.DS_Store
Thumbs.db
"@ | Set-Content .gitignore

Run:

git status --short

The ignored files should disappear from normal status output. The .gitignore file itself remains visible because it should be committed as part of the project policy.

Stage and commit it:

git add .gitignore
git commit -m "Ignore local secrets, logs, and temporary files"

How .gitignore Patterns Work

Common patterns include:

# Ignore one exact file
.env

# Ignore every .log file
*.log

# Ignore a directory and its contents
logs/

# Ignore temporary files anywhere
*.tmp

# Ignore a file only at the repository root
/config.local.php

# Ignore everything in build except one required file
build/*
!build/.gitkeep

Blank lines are ignored, and lines beginning with # are comments unless the character is escaped.

A repository-level .gitignore should describe shared project rules. Personal editor and operating-system patterns can also be stored in a global ignore file configured for one developer.

.gitignore Does Not Affect Tracked Files

This is one of the most common beginner surprises.

If a file is already tracked, adding its name to .gitignore does not remove it from Git history or stop Git from noticing future changes.

Ignore rules apply to intentionally untracked files.

To stop tracking a file while keeping it in the working directory:

git rm --cached path/to/file

Then commit the removal from the repository index.

For a directory:

git rm -r --cached path/to/directory

Use these commands carefully and review the staged result before committing.

Debug an Ignore Rule

If you do not understand why Git is ignoring a file, use:

git check-ignore -v logs/app.log

The output identifies the ignore file and pattern responsible for the match.

To display ignored files in status output:

git status --ignored --short

This is useful when a required file appears to be missing from the repository.

Step 15: Add Another Task and Commit It

Update notes/tasks.txt.

macOS, Linux, or Git Bash

cat > notes/tasks.txt <<'EOF'
[x] Learn git status
[x] Learn git add
[x] Learn git commit
[ ] Learn Git branches
EOF

PowerShell

@"
[x] Learn git status
[x] Learn git add
[x] Learn git commit
[ ] Learn Git branches
"@ | Set-Content notes/tasks.txt

Review the change:

git status
git diff

Stage it:

git add notes/tasks.txt

Review exactly what is staged:

git diff --staged

Commit:

git commit -m "Update completed Git learning tasks"

Step 16: Rename a Tracked File

Rename src/app.txt to src/version.txt.

Use Git’s move command:

git mv src/app.txt src/version.txt

Check the status:

git status --short

Git should report a staged rename, commonly represented by R.

Commit it:

git commit -m "Rename application information file"

Does Git Store Renames Directly?

Git generally records snapshots and later detects renames by comparing content similarity. The git mv command is a convenient combination of a filesystem move and staging the related deletion and addition.

You could also rename the file with an operating-system command and then stage the changes. Git may still recognize the result as a rename.

Step 17: Delete a Tracked File

For demonstration, create and commit an obsolete file.

macOS, Linux, or Git Bash

echo "Obsolete draft" > old-notes.txt
git add old-notes.txt
git commit -m "Add temporary project draft"

PowerShell

"Obsolete draft" | Set-Content old-notes.txt
git add old-notes.txt
git commit -m "Add temporary project draft"

Now remove it through Git:

git rm old-notes.txt

This removes the working file and stages the deletion.

Review:

git status
git diff --staged

Commit:

git commit -m "Remove obsolete project draft"

Deleting a tracked file with the operating-system command is also possible, but you must stage the deletion afterward.

Understanding the File Lifecycle

A file can move through several states:

New file
   |
   v
Untracked
   |
   | git add
   v
Staged
   |
   | git commit
   v
Tracked and committed
   |
   | edit the file
   v
Tracked and modified
   |
   | git add
   v
Staged again
   |
   | git commit
   v
New committed version

A tracked file can also be deleted, renamed, or intentionally removed from the index.

StateMeaningTypical Next Action
UntrackedThe file exists but Git is not tracking itgit add or add an ignore rule
ModifiedA tracked file differs from its staged versionReview with git diff
StagedThe selected version is prepared for the next commitReview and commit
CommittedThe version is recorded in repository historyContinue development
IgnoredAn untracked path matches an ignore ruleUsually leave it local

Reading git status --short

The short format uses two status columns:

XY PATH
  • X: Difference between the latest commit and the staging area.

  • Y: Difference between the staging area and the working directory.

Common examples:

?? file.txt       Untracked file
A  file.txt       New file staged
 M file.txt       Tracked file modified but not staged
M  file.txt       Modified version staged
MM file.txt       Staged change plus another unstaged change
D  file.txt       Deletion staged
R  old -> new     Rename staged

The long status output is easier for beginners, while the short form becomes useful for fast daily inspection and scripts.

Useful Path-Specific Commands

Inspect only one file:

git status --short README.md

View unstaged changes for one file:

git diff -- README.md

View staged changes for one file:

git diff --staged -- README.md

Stage one directory:

git add notes/

The double dash separates command options from paths. It becomes especially useful when a filename resembles an option or when command syntax becomes more complex.

What git add . Can Accidentally Include

The command:

git add .

is convenient, but it may stage:

  • Debug output.

  • Temporary files.

  • Generated builds.

  • Large assets.

  • Local configuration.

  • Credentials that were not ignored.

  • Unrelated edits from another task.

Use this safe sequence:

git status
git add .
git status
git diff --staged
git commit -m "Describe the logical change"

Never assume that a broad staging command selected only the files you intended.

Do Not Commit Secrets

Before every first commit and before adding new configuration files, check for:

  • Passwords.

  • API keys.

  • Database connection strings.

  • Cloud credentials.

  • Private SSH keys.

  • Access tokens.

  • Real production environment files.

Adding .env to .gitignore helps prevent accidental tracking, but ignore rules are not a security system. Review staged content before committing.

If a real secret is committed, removing it in a later commit does not make the earlier value safe. Rotate or revoke the secret immediately, then clean history through an appropriate process.

Check the Final Repository

Run:

git status
git log --oneline --decorate

The status should report a clean working tree.

Inspect tracked files:

git ls-files

Expected tracked content:

.gitignore
README.md
notes/tasks.txt
src/version.txt

The ignored .env, logs/app.log, and scratch.tmp files should not appear.

Inspect ignored files separately:

git status --ignored --short

Inspect the history as a graph:

git log --oneline --graph --decorate --all

Because no branches have diverged yet, the graph should appear as a straight sequence of commits.

Manual Run: What Changed After Every Command?

The following manual trace summarizes the internal state of the exercise.

1. Before git init

Working directory: Exists
.git directory: Does not exist
Repository history: Does not exist
Staging area: Does not exist

2. After git init -b main

Working directory: Exists
.git directory: Created
Current branch: main
Commits: None
Staging area: Empty

3. After Creating README.md

README.md: Untracked
Staging area: Empty
Commits: None

4. After git add README.md

README.md: Tracked and staged
Staging area: Contains README.md snapshot
Commits: None

5. After the First git commit

README.md: Tracked and committed
Latest commit: Create project README
Staging area: Matches latest commit
Working tree: Clean

6. After Editing README.md

Committed version: Still preserved
Staged version: Still matches committed version
Working version: Modified
git diff: Shows the new edit

7. After Staging and Editing Again

Committed version: Original committed content
Staged version: First new edit
Working version: First new edit plus second new edit
git diff --staged: Shows first edit
git diff: Shows second edit

8. After Staging Again and Committing

Committed version: Contains both edits
Staging area: Matches latest commit
Working directory: Matches staging area
Working tree: Clean

This is the core Git model in action.

Common Beginner Mistakes

Running git init in the Wrong Directory

Always check the current path before initialization. A repository created too high in the filesystem may begin observing unrelated files.

Assuming git add Saves a Commit

git add prepares content. git commit records it in history.

Assuming git commit Includes Every Changed File

A normal commit records staged content. Unstaged and untracked changes remain outside the commit.

Using git add . Without Reviewing

Broad staging can include unrelated or sensitive files. Inspect both status and staged diff.

Creating One Large “Initial Commit” Without Inspection

Even a first commit should exclude generated files, dependencies, logs, secrets, and local configuration.

Adding a Tracked Secret to .gitignore

Ignore rules do not stop Git from tracking a file already in history.

Editing Files Inside .git

The .git directory is repository infrastructure. Treat it as internal unless you are deliberately studying Git internals.

Writing Meaningless Commit Messages

Messages such as changes, update, or fix do not explain the purpose of the snapshot.

Mixing Several Tasks in One Commit

Documentation, refactoring, bug fixes, and new features should usually be separated when they represent different logical changes.

Best Practices for Your First Repositories

  • Initialize Git at the project root.

  • Create .gitignore before staging a large project.

  • Run git status frequently.

  • Review unstaged work with git diff.

  • Review the next commit with git diff --staged.

  • Stage files intentionally.

  • Keep commits focused.

  • Use clear, action-oriented commit messages.

  • Never commit secrets.

  • End each completed task with a clean working tree when practical.

Command Reference from This Tutorial

CommandPurpose
git init -b mainInitialize a repository with the initial branch named main
git statusShow detailed working tree and staging information
git status --shortShow compact status codes
git add fileStage the current version of one file
git add .Stage relevant changes under the current directory
git diffShow unstaged changes
git diff --stagedShow changes prepared for the next commit
git commit -m "message"Create a commit from staged content
git log --onelineDisplay compact commit history
git showInspect the latest commit by default
git check-ignore -v pathExplain which ignore rule matches a path
git mv old newMove or rename a file and stage the result
git rm fileRemove a tracked file and stage the deletion
git ls-filesList files currently tracked in the index

Getting Started Checklist

Before moving to the deeper staging and commit article, confirm that you can:

  • Create a project directory.

  • Initialize a repository with git init.

  • Explain the purpose of the .git directory.

  • Recognize an untracked file.

  • Stage a specific file.

  • Create a commit with a meaningful message.

  • Distinguish git diff from git diff --staged.

  • Explain why a staged file can also have unstaged changes.

  • Create and test a .gitignore file.

  • Recognize that tracked files are not affected by new ignore rules.

  • Read common short status codes.

  • Verify that the repository has a clean working tree.

Frequently Asked Questions

Can I Run git init Inside an Existing Project?

Yes. Git can be initialized inside an existing project directory. Create a suitable .gitignore and inspect all untracked files before staging the first commit.

Does git init Upload the Project?

No. It creates a local repository. Uploading or sharing commits requires a remote repository and a later push operation.

Does Git Track Empty Directories?

No. Git tracks file content. Projects sometimes place a file such as .gitkeep in an otherwise empty directory, but that filename has no special built-in meaning to Git.

What Is the Difference Between git add and git commit?

git add prepares selected file versions in the staging area. git commit records the staged snapshot in repository history.

Why Does git diff Show Nothing After git add?

Normal git diff shows unstaged changes. After staging, use git diff --staged to inspect the content prepared for the next commit.

Can I Commit Only One File?

Yes. Stage only that file, review the staged diff, and create the commit.

Should I Always Use git add .?

No. It is convenient when all current changes belong together, but specific paths or interactive staging provide better control when several tasks are mixed.

Why Is an Ignored File Still Tracked?

It was probably committed or staged before the ignore rule was added. Ignore patterns do not affect already tracked files.

What Does “Working Tree Clean” Mean?

It means Git sees no tracked modifications, staged differences, or reportable untracked files relative to the current commit and ignore rules.

Can I Delete the .git Directory?

Deleting it turns the working folder back into a normal directory and removes the local repository metadata and history. Do so only when that is explicitly your intention and any required history is safely stored elsewhere.

Conclusion

Your first Git repository demonstrates the complete basic workflow: initialize a project, create files, inspect their state, stage selected versions, review the staged content, and record focused commits.

The most important lesson is that Git manages multiple states at once. The working directory contains current edits, the staging area contains the proposed next snapshot, and the repository stores committed history. Commands such as git status, git diff, and git diff --staged reveal the differences between those states.

A disciplined workflow is simple: inspect, edit, inspect again, stage deliberately, review the staged diff, commit with a meaningful message, and verify the final status.

The next article will examine staging and commits in greater depth, including partial staging, unstaging, amending commits, commit-message structure, and strategies for creating a clean and useful history.

Official References and Further Reading