Skip to main content

Documentation Index

Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt

Use this file to discover all available pages before exploring further.

Git Fundamentals

Master the core concepts that make Git powerful: repositories, commits, and the staging area.

Installing and Configuring Git

# Download from git-scm.com or use winget
winget install Git.Git

# Verify installation
git --version

First-Time Configuration

# Set your identity (required)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

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

# Set default editor
git config --global core.editor "code --wait"  # VS Code
# or
git config --global core.editor "vim"

# View all settings
git config --list

Creating Your First Repository

Method 1: Initialize a New Repository

# Create a new directory
mkdir my-project
cd my-project

# Initialize Git repository
git init

# This creates a hidden .git directory
ls -la
The .git directory contains all Git metadata: commits, branches, configuration, and the entire history.

Method 2: Clone an Existing Repository

# Clone from GitHub
git clone https://github.com/username/repo.git

# Clone with a different name
git clone https://github.com/username/repo.git my-folder

# Clone a specific branch
git clone -b develop https://github.com/username/repo.git

The Git Workflow

Git Workflow

1. Working Directory

Your actual files where you make changes.
# Create a new file
echo "# My Project" > README.md

# Edit files with your editor
code index.html

2. Staging Area (Index)

Prepare changes for commit. The staging area is Git’s “shopping cart” — you browse the store (make changes in your working directory), add items to the cart (stage them), and checkout (commit) only when you are ready. You can add and remove items from the cart before committing, which means you control exactly what goes into each commit.
# Stage a single file
git add README.md

# Stage all changes
git add .

# Stage specific files
git add file1.txt file2.txt

# Stage all .js files
git add *.js

# Interactive staging
git add -p  # Choose which changes to stage
Why a staging area? It lets you craft precise commits. You can modify 10 files but commit only 3 related changes.

3. Repository

Committed snapshots stored permanently.
# Commit staged changes
git commit -m "Add README and initial HTML"

# Commit with detailed message
git commit  # Opens editor for multi-line message

# Stage and commit in one step (tracked files only)
git commit -am "Update homepage content"

Understanding Commits

A commit is a snapshot of your entire project at a point in time. Not a diff, not a delta — a full snapshot. Git is smart enough to deduplicate identical files across snapshots (using content-addressable hashing), so this is efficient despite sounding wasteful. Every commit also records who made it, when, and a message explaining why.

Anatomy of a Commit

commit abc123def456  # SHA-1 hash (unique identifier)
Author: John Doe <john@example.com>
Date:   Mon Dec 2 10:30:00 2024 +0500

    Add user authentication feature
    
    - Implement login/logout
    - Add password hashing
    - Create user session management

Writing Good Commit Messages

git commit -m "feat: add user authentication"
git commit -m "fix: resolve memory leak in image processor"
git commit -m "docs: update API documentation"
git commit -m "refactor: simplify database query logic"
Commit Message Best Practices:
  • Use present tense: “Add feature” not “Added feature”
  • Be specific: “Fix login timeout” not “Fix bug”
  • Keep first line under 50 characters
  • Add details in the body if needed
  • Reference issue numbers: “Fix #123: resolve login issue”

Checking Status and History

Git Status

# See what's changed
git status

# Short format
git status -s
Output explained:
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
        modified:   style.css

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        script.js

Git Log

# View commit history
git log

# One line per commit
git log --oneline

# With 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"

# Show changes in each commit
git log -p

Viewing Changes

Git Diff

# Changes in working directory (not staged)
git diff

# Changes in staging area
git diff --staged

# Changes between commits
git diff abc123 def456

# Changes in a specific file
git diff README.md

# Word-level diff
git diff --word-diff

Ignoring Files

Create a .gitignore file to exclude files from version control. This is not optional — without it, you will inevitably commit node_modules (300MB of dependencies), .env files (database passwords), or OS junk files (.DS_Store) that have no business in a repository.
# .gitignore

# Dependencies -- always reinstall from lockfile; host binaries may not match container/server
node_modules/
vendor/

# Build outputs -- generated from source; committing them causes constant merge conflicts
dist/
build/
*.exe
*.dll

# Environment files -- contain secrets (API keys, DB passwords). NEVER commit these.
.env
.env.local

# IDE files -- personal preferences that differ per developer
.vscode/
.idea/
*.swp

# OS files -- macOS and Windows generate these automatically
.DS_Store
Thumbs.db

# Logs -- ephemeral runtime output, not source code
*.log
logs/

# Temporary files
*.tmp
temp/
Critical gotcha: .gitignore only prevents untracked files from being added. If you already committed a file and then add it to .gitignore, it is NOT removed from tracking. You must explicitly untrack it: git rm --cached .env (removes from tracking but keeps the file on disk). This catches many beginners who accidentally commit secrets, add .env to .gitignore, and assume the secret is gone. It is still in the Git history.
Use gitignore.io to generate .gitignore templates for your tech stack.

Undoing Changes

Unstage Files

# Unstage a file (keep changes in working directory)
git restore --staged file.txt

# Unstage all files
git restore --staged .

Discard Changes

# Discard changes in working directory (DANGEROUS!)
git restore file.txt

# Discard all changes
git restore .
git restore without --staged permanently deletes uncommitted changes!

Amend Last Commit

# Fix the last commit message
git commit --amend -m "New message"

# Add forgotten files to last commit
git add forgotten-file.txt
git commit --amend --no-edit

Practical Example: First Project

Let’s create a complete example:
# 1. Create project
mkdir my-website
cd my-website
git init

# 2. Create files
echo "# My Website" > README.md
echo "<!DOCTYPE html><html><body>Hello</body></html>" > index.html

# 3. Check status
git status

# 4. Stage files
git add README.md index.html

# 5. Commit
git commit -m "Initial commit: add README and index page"

# 6. Make changes
echo "<p>Welcome!</p>" >> index.html

# 7. See what changed
git diff

# 8. Stage and commit
git add index.html
git commit -m "Add welcome message to homepage"

# 9. View history
git log --oneline

Common Workflows

Daily Development

# Start your day
git status                    # See where you left off
git pull origin main          # Get latest changes

# Work on feature
git checkout -b feature/new-ui
# ... make changes ...
git add .
git commit -m "feat: redesign homepage UI"

# Push your work
git push origin feature/new-ui

Quick Fixes

# Oops, typo in last commit
git add typo-file.txt
git commit --amend --no-edit

# Discard all uncommitted changes
git restore .
git clean -fd  # Remove untracked files

Key Takeaways

Three States

Modified → Staged → Committed

Commit Often

Small, logical commits are better than large ones

Good Messages

Future you will thank present you

Check Status

Run git status frequently

Practice Exercises

1

Exercise 1: Basic Workflow

  1. Create a new repository
  2. Add 3 files
  3. Make 5 commits
  4. View the log with --oneline --graph
2

Exercise 2: Staging

  1. Modify 3 files
  2. Stage only 2 of them
  3. Commit the staged files
  4. Commit the remaining file separately
3

Exercise 3: Undoing

  1. Make a commit with a typo in the message
  2. Amend the commit
  3. Make changes to a file
  4. Discard those changes

Interview Deep-Dive

Strong Answer:
  • In Git, a file passes through three states: modified (changed in your working directory but not yet staged), staged (marked for inclusion in the next commit via git add), and committed (safely stored in the repository’s history as an immutable snapshot).
  • The staging area (also called the index) exists because it gives you editorial control over your commits. In SVN or Mercurial, commit grabs everything that changed. In Git, you decide exactly what goes in each commit. If you changed 10 files but only 3 are related to the bug fix you are committing, you stage those 3, commit with a clear message, then handle the remaining 7 in separate commits.
  • This enables atomic, logical commits. A single coding session might touch error handling, add a feature, and fix a typo. Without a staging area, all three go into one messy commit. With staging, you create three clean commits that can be reviewed, reverted, and bisected independently.
  • git add -p takes this further by letting you stage individual hunks within a file. You can commit the bug fix on line 42 but leave the debug logging on line 100 unstaged. This level of granularity is impossible without a staging area.
  • Under the hood, the staging area is a binary file (.git/index) that records which file versions (blob hashes) are ready for the next commit. git status compares three things: working directory vs index (unstaged changes), index vs HEAD commit (staged changes). This two-comparison model is why git diff and git diff --staged show different things.
Follow-up: A developer on your team always uses ‘git add .’ and commits everything at once. How would you coach them toward better practices?I would demonstrate the value through a code review. I would show them a PR with 5 unrelated changes in one commit versus the same changes split into 5 logical commits. The second version is reviewable, revertable, and bisectable. I would also show them git add -p in action — most developers are amazed the first time they see partial staging. The concrete habit I recommend: before committing, always run git diff --staged to review exactly what is going in. If the diff contains unrelated changes, unstage some with git restore --staged <file> and commit in batches.
Strong Answer:
  • The secret is not safe. Adding a file to .gitignore only prevents future untracked files from being staged. It does not remove files that are already tracked. The .env file is still in the Git history — anyone who clones the repository or browses the commit history can see it. git log -p -- .env will show the full contents.
  • Immediate actions: First, rotate the database credentials right now. Assume they are compromised. Second, remove the file from tracking without deleting it from disk: git rm --cached .env followed by a commit. This stops Git from tracking changes to .env going forward, but the historical commit still contains the file.
  • To remove the file from all history, use git filter-repo --path .env --invert-paths. This rewrites every commit that touched .env, removing it entirely. This changes commit hashes, so all team members must re-clone or reset to the rewritten history. For public repositories on GitHub, you also need to contact GitHub support to purge cached data, because force-pushing does not immediately clear their CDN caches.
  • Prevention: set up a pre-commit hook (using Husky or a custom hook) that scans staged files for patterns matching secrets (API keys, passwords, connection strings). Tools like git-secrets (AWS), gitleaks, or ggshield automate this. Also, use .env.example with placeholder values committed to the repo, and .env in .gitignore from the very first commit.
Follow-up: The repository is public on GitHub. How long do you have before the credential is likely compromised?Minutes, not hours. Automated bots continuously scan public GitHub commits for secrets. Researchers have demonstrated that AWS keys committed to public repos are exploited within 5 minutes of the push. This is why credential rotation is the first step, not the last. History rewriting is important for long-term hygiene, but it does not undo exposure that has already happened.
Strong Answer:
  • All three move the branch pointer (HEAD) to a different commit. The difference is what happens to the staging area (index) and the working directory.
  • --soft moves HEAD to the target commit but leaves the index and working directory unchanged. Everything that was in the “undone” commits becomes staged. Scenario: you made 5 small commits that should have been one. git reset --soft HEAD~5 collapses them all into staged changes, and you re-commit with a single clean message. No work is lost.
  • --mixed (the default) moves HEAD and resets the index to match the target commit, but leaves the working directory unchanged. Previously committed and staged changes become unstaged modifications. Scenario: you staged a file by mistake with git add . and want to unstage everything. git reset HEAD (which is --mixed by default) unstages all files but keeps your edits.
  • --hard moves HEAD, resets the index, and overwrites the working directory to match the target commit. Uncommitted changes are permanently deleted. Scenario: your local branch is hopelessly mangled after a bad rebase, and you want to start fresh from the remote. git reset --hard origin/main discards everything local and syncs to the remote. Use with extreme caution — there is no undo for uncommitted work destroyed by --hard.
  • The mental model: --soft touches only the commit history, --mixed touches history and staging, --hard touches everything. Each level is more destructive than the previous.
Follow-up: You accidentally ran ‘git reset —hard HEAD~3’ and lost uncommitted changes that were in your working directory. Can you recover them?The committed changes (the 3 commits you reset past) are recoverable via git reflog — find the SHA and create a branch. But uncommitted changes that were in the working directory are gone forever. Git never tracked them, so there is no reflog entry. The only hope is IDE local history (VS Code, IntelliJ, and others maintain their own file history) or filesystem-level recovery (Time Machine, file system snapshots). This is why I always tell developers: commit early and often, even WIP commits. A git reset --soft later can clean up the history, but uncommitted work is the one thing Git cannot protect.

Next: Git Branching & Merging →