DEV Community

Cover image for The Complete Git & GitHub Developer Guide
Mohammad Aman
Mohammad Aman

Posted on

The Complete Git & GitHub Developer Guide

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Windows:

  1. Download from gitforwindows.org

  2. Run installer

  3. 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
Enter fullscreen mode Exit fullscreen mode

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:

Image


Core Commands

Initialize Repository

git init
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Commit Message Best Practices:

Good Examples:

"Fix login button alignment on mobile"
"Add email validation to signup form"
"Refactor database connection logic"
Enter fullscreen mode Exit fullscreen mode

Bad Examples:

"updates"
"fixed stuff"
"changes"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Navigation:

  • Arrow keys: Scroll

  • q: Exit

  • /pattern: Search

  • n: 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

Image git branch

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
Enter fullscreen mode Exit fullscreen mode

Critical Rule: Always verify your current branch before committing

git branch  # Shows current branch
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Undoing Changes

Discard Working Directory Changes

# Discard changes in specific file
git checkout -- <filename>

# Discard all changes
git checkout -- .
Enter fullscreen mode Exit fullscreen mode

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 .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 back

  • HEAD~3: 3 commits back

  • HEAD^: Parent commit


Revert vs Reset

Revert creates new commit that undoes changes:

git revert <commit-hash>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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  │                     │
└─────────────────────┘           └─────────────────────┘
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

"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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Push feature branch to remote

  2. Navigate to repository on GitHub

  3. Click "Compare & pull request" (yellow banner)

  4. Fill out PR template:

* Descriptive title

* Summary of changes

* Screenshots (if UI changes)

* Related issues/tickets
Enter fullscreen mode Exit fullscreen mode
  1. Request reviewers

  2. Address feedback with new commits

  3. Merge when approved (Squash/Merge/Rebase)

  4. 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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

2. Identify Conflicted Files:

git status
# Shows: both modified: app.js
Enter fullscreen mode Exit fullscreen mode

3. Open Conflicted File:

function login(user) {
<<<<<<< HEAD
  return authenticateWithOAuth(user);
=======
  return authenticateWithJWT(user);
>>>>>>> feature/login
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

5. Mark as Resolved:

git add app.js
Enter fullscreen mode Exit fullscreen mode

6. Complete Merge:

git commit  # Opens editor with default merge message
# or
git commit -m "Merge feature/login - use JWT authentication"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Advanced Techniques

Rebase

Purpose: Rewrite commit history for cleaner, linear progression

Basic Rebase:

# On feature branch
git rebase main
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Interactive Rebase

Edit commit history:

# Rebase last 3 commits
git rebase -i HEAD~3
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Common Use Cases:

Squash Multiple Commits:

pick a1b2c3d Add login feature
squash e4f5g6h Fix typo in login
squash i7j8k9l Update login tests
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

After Changes:

# If conflicts occur
git add <resolved-files>
git rebase --continue

# Abort rebase
git rebase --abort
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Usage:

git st      # instead of git status
git co main # instead of git checkout main
git lg      # beautiful log output
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Branch Lifecycle:

  1. Create from updated main

  2. Develop and commit

  3. Push for backup/collaboration

  4. Create pull request

  5. Merge after review

  6. 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
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Scenario: Made changes to wrong branch

# Stash changes
git stash

# Switch to correct branch
git checkout correct-branch

# Apply changes
git stash pop
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Problem: "Your branch is ahead of origin/main by X commits"

# Push commits to remote
git push origin main
Enter fullscreen mode Exit fullscreen mode

Problem: "Updates were rejected"

# Pull first, then push
git pull origin main
git push origin main
Enter fullscreen mode Exit fullscreen mode

Problem: Detached HEAD state

# Return to branch
git checkout main

# Or create branch from detached state
git checkout -b new-branch
Enter fullscreen mode Exit fullscreen mode

Learning Resources

Official Documentation:

Interactive Learning:

Visualization Tools:

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:

  1. Commit often - Small, focused commits are easier to manage

  2. Branch liberally - Isolate work to prevent conflicts

  3. Pull frequently - Stay synchronized with team

  4. Review carefully - Use git status and git diff constantly

  5. Communicate 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)