Git Basics You Actually Need to Know - Part 1

You've cloned a repo, made some changes, and now you're staring at the terminal wondering what comes next. git add ., git commit -m "fix", git push — you've copy-pasted these commands a hundred times, but do you actually know what they're doing?
Let's fix that. This is Part 1 of understanding Git from the ground up — the commands you use every day, what they actually do, and when to use them.
How Git Actually Works
Before touching any commands, you need to understand Git's mental model. Git has four places your code can exist:
Working Directory - Your actual files, the ones you edit
Staging Area (Index) - Changes you've marked to commit
Local Repository - Commits on your machine
Remote Repository - Commits on GitHub/GitLab
Every Git command moves your code between these areas. Once you see this, Git stops being magic.
Starting a Repository: git init
Creating a new Git repository is simple:
git init
This creates a hidden .git folder in your current directory. That folder contains the entire history of your project. Delete it and your Git history is gone — but your files remain.
When you clone a repository, git clone does git init plus downloads all the commits from the remote:
git clone https://github.com/user/repo.git
This creates a new folder, initializes Git, downloads the history, and checks out the default branch (usually main or master).
Understanding Commits
A commit is a snapshot of your code at a specific moment. Not a diff, not changes — a complete snapshot. Git is smart enough to store this efficiently, but conceptually, each commit contains the full state of your project.
Every commit has:
A unique SHA hash (like
a3f2d91)A parent commit (except the first commit)
Author and timestamp
A commit message
A complete snapshot of all tracked files
Commits form a chain:
The Three-Step Commit Process
Making a commit is actually three separate actions:
Step 1: Edit Files (Working Directory)
You change a file. Git sees it as "modified" but hasn't done anything with it yet.
# Check what changed
git status
Output:
Changes not staged for commit:
modified: src/app.js
Step 2: Stage Changes (Staging Area)
You mark which changes should go into the next commit:
# Stage a specific file
git add src/app.js
# Stage all changes
git add .
# Stage all changes in current directory
git add -A
Now git status shows:
Changes to be committed:
modified: src/app.js
Step 3: Commit (Local Repository)
You save the staged changes as a commit:
git commit -m "Add user authentication"
Your changes are now permanently saved in Git's history. But they're still only on your machine.
Shortcut: Stage and commit modified files in one step (doesn't work for new files):
git commit -am "Update user model"
Branches: Parallel Universes
A branch is just a pointer to a commit. That's it. When you create a branch, Git creates a new pointer. When you commit, the pointer moves forward.
# Create a new branch
git branch feature/login
# Switch to it
git checkout feature/login
# Or do both at once
git checkout -b feature/login
Modern Git also has:
git switch feature/login # Switch branches
git switch -c feature/login # Create and switch
When you're on a branch and make a commit, only that branch pointer moves. Other branches stay where they are. This lets you work on multiple features simultaneously without them interfering.
List all branches:
git branch # Local branches only
git branch -a # Include remote branches
Delete a branch:
git branch -d feature/login # Safe delete (won't delete if unmerged)
git branch -D feature/login # Force delete
Connecting to Remote: git remote
A remote is a URL where your repository lives online (GitHub, GitLab, etc). When you clone, Git automatically adds a remote called origin.
# View remotes
git remote -v
Output:
origin https://github.com/user/repo.git (fetch)
origin https://github.com/user/repo.git (push)
Add a remote manually:
git remote add origin https://github.com/user/repo.git
Change remote URL:
git remote set-url origin https://github.com/user/new-repo.git
Remove a remote:
git remote remove origin
You can have multiple remotes. Common pattern for open source:
git remote add upstream https://github.com/original/repo.git
git remote add origin https://github.com/yourfork/repo.git
Now you can pull from upstream (the original project) and push to origin (your fork).
Pushing and Pulling
Push sends your commits to the remote. Pull downloads commits from the remote.
Push to remote:
# First time on a new branch
git push -u origin feature/login
# After that, just
git push
The -u flag sets the upstream tracking relationship. After that, Git knows where to push when you type git push.
Pull from remote:
git pull
This does two things:
git fetch- Downloads commits from remotegit merge- Merges them into your current branch
Fetch without merging:
git fetch origin
This updates your local knowledge of what's on the remote, but doesn't change your working directory. Useful when you want to see what changed before merging.
Git Reset: Undoing Things
Reset moves the branch pointer backward. It comes in three flavors:
git reset --soft
Moves the branch pointer, keeps staging area and working directory:
git reset --soft HEAD~1
This undoes the last commit but keeps your changes staged. Useful when you committed too early or want to recommit with a better message.
Use case: You committed "WIP" and want to add more changes to that commit:
git reset --soft HEAD~1
# Make more changes
git add .
git commit -m "Complete feature implementation"
git reset --mixed (default)
Moves the branch pointer, unstages changes, keeps working directory:
git reset HEAD~1
# Same as: git reset --mixed HEAD~1
This undoes the commit and unstages the changes, but your file edits remain. The most common reset type.
Use case: You committed the wrong files:
git reset HEAD~1
# Now selectively stage the right files
git add src/correct-file.js
git commit -m "Fix authentication bug"
git reset --hard
Moves the branch pointer, clears staging area, resets working directory:
git reset --hard HEAD~1
⚠️ Danger zone: This deletes your changes. They're gone. Use with caution.
Use case: You completely messed up and want to start over:
git reset --hard HEAD # Discard all uncommitted changes
git reset --hard origin/main # Match remote exactly
HEAD~1 vs HEAD^:
HEAD~1- One commit before HEADHEAD~2- Two commits before HEADHEAD^- First parent (same as HEAD~1 for linear history)
Checking History
See what commits exist:
# Basic log
git log
# One line per commit
git log --oneline
# With branch graph
git log --oneline --graph --all
# Last 5 commits
git log -5
# Commits by author
git log --author="John"
# Commits in date range
git log --since="2 weeks ago"
See what changed in a commit:
git show a3f2d91
See what changed in a file:
git log -p src/app.js
Practical Workflows
Starting a New Feature
# Make sure you're on main and up to date
git checkout main
git pull
# Create feature branch
git checkout -b feature/user-profile
# Work and commit
git add src/profile.js
git commit -m "Add user profile component"
# Push to remote
git push -u origin feature/user-profile
Fixing a Mistake in Last Commit
Wrong commit message:
git commit --amend -m "Better commit message"
Forgot to add a file:
git add forgotten-file.js
git commit --amend --no-edit
The --amend flag replaces the last commit. Don't amend commits that you've already pushed to a shared branch — it rewrites history.
Discarding Uncommitted Changes
Discard changes in one file:
git checkout -- src/app.js
# Or in modern Git:
git restore src/app.js
Discard all changes:
git reset --hard HEAD
Unstage a file (keep changes):
git reset HEAD src/app.js
# Or:
git restore --staged src/app.js
What We Covered
You now understand:
Git's four areas: working directory, staging, local repo, remote repo
How commits form a chain of snapshots
Creating and switching branches
The three-step commit process (edit, stage, commit)
Connecting to remotes and pushing/pulling
The three types of reset and when to use each
Basic history exploration
In Part 2, we'll cover merging, rebasing, handling conflicts, stashing, and recovering lost commits.
Common Mistakes to Avoid
Committing to main directly: Always create a feature branch. Keep main clean.
Not pulling before pushing: Always pull before starting work. Prevents conflicts.
Using reset --hard carelessly: Your changes are gone. Make sure you want that.
Amending pushed commits: Rewrites history. Only amend commits that haven't been pushed.
Forgetting to track new files: git add . includes new files. git commit -am doesn't.
TLDR;
Git has four areas: working directory (your files), staging area (changes marked for commit), local repository (commits on your machine), and remote repository (commits on GitHub/GitLab). The basic workflow is: edit files → git add to stage → git commit to save → git push to upload. Branches are pointers to commits — create them with git checkout -b branch-name. Connect to remotes with git remote add origin url. Reset moves the branch pointer: --soft keeps changes staged, --mixed (default) unstages them, --hard deletes everything. Use git log to see history. Always pull before pushing. Never reset hard unless you want to lose changes. Part 2 will cover merging, rebasing, and conflict resolution.





