Skip to content
beginner Phase 5 · Git and Version Control

Git Fundamentals

Initialize repositories, stage changes, commit snapshots, and understand Git's working tree, staging area, and HEAD.

50m
0 problems
Topic Progress 0%

Initializing Repositories and Making Commits

Initializing Repositories and Making Commits

Creating a Repository

# Initialize a new repo
git init
git init my-project && cd my-project

# Clone an existing repo
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git    # SSH
git clone --depth 1 https://github.com/user/repo.git  # Shallow clone

The Three Areas

Git has three main areas:

  1. Working Directory — Your actual files
  2. Staging Area (Index) — Files marked for the next commit
  3. Repository (.git) — The committed history
Working Directory  →  git add  →  Staging Area  →  git commit  →  Repository
    ←  git checkout   ←              ←  git reset  ←

Staging and Committing

# Check status
git status
git status -s    # Short format

# Stage specific files
git add file.txt
git add src/app.js src/utils.js

# Stage all changes
git add .
git add -A    # All changes including deletions

# Stage parts of a file (interactive)
git add -p file.txt    # Shows hunks, you choose what to stage

# Commit with a message
git commit -m "Add user authentication module"

# Commit with detailed message
git commit -m "Add user authentication module" -m "- Implement JWT token generation
- Add login/logout endpoints
- Add password hashing with bcrypt"

# Stage and commit in one step (only for modified tracked files)
git commit -am "Fix memory leak in connection pool"

# Amend the last commit
git commit --amend -m "Updated commit message"
git commit --amend --no-edit    # Keep the same message, add staged files

Writing Good Commit Messages

# Format: <type>(<scope>): <subject>

feat(auth): add JWT token validation middleware
fix(db): handle connection timeout in pool
docs(readme): add installation instructions
refactor(api): extract validation into middleware
test(auth): add unit tests for login endpoint
chore(deps): upgrade express to v4.18.2

# Subject line:
# - Use imperative mood ("add feature" not "added feature")
# - Keep under 50 characters
# - No period at the end

Inspecting the Repository

Inspecting the Repository

git log

# Full log
git log

# One line per commit
git log --oneline

# Graphical branch visualization
git log --oneline --graph --all --decorate

# Filter by author
git log --author="John"
git log --author="john@example.com"

# Filter by date
git log --since="2 weeks ago"
git log --since="2024-01-01" --until="2024-01-31"

# Filter by message
git log --grep="fix" --grep="bug" --all-match
git log --grep="login"

# Show file changes per commit
git log --stat
git log --name-only

# Show actual diffs
git log -p              # Full diff
git log -p -- src/app.js  # Only changes to src/app.js

# Pretty format
git log --pretty=format:"%h %s (%an, %ar)"
git log --pretty=format:"%C(yellow)%h%C(reset) %s%C(red)(%an%C(reset) %ar)"

# Limit results
git log --oneline -20          # Last 20 commits
git log --oneline --follow -- src/app.js  # Follow file renames

git diff

# Unstaged changes (working directory vs staging)
git diff

# Staged changes (staging area vs last commit)
git diff --staged
git diff --cached

# Specific file
git diff -- src/app.js

# Between two commits
git diff abc1234 def5678

# Between branches
git diff main..feature-branch

# Summary only
git diff --stat

# Ignore whitespace changes
git diff -w

# Show only file names that changed
git diff --name-only

# Compare with a specific commit
git diff HEAD~3          # Changes in last 3 commits
git diff HEAD~1          # Changes in last commit only

git show and git status

# Show a specific commit
git show abc1234
git show abc1234:src/app.js    # Show file at that commit

# Show file at a specific commit
git show HEAD:package.json
git show main:README.md

# Detailed status
git status -sb    # Short + branch info

# Check what's untracked
git ls-files --others --exclude-standard

# Find which commit last modified a line
git blame src/app.js
git blame -L 10,20 src/app.js   # Lines 10-20 only

Undoing Changes

Undoing Changes

Understanding the Options

Command Working Dir Staging Repository Use When
git restore Yes Yes No Discard changes
git reset Yes Yes Yes Undo commits
git revert No No Yes Undo with new commit

Discarding Working Directory Changes

# Discard changes to a file
git restore file.txt

# Discard all unstaged changes
git restore .

# Unstage a file (move from staging to working dir)
git restore --staged file.txt

# Unstage all
git restore --staged .

# Discard ALL changes (working + staged) — DANGEROUS
git restore --staged --worktree .

Reset (Moving HEAD)

# Soft reset: move HEAD, keep staged changes
git reset --soft HEAD~1        # Undo last commit, keep staged

# Mixed reset (default): move HEAD, unstage changes
git reset HEAD~1              # Undo last commit, keep in working dir

# Hard reset: move HEAD, discard everything — DANGEROUS
git reset --hard HEAD~1       # Complete undo

# Reset to a specific commit
git reset --hard abc1234

# Reset a specific file
git restore --source=HEAD~1 file.txt

Revert (Safe Undo)

# Create a new commit that undoes a previous commit
git revert abc1234

# Revert multiple commits
git revert abc1234 def5678

# Revert without committing (stage the changes)
git revert --no-commit abc1234

# Revert merge commit
git revert -m 1 abc1234    # -m 1 keeps parent side

Practical Examples

# I added a file but want to remove it from the commit
git restore --staged unwanted-file.txt

# I committed secrets — remove from history
git reset --soft HEAD~1
git restore --staged .env
echo '.env' >> .gitignore
git add .gitignore
git commit -m "Remove .env and add to gitignore"

# I want to go back 3 commits but keep changes
git reset --soft HEAD~3

# Accidentally committed to wrong branch
git log --oneline -1     # Note the commit hash
git checkout main
git cherry-pick abc1234   # Apply the commit here
git checkout feature-branch
git reset --hard HEAD~1   # Remove from wrong branch

Git Ignore and Configuration

Git Ignore and Configuration

.gitignore Patterns

# Create .gitignore
touch .gitignore

# Common patterns
.env
.env.local
.env.production

# Build output
dist/
build/
*.min.js
*.min.css

# Dependencies
node_modules/
venv/
__pycache__/
*.pyc

# IDE files
.vscode/
.idea/
*.swp
*.swo
*~

# OS files
.DS_Store
Thumbs.db

# Logs
*.log
logs/

# Specific file
/secrets.json

# Files ending in .bak
*.bak

# Negation: include a file normally ignored
!important.log

# Match directories
build/

# Match files with specific name
TODO

Global Git Configuration

# Set your identity
git config --global user.name "John Doe"
git config --global user.email "john@example.com"

# Set default branch name
git config --global init.defaultBranch main

# Set editor
git config --global core.editor "code --wait"
git config --global core.editor "vim"

# Set diff tool
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'

# Enable color output
git config --global color.ui auto

# Set pull strategy
git config --global pull.rebase true

# Set push strategy
git config --global push.default current

# Useful aliases
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.unstage "restore --staged"
git config --global alias.last "log -1 HEAD"
git config --global alias.amend "commit --amend --no-edit"

# View all config
git config --list
git config --list --show-origin

# Remove a setting
git config --global --unset alias.st

Git Hooks

# Hooks live in .git/hooks/
# Common hooks:
# pre-commit    - runs before commit (lint, format)
# commit-msg    - validates commit message
# pre-push      - runs before push (tests)

# Example pre-commit hook (.git/hooks/pre-commit)
#!/bin/bash
set -e

echo "Running linting..."
npm run lint
echo "Running tests..."
npm test -- --passWithNoTests

echo "All checks passed"

# Make it executable
chmod +x .git/hooks/pre-commit

# Use Husky for Node.js projects
npx husky init
npx husky add .husky/pre-commit "npm run lint"

Git Attributes and LFS

# .gitattributes — handle line endings, binary files
* text=auto
*.sh text eol=lf
*.bat text eol=crlf
*.png binary
*.jpg binary

# Git LFS for large files
git lfs install
git lfs track "*.zip"
git lfs track "*.mp4"
git lfs track "bin/**"
git add .gitattributes

Working with Remotes

Working with Remotes

Remote Basics

# Add a remote
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git

# List remotes
git remote -v

# Show remote details
git remote show origin

# Rename a remote
git remote rename origin origin-old

# Remove a remote
git remote remove upstream

Fetching and Pulling

# Fetch: download remote changes (don't merge)
git fetch origin
git fetch --all    # Fetch all remotes

# View fetched changes
git log origin/main..HEAD    # Commits you have that remote doesn't
git log HEAD..origin/main    # Commits remote has that you don't

# Pull: fetch + merge
git pull origin main
git pull --rebase origin main    # Fetch + rebase

# Pull with autosquash
git pull --rebase --autostash origin main

Pushing

# Push to remote
git push origin main

# Push and set upstream
git push -u origin feature-branch

# Force push (DANGEROUS)
git push --force origin main

# Force push with lease (safer)
git push --force-with-lease origin main

# Push all branches
git push --all origin

# Push tags
git push origin --tags
git push origin v1.0.0

Fork Workflow

# 1. Fork on GitHub, then clone your fork
git clone https://github.com/YOUR-USER/repo.git
cd repo

# 2. Add upstream remote
git remote add upstream https://github.com/ORIGINAL-USER/repo.git

# 3. Create feature branch
git checkout -b feature/new-feature

# 4. Make changes, commit
git add .
git commit -m "Add new feature"

# 5. Push to your fork
git push origin feature/new-feature

# 6. Create PR on GitHub

# 7. Keep fork updated
git fetch upstream
git checkout main
git merge upstream/main
git push origin main