Why Git Is Needed
When editing code, you need to be able to undo mistakes. Multiple people need to be able to modify the same code simultaneously. Git is a distributed version control system that solves both of these problems.
Key characteristics of Git:
- Work independently locally — commit, branch, and browse history without a network connection
- Branches are lightweight — creating a new branch is nearly instant (just creating a pointer)
- Full change history — records who changed what, when, and why
Initial Setup
The first settings to configure after installing Git.
# Set user info (recorded in commits)
git config --global user.name "Alice"
git config --global user.email "alice@example.com"
# Set default branch name to main
git config --global init.defaultBranch main
# Verify settings
git config --list
# user.name=Alice
# user.email=alice@example.com
# init.defaultbranch=main
Core Concept: Three Areas
Git has three areas that files pass through.
| Area | Description | Analogy |
|---|---|---|
| Working Directory | Where you actually edit files | Your desk |
| Staging Area (Index) | Where changes for the next commit are gathered | Packing area |
| Repository (.git) | Where committed snapshots are stored | Warehouse |
Flow: Edit -> git add -> Staging -> git commit -> Repository
Essential Commands
Creating and Cloning Repositories
# Initialize a new repository
mkdir my-project && cd my-project
git init
# Initialized empty Git repository in /my-project/.git/
# Clone an existing remote repository
git clone https://github.com/user/repo.git
git clone https://github.com/user/repo.git my-folder # Specify folder name
Checking Status and Tracking Changes
# Check current status (the most frequently used command)
git status
# On branch main
# Changes not staged for commit:
# modified: src/app.js
# Untracked files:
# src/utils.js
# Compare changes
git diff # Working -> Staging comparison
git diff --staged # Staging -> Last commit comparison
# View commit history
git log --oneline --graph
# * a1b2c3d (HEAD -> main) feat: add login feature
# * d4e5f6g fix: bug fix
# * g7h8i9j init: project initialization
Staging and Committing
# Stage specific files
git add src/app.js
# Stage all changed files (including new files)
git add .
# Commit (message should record "why" the change was made)
git commit -m "feat: add user login feature"
# Stage + commit in one step (tracked files only)
git commit -am "fix: fix password validation error"
Commit Message Conventions
Using a unified format within a team makes history easier to understand.
| Prefix | Purpose | Example |
|---|---|---|
| feat | New feature | feat: add social login |
| fix | Bug fix | fix: resolve session expiry error |
| refactor | Refactoring (no behavior change) | refactor: extract auth module |
| docs | Documentation changes | docs: add API endpoint descriptions |
| test | Add/modify tests | test: add login failure test cases |
| chore | Build, config changes | chore: update ESLint rules |
| perf | Performance improvement | perf: optimize query indexing |
Using Branches
Branches are independent workspaces. Develop features while keeping the main branch safe.
# List branches
git branch
# * main
# feature/login
# Create + switch to a branch
git checkout -b feature/login
# Or (Git 2.23+)
git switch -c feature/login
# Switch branches
git checkout main
git switch main
# Delete a branch (after merging)
git branch -d feature/login
Merging
# Merge a feature branch into main
git checkout main
git merge feature/login
# Auto-merges if there are no conflicts
# When conflicts occur
# 1. Manually edit conflicting files
# 2. Stage after resolving conflicts
git add src/auth.js
# 3. Create merge commit
git commit -m "merge: merge feature/login"
Rebase vs Merge
| Aspect | Merge | Rebase |
|---|---|---|
| History | Merge commit remains (branch visible) | Linear history (clean) |
| Safety | Preserves original history | Commit hashes change |
| When to use | Merging into main | Updating feature branch with main |
| Rule | Safe on shared branches | Never rebase shared branches |
# Bring latest changes from main into a feature branch
git checkout feature/login
git rebase main
# -> Feature commits are replayed on top of latest main
Remote Repositories
Commands for synchronizing with remote repositories like GitHub and GitLab.
# Register a remote repository
git remote add origin https://github.com/user/repo.git
# List remotes
git remote -v
# Push (local -> remote)
git push origin main
git push -u origin feature/login # -u: set upstream (git push alone is enough after this)
# Pull (remote -> local, fetch + merge)
git pull origin main
# Fetch remote changes only (no merge)
git fetch origin
Undoing Mistakes
| Situation | Command | Description |
|---|---|---|
| Unstage | git restore --staged file.js | Undo add (file content preserved) |
| Discard changes | git restore file.js | Restore to last commit state (caution: deletes changes) |
| Amend last commit | git commit --amend | Edit message or add files (unpushed commits only) |
| Revert a specific commit | git revert a1b2c3d | Creates a new reverting commit (safe) |
| Reset commit history | git reset --soft HEAD~1 | Undo commit, changes preserved in Staging |
# Most common mistake: forgot to include a file in commit
git add forgotten-file.js
git commit --amend --no-edit # Add file while keeping the message
# Dangerous commands — use with caution
git reset --hard HEAD~1 # Deletes commit + all changes (difficult to recover)
Real-World Collaboration Workflow
The most commonly used workflow based on GitHub Flow.
# 1. Get latest code from main
git checkout main
git pull origin main
# 2. Create a feature branch
git checkout -b feature/user-profile
# 3. Work + commit (repeat multiple times)
git add .
git commit -m "feat: implement profile edit UI"
git commit -m "feat: add profile image upload"
# 4. Push to remote
git push -u origin feature/user-profile
# 5. Create a Pull Request on GitHub
# -> Code review -> Approval -> Merge to main
# 6. Clean up locally
git checkout main
git pull origin main
git branch -d feature/user-profile
.gitignore Setup
Specify files to exclude from version control. Create a .gitignore file at the project root.
# Dependencies
node_modules/
vendor/
venv/
# Build artifacts
dist/
build/
*.pyc
# Environment variables / secrets
.env
.env.local
*.pem
# IDE settings
.vscode/
.idea/
*.swp
# OS files
.DS_Store
Thumbs.db
Summary
| Situation | Command |
|---|---|
| Start a project | git init or git clone |
| Save changes | git add . -> git commit -m "message" |
| Check status | git status, git log --oneline |
| Branch work | git switch -c feature/xxx -> work -> git merge |
| Sync with remote | git pull -> work -> git push |
| Undo mistakes | git restore, git revert, git reset --soft |
Git is a tool, not an end in itself. Do not try to memorize complex commands — just learn the basic flow in the table above and you can handle most situations. Look up the rest when you need it.