Your First Repository — init, add, commit
Creating Your First Repository
In this lesson you will build taskr — a simple command-line task manager — and version-control it with Git from the very first file. Every concept introduced here will be used throughout the rest of the course.
git init — Starting a New Repository
To create a new Git repository, navigate to your project directory and run git init:
You will see output like:
That is all it takes. The directory taskr/ is now a Git repository. Git has created a hidden .git/ subdirectory inside it. This subdirectory is the repository — it contains the entire history, configuration, and object database.
You can also initialize a repository in an existing directory that already has files in it:
Initializing a repository in an existing directory is safe — Git does not touch your files. It just creates the .git/ directory.
git init with a name
You can pass a directory name to git init to create the directory and initialize a repo in one step:
The .git Directory — What Git Actually Stores
Before you make any commits, take a moment to look inside .git/. Understanding this directory demystifies Git considerably.
You will see something like:
Key contents (do not modify these manually):
- HEAD: A pointer to the current branch or commit. Right now it contains
ref: refs/heads/main. - config: Repository-specific Git configuration (overrides global config for this repo).
- objects/: The object database. All commits, file contents, and directory trees are stored here as compressed objects identified by SHA-1 hashes.
- refs/: References — named pointers to commits. Branches are stored here as files in
refs/heads/, tags inrefs/tags/, and remote-tracking branches inrefs/remotes/. - hooks/: Directory containing sample hook scripts. Hooks let you run custom scripts at specific Git events. Covered in lesson 10.
You will explore the internals of .git/ in detail in lesson 9. For now, just know it exists and do not delete or manually edit anything inside it.
git status — Understanding What Git Sees
git status is the command you will run more than any other. It tells you the current state of your working directory and staging area.
In a brand-new, empty repository:
Let's create some files:
Now run git status again:
Git sees both files but reports them as "untracked" — Git knows they exist in the working directory but is not tracking their history. They will not be included in any commit until you explicitly add them.
The status output is structured in sections:
- The current branch (
On branch main) - Changes staged for commit (empty right now)
- Changes not staged for commit (empty right now)
- Untracked files (
README.md,taskr.sh)
Tracking Files: git add
git add moves files from the working directory to the staging area (the index). Once staged, they will be included in the next commit.
Adding a Single File
README.md has moved from "Untracked files" to "Changes to be committed". It is now staged. taskr.sh is still untracked.
Adding All Files
Both files are now staged and ready to commit.
Adding with Patterns
Adding Interactively (Partial Staging)
One of Git's most powerful features is the ability to stage only part of a changed file — specific hunks (chunks of changed lines) rather than the whole file:
Git walks you through each changed hunk and asks what to do:
y— stage this hunkn— do not stage this hunks— split the hunk into smaller piecese— manually edit the hunkq— quit
This lets you create commits that are logically coherent even if you made multiple unrelated changes in one editing session.
The Staging Area in Depth
The staging area is not just a waiting room. It is a precise instrument for constructing meaningful commits.
Consider this scenario: you are working on a feature and you notice a typo in a comment somewhere. You fix the typo while also implementing the feature. Without the staging area, your only option is one commit that mixes the feature work and the typo fix. With the staging area, you can:
- Stage only the typo fix and commit it with message "fix: correct typo in auth module comment"
- Stage the feature work and commit it with message "feat: implement user authentication"
The result is a cleaner history where every commit has a single, clear purpose. This makes git log, git blame, git bisect, and code review far more useful.
Think of the staging area as your drafting table. Your working directory is where you do messy, exploratory work. The staging area is where you carefully compose the commit you want to make. The repository is where you publish that commit permanently.
git commit — Recording a Snapshot
Once your staging area contains exactly what you want to commit, you record it:
This opens your configured editor with a template:
Write your message, save, and close the editor. Git records the commit.
For short messages, use the -m flag to provide the message inline:
Output:
The output tells you:
- The branch (
main) - Whether this is the root commit (first commit in the repo)
- The abbreviated SHA-1 hash of the commit (
4f2a8b1) - The commit message
- A summary of what changed
Writing Good Commit Messages
A commit message is documentation. Future you — and your teammates — will read these messages when investigating bugs, understanding context, or reviewing changes. Write them well.
The Seven Rules of a Great Commit Message:
- Separate subject from body with a blank line
- Limit the subject line to 72 characters (some say 50, but 72 is widely accepted)
- Capitalize the subject line
- Do not end the subject line with a period
- Use the imperative mood in the subject line ("Add feature" not "Added feature" or "Adds feature")
- Use the body to explain what and why, not how
- Wrap the body at 72 characters
A full commit message with a body:
Subject line styles vary by team. Common conventions:
- Conventional Commits (
feat:,fix:,docs:,chore:, etc.) — covered in lesson 10 - Imperative plain English ("Add user auth", "Fix null pointer in login")
- Ticket references ("JIRA-123: Add user auth")
The most important rule: explain why, not just what. The diff already shows what changed. The commit message should explain the reasoning.
The -a Flag: Stage and Commit in One Step
For already-tracked files (not new files), you can skip git add and commit everything in one step:
The -a flag automatically stages all modified tracked files before committing. It does not include untracked files. Use this only when you want to commit all your changes as-is — use git add when you want to be selective.
Amending the Last Commit
If you made a commit and immediately realize you forgot a file or made a typo in the message:
--amend replaces the last commit with a new one that includes your staged changes and the new message. The old commit is discarded.
Warning: Only amend commits that have not been pushed to a shared remote. Amending rewrites history, which causes problems for anyone who has already pulled the original commit.
git log — Viewing History
git log shows the commit history of the current branch.
Let's make a second commit to have more to look at:
Now git log shows both commits:
Useful git log Options
The default output is verbose. These options make log much more useful:
A particularly useful combination for day-to-day use:
This gives you a compact, visual representation of your entire branch and commit history.
.gitignore — Telling Git What to Ignore
Not everything in your project directory should be tracked by Git. Build artifacts, compiled output, dependency directories, editor configuration, secrets, and operating system files should not be committed.
The .gitignore file tells Git which files and directories to ignore.
Create .gitignore in the root of your repository:
.gitignore Pattern Syntax
Global .gitignore
You can also create a global gitignore that applies to all repositories on your machine. This is useful for OS-specific files like .DS_Store (macOS) or Thumbs.db (Windows):
What if a File is Already Tracked?
If a file is already committed to the repository, adding it to .gitignore will not stop Git from tracking it. You need to remove it from tracking first:
After this, secrets.txt will be ignored by Git (assuming it is in .gitignore) but the file will remain on your filesystem.
git diff — Comparing Changes
git diff shows you what has changed but not yet been staged. It is your window into the working directory.
Let's make a change to see it in action:
Now:
Output shows the added lines with + prefix in green:
diff Variants
Practical diff Workflow
Before every commit, run both:
This two-step check ensures you are committing exactly what you intend and nothing else. Many experienced developers make this a habit: they never commit without reviewing the staged diff first.
A Complete Workflow Example
Here is the complete workflow you will use hundreds of times:
This loop — edit, status, diff, add, diff staged, commit — is the heartbeat of working with Git. The more naturally you move through it, the more control you have over your history.
Practical Exercises
Exercise 1: Build and Version the taskr Project
Exercise 2: Practice Staging Control
Exercise 3: Explore git log Options
Exercise 4: Practice git diff
Challenge: Reconstruct History
Look at your git log output and for each commit, use git show <hash> to see the full details of that commit. git show combines the commit metadata with a full diff of what changed. Notice how each commit is a self-contained unit of information.
Summary
git initcreates a new repository by adding a.git/directory to your project folder.- The
.git/directory contains the entire history, object database, configuration, and references for the repository. git statusshows which files are untracked, modified, or staged.git addmoves changes from the working directory to the staging area. Usegit add -pto stage specific hunks.- The staging area lets you compose commits with precision, even when your working directory is messier.
git commitrecords everything in the staging area as a permanent snapshot. Write clear, imperative commit messages explaining why.git logshows the commit history. Use--oneline --graph --allfor a compact visual overview..gitignoretells Git to ignore specified files and directories. Add OS files, editor files, build artifacts, and secrets.git diffshows changes in the working directory vs the last commit.git diff --stagedshows what is staged for the next commit.
In the next lesson, you will learn about branches — one of Git's most powerful features — and how they enable parallel lines of development without conflict.