These commands cover 80% of daily Git usage. Practice them in a test repository until they become muscle memory.

Repository Setup

  # Create a new repository
mkdir my-app && cd my-app
git init

# Clone an existing repository
git clone https://github.com/user/my-app.git
cd my-app
  

git init creates a hidden .git/ directory that stores all history.

Checking Status

  git status
  

Output shows:

  • Untracked files — new files Git hasn’t seen
  • Changes not staged — modified files not yet added
  • Changes to be committed — staged files ready for commit

Always run git status before committing to know exactly what you’re saving.

Staging and Committing

The two-step commit process:

  # Stage specific files
git add README.md src/app.js

# Stage all changes
git add .

# Commit with message
git commit -m "Add user login form"

# Stage and commit in one step (tracked files only)
git commit -am "Fix validation bug"
  

Write commit messages in imperative mood: “Add feature” not “Added feature.”

Good commit message structure:

  Short summary (50 chars or less)

Optional body explaining WHY the change was made,
not just what changed. Reference issue numbers.
  

Viewing History

  # Full log
git log

# Compact one-line log
git log --oneline

# Graph with branches
git log --oneline --graph --all

# Last 5 commits
git log -5 --oneline

# Commits by author
git log --author="Alice"

# Changes in a specific file
git log --follow -- src/app.js
  

Viewing Differences

  # Unstaged changes (working dir vs staging)
git diff

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

# Compare two commits
git diff a1b2c3d e4f5g6h

# Diff for one file
git diff HEAD -- src/app.js
  

Undoing Changes

  # Discard unstaged changes to a file
git restore src/app.js

# Unstage a file (keep changes in working dir)
git restore --staged src/app.js

# Amend last commit (change message or add files)
git add forgotten-file.js
git commit --amend -m "Updated commit message"

# Reset to previous commit (keep changes unstaged)
git reset HEAD~1

# Hard reset — DESTROYS uncommitted changes
git reset --hard HEAD~1
  

Use --hard only when you’re certain — it cannot be undone easily.

Ignoring Files

Create .gitignore in the project root:

  # Dependencies
node_modules/
vendor/

# Build output
dist/
build/
*.o
*.exe

# Environment secrets
.env
.env.local
*.pem

# IDE
.idea/
.vscode/
*.swp

# OS
.DS_Store
Thumbs.db
  
  # Stop tracking a file already committed
git rm --cached .env
git commit -m "Remove .env from tracking"
  

Inspecting Commits

  # Show a specific commit
git show a1b2c3d

# Show who changed each line (blame)
git blame src/app.js

# Find which commit introduced a bug
git bisect start
  

Practical Workflow Example

Building a small Node.js API:

  git init
npm init -y
echo "node_modules/" > .gitignore
git add .
git commit -m "Initialize Node.js project"

# Add feature
echo 'console.log("API ready");' > index.js
git add index.js
git commit -m "Add entry point"

# Fix typo
# ... edit index.js ...
git diff                    # review changes
git add index.js
git commit -m "Fix startup message"
  

Useful Aliases

Add to ~/.gitconfig:

  [alias]
    st = status
    co = checkout
    br = branch
    ci = commit
    lg = log --oneline --graph --all --decorate
    last = log -1 HEAD
    unstage = restore --staged
  

What Comes Next

Learn Branching and Merging to work on features in isolation, then Advanced Git for stash, rebase, and hooks.