What is Git?
Git is a distributed version control system that tracks changes in your codebase, enabling collaboration and maintaining a complete history of your project.
Key Benefits:
Track every change made to your code
Collaborate with multiple developers simultaneously
Revert to previous versions when needed
Experiment safely with branches
Maintain detailed project history
Installation
Verify Installation:
git --version
macOS (via Homebrew):
# Install Homebrew first
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# Install Git
brew install git
# Verify
git --version
Windows:
Download from gitforwindows.org
Run installer
Verify in Command Prompt:
git --version
Essential Configuration
First-Time Setup
Before making your first commit, configure your identity:
# Set your name
git config --global user.name "Your Name"
# Set your email
git config --global user.email "your.email@example.com"
# Verify configuration
git config --list
Why This Matters:
Every commit you make includes this information. It ensures proper attribution in collaborative projects.
Configuration Locations:
Global:
~/.gitconfig(applies to all repositories)Local:
.git/config(repository-specific)System: System-wide settings
Understanding Git Workflow
The Three States
Git manages your files in three distinct states:
Core Commands
Initialize Repository
git init
Purpose: Create a new Git repository
Result: Creates .git directory with repository metadata
Use Case: Starting a new project or adding Git to existing code
Check Status
git status
Purpose: Display state of working directory and staging area
Output Indicators:
🟢 Green: Staged files (ready to commit)
🔴 Red: Modified but unstaged
⚪ White: Untracked files
Best Practice: Run git status frequently—it's your safety net
View Changes
# See unstaged changes
git diff
# See staged changes
git diff --staged
# See changes in specific file
git diff <filename>
Purpose: Review line-by-line modifications
Use Case: Before staging or committing, verify what changed
Stage Changes
# Stage specific file
git add <filename>
# Stage multiple files
git add file1.js file2.css
# Stage all changes
git add .
# Stage all files of a type
git add *.js
Purpose: Select changes for next commit
Analogy: Like adding items to a shopping cart before checkout
Pro Tip: Stage related changes together for atomic commits
Commit Changes
# Commit with inline message
git commit -m "Add user authentication feature"
# Commit with detailed message (opens editor)
git commit
# Stage and commit in one step (tracked files only)
git commit -am "Update navigation styles"
Commit Message Best Practices:
Good Examples:
"Fix login button alignment on mobile"
"Add email validation to signup form"
"Refactor database connection logic"
Bad Examples:
"updates"
"fixed stuff"
"changes"
Guidelines:
Use present tense ("Add feature" not "Added feature")
Be specific and concise
Describe what and why, not how
First line under 50 characters
Leave blank line before detailed description
View History
# Standard log
git log
# Compact one-line format
git log --oneline
# Show last 5 commits
git log -5
# Graph view with branches
git log --graph --all --decorate
# Beautiful colored graph
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
Navigation:
Arrow keys: Scroll
q: Exit/pattern: Searchn: Next match
Branching Strategies
Why Branch?
Branches enable parallel development, allowing teams to work on features, fixes, and experiments simultaneously without interfering with stable code.
Branch Visualization
Essential Branch Commands
# List all branches (* marks current)
git branch
# Create new branch
git branch feature/new-feature
# Switch to branch
git checkout feature/new-feature
# Create and switch (shortcut)
git checkout -b feature/new-feature
# Delete merged branch
git branch -d feature/old-feature
# Force delete unmerged branch
git branch -D feature/experimental
Critical Rule: Always verify your current branch before committing
git branch # Shows current branch
Branch Naming Conventions
Professional Standards:
# Feature branches
feature/user-authentication
feature/payment-gateway
feature/dark-mode
# Bug fixes
bugfix/login-error
bugfix/cart-calculation
fix/mobile-responsive
# Hotfixes (urgent production fixes)
hotfix/security-patch
hotfix/crash-on-startup
# With ticket systems (Jira, Linear, etc.)
feature/PROJ-123-user-dashboard
bugfix/PROJ-456-email-validation
Rules:
Lowercase with hyphens
Descriptive but concise
Include ticket/issue number
Use consistent prefixes
Merging Branches
Standard Merge Workflow:
# 1. Switch to target branch
git checkout main
# 2. Update target branch
git pull origin main
# 3. Merge feature branch
git merge feature/new-feature
# 4. Push merged changes
git push origin main
# 5. Delete merged branch
git branch -d feature/new-feature
Merge Visualization:
BEFORE MERGE:
feature
┌─ F1 ─ F2 ─ F3
│
main ─ M1 ─ M2 ─ M3
AFTER MERGE:
feature
┌─ F1 ─ F2 ─ F3 ─┐
│ ▼
main ─ M1 ─ M2 ─ M3 ─ M4 (merge commit)
Undoing Changes
Discard Working Directory Changes
# Discard changes in specific file
git checkout -- <filename>
# Discard all changes
git checkout -- .
WARNING: Permanently deletes uncommitted changes
Use Case: Abandon work and restore last committed version
Unstage Files
# Unstage specific file
git reset HEAD <filename>
# Unstage all files
git reset HEAD .
Purpose: Remove files from staging area (preserves changes)
Use Case: Accidentally staged wrong files
Undo Commits
# Undo last commit, keep changes staged
git reset --soft HEAD~1
# Undo last commit, keep changes unstaged
git reset --mixed HEAD~1
# Undo last commit, delete all changes
git reset --hard HEAD~1
# Undo multiple commits
git reset --soft HEAD~3
Reset Modes Compared:
| Mode | Commit | Staging Area | Working Directory |
|---|---|---|---|
--soft |
✗ Removed | ✓ Preserved | ✓ Preserved |
--mixed |
✗ Removed | ✗ Cleared | ✓ Preserved |
--hard |
✗ Removed | ✗ Cleared | ✗ Deleted |
HEAD Notation:
HEAD~1: 1 commit backHEAD~3: 3 commits backHEAD^: Parent commit
Revert vs Reset
Revert creates new commit that undoes changes:
git revert <commit-hash>
When to Use Each:
RESET (Rewrites History):
A ─── B ─── C ─── D (HEAD)
↓ git reset --hard B
A ─── B (HEAD)
✓ Local changes only
✓ Recent commits
✗ Never on shared branches
REVERT (Preserves History):
A ─── B ─── C ─── D (HEAD)
↓ git revert C
A ─── B ─── C ─── D ─── C' (HEAD)
✓ Shared/public branches
✓ Historical commits
✓ Audit trail required
Remote Collaboration
Understanding Remotes
Remote Repository: Centralized server hosting your Git repository, enabling team collaboration.
YOUR COMPUTER GITHUB SERVER
┌─────────────────────┐ ┌─────────────────────┐
│ Local Repository │ │ Remote Repository │
│ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ Commits │ │ git push │ │ Commits │ │
│ │ Branches │ │──────────►│ │ Branches │ │
│ │ History │ │ │ │ History │ │
│ └─────────────┘ │◄──────────│ └─────────────┘ │
│ │ git pull │ │
└─────────────────────┘ └─────────────────────┘
Clone Repository
# Clone via HTTPS
git clone https://github.com/username/repository.git
# Clone via SSH
git clone git@github.com:username/repository.git
# Clone to specific directory
git clone https://github.com/username/repo.git my-folder
# Clone specific branch
git clone -b develop https://github.com/username/repo.git
Purpose: Download complete repository with full history
Result: Creates local copy ready for development
Connect Local Repository to Remote
# Add remote (first time)
git remote add origin https://github.com/username/repository.git
# Verify remote
git remote -v
# Change remote URL
git remote set-url origin https://github.com/username/new-repo.git
# Remove remote
git remote remove origin
"origin": Standard name for primary remote (convention, not requirement)
Push to Remote
# Push current branch
git push
# Push specific branch
git push origin feature/login
# Push new branch (set upstream)
git push -u origin feature/new-feature
# Push all branches
git push --all
# Push tags
git push --tags
First Push Workflow:
git checkout -b feature/awesome
# ... make changes and commit ...
git push -u origin feature/awesome # -u sets upstream tracking
# Future pushes: just "git push"
Pull from Remote
# Fetch and merge
git pull
# Pull specific branch
git pull origin main
# Fetch only (no merge)
git fetch
# Pull with rebase (cleaner history)
git pull --rebase
Pull vs Fetch:
FETCH (Download only):
Remote: A ─── B ─── C ─── D
↓
Local: A ─── B origin/main points to D
│
HEAD (unchanged)
PULL (Download + Merge):
Remote: A ─── B ─── C ─── D
↓
Local: A ─── B ─── E (merged)
↙ ↖
D Local changes
Pull Request Workflow
What is a Pull Request?
A formal request to merge your branch into another (typically main), enabling code review and discussion.
Complete Workflow:
On GitHub:
Push feature branch to remote
Navigate to repository on GitHub
Click "Compare & pull request" (yellow banner)
Fill out PR template:
* Descriptive title
* Summary of changes
* Screenshots (if UI changes)
* Related issues/tickets
Request reviewers
Address feedback with new commits
Merge when approved (Squash/Merge/Rebase)
Delete remote branch
Locally After Merge:
# Switch to main branch
git checkout main
# Pull merged changes
git pull origin main
# Delete local feature branch
git branch -d feature/completed
# Prune deleted remote branches
git fetch --prune
Handling Conflicts
When Conflicts Occur
Conflicts arise when Git cannot automatically merge changes because:
Same lines modified in both branches
File deleted in one branch, modified in another
Binary files changed differently
Conflict Resolution Process
1. Conflict Appears During Merge:
$ git merge feature/login
Auto-merging app.js
CONFLICT (content): Merge conflict in app.js
Automatic merge failed; fix conflicts and then commit the result.
2. Identify Conflicted Files:
git status
# Shows: both modified: app.js
3. Open Conflicted File:
function login(user) {
<<<<<<< HEAD
return authenticateWithOAuth(user);
=======
return authenticateWithJWT(user);
>>>>>>> feature/login
}
Conflict Markers:
<<<<<<< HEAD: Your current branch version=======: Separator>>>>>>> feature/login: Incoming branch version
4. Resolve Conflict:
Choose one version, combine both, or write new solution:
function login(user) {
return authenticateWithJWT(user); // Chosen version
}
5. Mark as Resolved:
git add app.js
6. Complete Merge:
git commit # Opens editor with default merge message
# or
git commit -m "Merge feature/login - use JWT authentication"
Conflict Prevention
# Keep feature branch updated with main
git checkout feature/my-feature
git merge main # or git rebase main
# Pull before starting work
git pull origin main
# Communicate with team about file changes
Advanced Techniques
Rebase
Purpose: Rewrite commit history for cleaner, linear progression
Basic Rebase:
# On feature branch
git rebase main
Visual Comparison:
MERGE (Creates merge commit):
feature
┌─ F1 ─ F2 ─┐
│ ▼
main ─ M1 ─ M2 ─ M3 ─ M4
↑
(merge commit)
REBASE (Linear history):
Before:
feature
┌─ F1 ─ F2
│
main ─ M1 ─ M2 ─ M3
After:
feature
┌─ F1' ─ F2'
│
main ─ M1 ─ M2 ─ M3
When to Rebase:
Update feature branch with main changes
Clean up commits before PR
Maintain linear project history
Golden Rule of Rebase:NEVER rebase commits that exist on public/shared branches
# After rebase, force push required
git push --force-with-lease # Safer than -f
Interactive Rebase
Edit commit history:
# Rebase last 3 commits
git rebase -i HEAD~3
Editor Opens:
pick a1b2c3d Add login feature
pick e4f5g6h Fix typo in login
pick i7j8k9l Update login tests
# Commands:
# p, pick = use commit
# r, reword = use commit, edit message
# e, edit = use commit, stop for amending
# s, squash = combine with previous commit
# f, fixup = like squash, discard message
# d, drop = remove commit
Common Use Cases:
Squash Multiple Commits:
pick a1b2c3d Add login feature
squash e4f5g6h Fix typo in login
squash i7j8k9l Update login tests
Result: All three commits become one
Reword Commit Message:
pick a1b2c3d Add login feature
reword e4f5g6h Fix typo in login
pick i7j8k9l Update login tests
After Changes:
# If conflicts occur
git add <resolved-files>
git rebase --continue
# Abort rebase
git rebase --abort
Stash Changes
# Stash current changes
git stash
# Stash with message
git stash save "WIP: login form validation"
# List stashes
git stash list
# Apply most recent stash
git stash apply
# Apply and remove stash
git stash pop
# Apply specific stash
git stash apply stash@{2}
# Delete stash
git stash drop stash@{0}
# Clear all stashes
git stash clear
Use Case: Switch branches without committing incomplete work
Cherry Pick
# Apply specific commit to current branch
git cherry-pick <commit-hash>
# Cherry pick multiple commits
git cherry-pick abc123 def456
# Cherry pick without committing
git cherry-pick -n <commit-hash>
Use Case: Apply bug fix from one branch to another without full merge
Create Aliases
# Shortcut for status
git config --global alias.st status
# Shortcut for checkout
git config --global alias.co checkout
# Shortcut for commit
git config --global alias.cm commit
# Shortcut for branch
git config --global alias.br branch
# Pretty log
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
Usage:
git st # instead of git status
git co main # instead of git checkout main
git lg # beautiful log output
Best Practices
Commit Hygiene
DO:
Commit frequently (small, logical units)
Write descriptive commit messages
Test before committing
Commit related changes together
Use present tense in messages
DON'T:
Commit commented code
Commit sensitive data (keys, passwords)
Make massive commits with unrelated changes
Use vague messages ("fix", "update")
Commit broken code to main
Branch Management
Keep Branches Clean:
# List all branches
git branch -a
# Delete merged local branches
git branch -d feature/completed
# Delete remote branch
git push origin --delete feature/old
# Prune stale remote branches
git fetch --prune
Branch Lifecycle:
Create from updated main
Develop and commit
Push for backup/collaboration
Create pull request
Merge after review
Delete immediately
Pull Request Excellence
Before Creating PR:
[ ] Code runs without errors
[ ] Tests pass
[ ] Code follows style guide
[ ] Commits are clean (consider squashing)
[ ] Branch is up-to-date with main
PR Description Template:
## Description
Brief summary of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
How was this tested?
## Screenshots
If applicable
## Related Issues
Fixes #123
Security Practices
Never Commit:
API keys and secrets
Passwords
Database credentials
Private keys
Environment files (.env)
Use .gitignore:
# Environment variables
.env
.env.local
# API keys
config/secrets.yml
credentials.json
# Dependencies
node_modules/
vendor/
# Build outputs
dist/
build/
# IDE files
.vscode/
.idea/
If Accidentally Committed:
# Remove from history (use with caution)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch path/to/sensitive/file" \
--prune-empty --tag-name-filter cat -- --all
# Or use BFG Repo-Cleaner (easier)
bfg --delete-files sensitive-file.txt
Quick Reference
Daily Workflow Commands
# Start day
git checkout main
git pull origin main
git checkout -b feature/new-work
# During development
git status # Check changes
git add . # Stage changes
git commit -m "Description" # Commit
git push -u origin feature/new-work # First push
# Continue work on existing branch
git checkout feature/existing
git pull origin feature/existing # Get latest
# ... make changes ...
git add .
git commit -m "More updates"
git push # Subsequent pushes
# Merge to main
git checkout main
git pull origin main
git merge feature/new-work
git push origin main
git branch -d feature/new-work
Essential Commands Table
| Command | Purpose | Example |
|---|---|---|
git init |
Create repository | git init |
git clone |
Copy remote repository | git clone <url> |
git status |
Check file states | git status |
git add |
Stage changes | git add . |
git commit |
Save changes | git commit -m "msg" |
git push |
Upload to remote | git push origin main |
git pull |
Download from remote | git pull origin main |
git branch |
Manage branches | git branch -a |
git checkout |
Switch branches | git checkout -b new |
git merge |
Combine branches | git merge feature |
git log |
View history | git log --oneline |
git diff |
See changes | git diff |
git stash |
Save work temporarily | git stash save "WIP" |
git reset |
Undo commits | git reset --soft HEAD~1 |
git revert |
Undo commit (safe) | git revert <hash> |
Common Scenarios
Scenario: Accidentally committed to main instead of feature branch
# Undo commit but keep changes
git reset --soft HEAD~1
# Create feature branch
git checkout -b feature/correct-branch
# Commit again
git commit -m "Feature work"
Scenario: Need to switch branches with uncommitted changes
# Stash changes
git stash
# Switch branch
git checkout other-branch
# Return and restore
git checkout original-branch
git stash pop
Scenario: Pull request has conflicts
# Update feature branch
git checkout feature/my-work
git fetch origin
git merge origin/main
# Resolve conflicts
# ... fix conflicts in files ...
git add .
git commit -m "Resolve merge conflicts"
git push origin feature/my-work
Scenario: Made changes to wrong branch
# Stash changes
git stash
# Switch to correct branch
git checkout correct-branch
# Apply changes
git stash pop
Troubleshooting
Problem: "Permission denied (publickey)"
# Generate SSH key
ssh-keygen -t ed25519 -C "your_email@example.com"
# Add to ssh-agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Copy public key and add to GitHub
cat ~/.ssh/id_ed25519.pub
Problem: "Your branch is ahead of origin/main by X commits"
# Push commits to remote
git push origin main
Problem: "Updates were rejected"
# Pull first, then push
git pull origin main
git push origin main
Problem: Detached HEAD state
# Return to branch
git checkout main
# Or create branch from detached state
git checkout -b new-branch
Learning Resources
Official Documentation:
Pro Git Book - Comprehensive guide
Git Documentation - Command reference
Interactive Learning:
Learn Git Branching - Visual tutorial
GitHub Skills - Hands-on courses
Visualization Tools:
Git Graph Extension - VS Code
GitKraken - GUI client
Cheat Sheets:
Conclusion
Git mastery requires practice and patience. Start with basic commands, gradually incorporate branching, and eventually explore advanced features like rebase and interactive staging.
Key Takeaways:
Commit often - Small, focused commits are easier to manage
Branch liberally - Isolate work to prevent conflicts
Pull frequently - Stay synchronized with team
Review carefully - Use
git statusandgit diffconstantlyCommunicate clearly - Write meaningful messages and PR descriptions
Next Steps:
Practice commands in a test repository
Create a personal .gitconfig with aliases
Integrate Git into your daily workflow
Contribute to open source projects
Explore advanced workflows (Git Flow, trunk-based development)
NOTE: Every Git expert started as a beginner. The commands that seem complex now will become second nature with consistent practice.
Happy coding! and Gitting!


Top comments (0)