005 — Git Cheatsheet

📦 Git is a version control system that tracks changes to your code. GitHub is the platform where we host our repositories remotely. This cheatsheet covers the workflow you'll use during the bootcamp.


Table of Contents

  1. Core Concepts
  2. SSH vs HTTPS
  3. Bootcamp Workflow: Clone → Change Remote → Push
  4. Essential Git Commands
  5. Branching
  6. Undoing Mistakes
  7. Working with Remotes
  8. Git Configuration
  9. Common Issues & Fixes
  10. Quick Reference Card

1. Core Concepts

┌──────────────────────────────────────────────────────────────┐
│                     GIT MENTAL MODEL                           │
├──────────────────────────────────────────────────────────────┤
│                                                               │
│  Working Directory ──add──▶ Staging Area ──commit──▶ Local Repo ──push──▶ Remote (GitHub)
│  (your files)              (ready to save)          (history)           (shared)
│                                                               │
│  ◄──checkout──             ◄──reset──              ◄──pull──  │
│                                                               │
├──────────────────────────────────────────────────────────────┤
│                                                               │
│  Repository (repo) = Project folder tracked by Git            │
│  Commit            = Snapshot of your code at a point in time │
│  Branch            = Independent line of development          │
│  Remote            = A copy of the repo on GitHub             │
│  Clone             = Download a repo to your machine          │
│  Pull              = Download + merge latest changes          │
│  Push              = Upload your commits to remote            │
│                                                               │
└──────────────────────────────────────────────────────────────┘

How Clone + Change Remote Relates

┌─────────────────────────────────────────────────────────────┐
│                        GITHUB                                │
│                                                              │
│   devopsmalaysia/bootcamp        USERNAME/bootcamp            │
│   (source repo)                  (YOUR repo — empty at first)│
│        │                              ▲                      │
│        │                              │                      │
└────────┼──────────────────────────────┼──────────────────────┘
         │                              │
    clone│                         push │
         ▼                              │
┌──────────────────────────────────────────────────────────────┐
│                    YOUR LOCAL MACHINE                          │
│                                                               │
│   ~/bootcamp/                                                 │
│   (cloned from devopsmalaysia, remote changed to YOUR repo)   │
│                                                               │
│   origin → git@github.com:USERNAME/bootcamp.git               │
│   upstream → git@github.com:devopsmalaysia/bootcamp.git       │
│              (optional, for syncing instructor updates)        │
│                                                               │
└──────────────────────────────────────────────────────────────┘

2. SSH vs HTTPS

Comparison

FeatureSSHHTTPS
URL formatgit@github.com:user/repo.githttps://github.com/user/repo.git
AuthenticationSSH key (automatic)Username + token (every time)
SetupOne-time key setupToken management
Recommended✅ Yes (use this)Only if SSH is blocked
Firewall-friendlyMay be blocked on port 22Always works (port 443)

How to Tell Which You're Using

# Check remote URL
git remote -v

# SSH (✅ what we want):
# origin  git@github.com:your-username/bootcamp.git (fetch)
# origin  git@github.com:your-username/bootcamp.git (push)

# HTTPS (❌ switch to SSH):
# origin  https://github.com/your-username/bootcamp.git (fetch)
# origin  https://github.com/your-username/bootcamp.git (push)

Switch from HTTPS to SSH

git remote set-url origin git@github.com:your-username/bootcamp.git

Switch from SSH to HTTPS (fallback)

git remote set-url origin https://github.com/your-username/bootcamp.git

SSH Over HTTPS Port (If Port 22 is Blocked)

Some networks block port 22. You can tunnel SSH through port 443:

Add to ~/.ssh/config:

Host github.com
    HostName ssh.github.com
    Port 443
    User git
    IdentityFile ~/.ssh/id_ed25519

Test:

ssh -T git@github.com

3. Bootcamp Workflow: Clone → Change Remote → Push

Step 1: Create an Empty Repository on GitHub

  1. Go to: https://github.com/new
  2. Repository name: bootcamp
  3. Visibility: Public
  4. ⚠️ Do NOT check "Add a README file"
  5. ⚠️ Do NOT add .gitignore or license
  6. Click Create repository

You now have an empty repo at https://github.com/YOUR_USERNAME/bootcamp

Step 2: Clone the Source Repository

Clone the instructor's repository (contains the full bootcamp codebase):

git clone git@github.com:devopsmalaysia/bootcamp.git

Navigate into the project:

cd bootcamp

At this point, the remote origin points to the instructor's repo:

git remote -v
# origin  git@github.com:devopsmalaysia/bootcamp.git (fetch)
# origin  git@github.com:devopsmalaysia/bootcamp.git (push)

Step 3: Change Remote to YOUR Repository

Replace the origin with your own repository:

git remote set-url origin git@github.com:YOUR_USERNAME/bootcamp.git

Verify:

git remote -v
# origin  git@github.com:YOUR_USERNAME/bootcamp.git (fetch)
# origin  git@github.com:YOUR_USERNAME/bootcamp.git (push)

⚠️ Replace YOUR_USERNAME with your actual GitHub username.

Step 4: Push to YOUR Repository

git push origin main

Visit https://github.com/YOUR_USERNAME/bootcamp — you should see all project files. 🎉

Step 5: (Optional) Add Upstream for Future Updates

If you want to sync instructor updates later:

git remote add upstream git@github.com:devopsmalaysia/bootcamp.git

Verify all remotes:

git remote -v
# origin    git@github.com:YOUR_USERNAME/bootcamp.git (fetch)
# origin    git@github.com:YOUR_USERNAME/bootcamp.git (push)
# upstream  git@github.com:devopsmalaysia/bootcamp.git (fetch)
# upstream  git@github.com:devopsmalaysia/bootcamp.git (push)

Complete Bootcamp Workflow Diagram

┌─────────── ONE TIME SETUP ──────────────────────────────┐
│                                                          │
│  1. Create empty "bootcamp" repo on GitHub               │
│  2. git clone git@github.com:devopsmalaysia/bootcamp.git │
│  3. cd bootcamp                                          │
│  4. git remote set-url origin git@github.com:YOU/bootcamp.git │
│  5. git push origin main                                 │
│  6. (optional) git remote add upstream git@github.com:devopsmalaysia/... │
│                                                          │
└──────────────────────────────────────────────────────────┘

┌─────────── DAILY WORKFLOW ──────────────────────────────┐
│                                                          │
│  1. git pull origin main          (get your latest)      │
│  2. (make changes)                                       │
│  3. git add .                     (stage changes)        │
│  4. git commit -m "message"       (save snapshot)        │
│  5. git push origin main          (upload to GitHub)     │
│                                                          │
│  → GitHub Actions auto-triggers → Images built → VPS     │
│                                                          │
└──────────────────────────────────────────────────────────┘

┌─────────── SYNC WITH INSTRUCTOR (optional) ─────────────┐
│                                                          │
│  1. git fetch upstream                                   │
│  2. git merge upstream/main                              │
│  3. git push origin main                                 │
│                                                          │
└──────────────────────────────────────────────────────────┘

4. Essential Git Commands

4.1 Getting Information

CommandDescription
git statusShow modified/staged/untracked files
git logShow commit history
git log --onelineCompact commit history
git log --oneline -10Last 10 commits
git log --graph --onelineVisual branch graph
git diffShow unstaged changes
git diff --stagedShow staged changes
git diff HEAD~1Changes since last commit
git show COMMIT_HASHShow specific commit details
git blame filenameWho changed each line

4.2 Making Changes

CommandDescription
git add file.txtStage a specific file
git add .Stage all changes
git add -pInteractive staging (chunk by chunk)
git commit -m "message"Commit with message
git commit -am "message"Stage tracked files + commit
git commit --amendModify the last commit
git commit --amend -m "new msg"Change last commit message

4.3 Commit Message Convention

type: short description

# Types:
feat:     New feature
fix:      Bug fix
docs:     Documentation only
style:    Formatting (no code change)
refactor: Code restructuring
test:     Adding tests
chore:    Maintenance (deps, config)
ci:       CI/CD changes

Examples:

git commit -m "feat: add Docker deployment configuration"
git commit -m "fix: resolve database connection timeout"
git commit -m "docs: update README with setup instructions"
git commit -m "ci: enable automated deployments"
git commit -m "chore: update dependencies"

4.4 Syncing with Remote

CommandDescription
git pushPush current branch to remote
git push origin mainPush main to origin
git push -u origin mainPush + set upstream tracking
git pullFetch + merge from remote
git pull origin mainPull specific branch
git fetchDownload changes without merging
git fetch --allFetch from all remotes

5. Branching

5.1 Branch Commands

CommandDescription
git branchList local branches
git branch -aList all branches (local + remote)
git branch feature-xCreate new branch
git checkout feature-xSwitch to branch
git checkout -b feature-xCreate + switch (shortcut)
git switch feature-xSwitch (newer syntax)
git switch -c feature-xCreate + switch (newer syntax)
git branch -d feature-xDelete branch (safe)
git branch -D feature-xDelete branch (force)
git push origin --delete feature-xDelete remote branch

5.2 Feature Branch Workflow

# 1. Start from latest main
git checkout main
git pull origin main

# 2. Create feature branch
git checkout -b feature/add-watchtower

# 3. Make changes and commit
git add .
git commit -m "feat: add watchtower for auto-updates"

# 4. Push feature branch
git push origin feature/add-watchtower

# 5. Create Pull Request on GitHub (optional)

# 6. After merge, clean up
git checkout main
git pull origin main
git branch -d feature/add-watchtower

5.3 Merge vs Rebase (Simple Explanation)

# Merge: combines branches (creates merge commit)
git checkout main
git merge feature-x

# Rebase: replays your commits on top of main (cleaner history)
git checkout feature-x
git rebase main

For the bootcamp: Just use git merge or work directly on main. Don't worry about rebase.


6. Undoing Mistakes

6.1 "I haven't committed yet"

# Discard changes to a specific file
git checkout -- filename.txt
# Or (newer syntax):
git restore filename.txt

# Discard ALL uncommitted changes
git checkout -- .
# Or:
git restore .

# Unstage a file (keep changes, remove from staging)
git reset HEAD filename.txt
# Or:
git restore --staged filename.txt

# Unstage everything
git reset HEAD .

6.2 "I committed but haven't pushed"

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

# Undo last commit, keep changes unstaged
git reset HEAD~1

# Undo last commit, discard changes completely ⚠️
git reset --hard HEAD~1

# Undo last 3 commits
git reset --soft HEAD~3

# Change last commit message
git commit --amend -m "corrected message"

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

6.3 "I already pushed"

# Create a NEW commit that undoes the previous one (safe)
git revert HEAD
git push

# Force push to rewrite history (⚠️ use cautiously with shared branches)
git reset --hard HEAD~1
git push --force-with-lease

6.4 "I committed to the wrong branch"

# Move last commit to a new branch
git branch correct-branch    # Create branch at current position
git reset --hard HEAD~1      # Remove commit from current branch
git checkout correct-branch  # Switch to correct branch

6.5 "I need to temporarily save work"

# Stash uncommitted changes
git stash

# Stash with a description
git stash push -m "WIP: database config"

# List stashes
git stash list

# Apply most recent stash (keep in stash list)
git stash apply

# Apply and remove from stash list
git stash pop

# Apply specific stash
git stash apply stash@{2}

# Drop a stash
git stash drop stash@{0}

# Clear all stashes
git stash clear

7. Working with Remotes

7.1 Remote Management

CommandDescription
git remote -vList remotes with URLs
git remote add NAME URLAdd new remote
git remote remove NAMERemove remote
git remote rename old newRename remote
git remote set-url origin URLChange remote URL
git remote show originDetailed remote info

7.2 Typical Remote Setup for Bootcamp

# After cloning and changing remote:
git remote -v
# origin    git@github.com:YOUR_USERNAME/bootcamp.git (fetch)
# origin    git@github.com:YOUR_USERNAME/bootcamp.git (push)

# Add instructor's repo as upstream (optional):
git remote add upstream git@github.com:devopsmalaysia/bootcamp.git

# Now you have:
# origin   = YOUR repo (you push here)
# upstream = instructor's repo (you pull from here for updates)

7.3 Syncing with Upstream

If the instructor pushes updates to the original source repo:

# Get latest from instructor
git fetch upstream

# View what's different
git log HEAD..upstream/main --oneline

# Merge instructor's changes into your main
git checkout main
git merge upstream/main

# If there are conflicts, resolve them, then:
git add .
git commit -m "merge: sync with upstream"

# Push to your repo
git push origin main

7.4 Force Push (When Needed)

# Safe force push (fails if someone else pushed)
git push --force-with-lease

# Dangerous force push (overwrites everything) ⚠️
git push --force

⚠️ Never force push to a shared branch unless you know what you're doing.


8. Git Configuration

8.1 Essential Setup

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

# Default branch name
git config --global init.defaultBranch main

# Better diff output
git config --global diff.colorMoved zebra

# Auto-correct typos (waits 1.5s before executing)
git config --global help.autocorrect 15

8.2 Useful Aliases

# Short status
git config --global alias.s "status -sb"

# Pretty log
git config --global alias.lg "log --oneline --graph --decorate -20"

# Unstage shortcut
git config --global alias.unstage "restore --staged"

# Last commit
git config --global alias.last "log -1 HEAD --stat"

# Quick amend (no message edit)
git config --global alias.oops "commit --amend --no-edit"

Usage:

git s          # Short status
git lg         # Pretty graph log
git unstage .  # Unstage all files
git last       # Show last commit
git oops       # Amend last commit silently

8.3 View Configuration

# Show all config
git config --global --list

# Show specific value
git config --global user.email

# Show where config is stored
git config --list --show-origin

8.4 .gitignore

Files/folders to exclude from version control:

# Environment files (contain secrets!)
.env
.env.local
.env.production

# Dependencies
node_modules/
.pnpm-store/

# Build outputs
dist/
.next/
bin/
obj/

# OS files
.DS_Store
Thumbs.db

# IDE
.vscode/
.idea/
*.swp

# Docker
docker-compose.override.yml

Check if a file is ignored:

git check-ignore -v filename

9. Common Issues & Fixes

9.1 "Permission denied (publickey)" on Push/Pull

Cause: SSH key not configured for GitHub.

# Test SSH connection
ssh -T git@github.com

# If it fails, check:
ssh-add -l                    # Is key loaded?
cat ~/.ssh/id_ed25519.pub     # Does it match GitHub?

# Fix: reload key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

Also verify remote URL uses SSH:

git remote -v
# Should show: git@github.com:... (NOT https://...)

# Fix if HTTPS:
git remote set-url origin git@github.com:YOUR_USERNAME/bootcamp.git

9.2 "fatal: not a git repository"

Cause: You're not inside a git-tracked folder.

# Check current directory
pwd

# Navigate to your project
cd ~/bootcamp

# Verify it's a git repo
ls -la .git/

9.3 "error: failed to push some refs"

Cause: Remote has changes you don't have locally.

# Pull first, then push
git pull origin main
git push origin main

# If pull creates a merge conflict, see section 9.6

Or if you want to rebase (cleaner history):

git pull --rebase origin main
git push origin main

9.4 "fatal: refusing to merge unrelated histories"

Cause: Trying to merge two repos that have no common ancestor.

git pull origin main --allow-unrelated-histories

9.5 "Your branch is ahead of 'origin/main' by X commits"

Cause: You have local commits that haven't been pushed.

# Just push them
git push origin main

9.6 Merge Conflicts

What it looks like:

<<<<<<< HEAD
your local changes
=======
changes from remote
>>>>>>> origin/main

How to resolve:

# 1. Open the conflicting file(s)
git status   # Shows which files have conflicts

# 2. Edit the file — keep what you want, remove the markers
#    Remove <<<<<<< HEAD, =======, and >>>>>>> lines

# 3. Stage the resolved file
git add filename.txt

# 4. Complete the merge
git commit -m "merge: resolve conflict in filename.txt"

# 5. Push
git push origin main

Abort a merge (go back to before the merge):

git merge --abort

9.7 "Changes not staged for commit" / Dirty Working Directory

# See what's modified
git status

# Option A: Commit the changes
git add .
git commit -m "save current work"

# Option B: Discard the changes
git restore .

# Option C: Stash for later
git stash

9.8 Accidentally Committed Secrets / .env File

# Remove from git tracking (keep local file)
git rm --cached .env
echo ".env" >> .gitignore
git add .gitignore
git commit -m "fix: remove .env from tracking"
git push

# ⚠️ If you pushed secrets to a public repo:
# 1. Rotate/regenerate ALL exposed credentials immediately
# 2. The secret is in git history forever (even after deletion)
# 3. Consider using: git filter-branch or BFG Repo Cleaner

9.9 "detached HEAD state"

Cause: You checked out a specific commit instead of a branch.

# Get back to main branch
git checkout main

# If you made changes in detached state, save them:
git stash
git checkout main
git stash pop

9.10 Large Files / Slow Push

# Check what's taking space
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sort -k3 -n | tail -20

# If node_modules got committed accidentally:
git rm -r --cached node_modules
echo "node_modules/" >> .gitignore
git add .gitignore
git commit -m "fix: remove node_modules from tracking"

9.11 WSL: Line Ending Issues (CRLF vs LF)

Symptom: Git shows every file as modified even though you changed nothing.

# Configure Git to handle line endings
git config --global core.autocrlf input    # WSL/macOS
# git config --global core.autocrlf true   # Windows native (not WSL)

# Fix existing repo
git rm --cached -r .
git reset --hard

9.12 "RPC failed; HTTP 400 curl 22"

Cause: Push too large (big files or many commits).

# Increase Git buffer size
git config --global http.postBuffer 524288000

# Push in smaller batches
git push origin main --force-with-lease

10. Quick Reference Card

The 5 Commands You'll Use 90% of the Time

git status                    # What changed?
git add .                     # Stage everything
git commit -m "message"       # Save snapshot
git push origin main          # Upload to GitHub
git pull origin main          # Download latest

Bootcamp Day — Complete Flow

# ─── INITIAL SETUP (once) ──────────────────────────────
# Create empty "bootcamp" repo on GitHub, then:
git clone git@github.com:devopsmalaysia/bootcamp.git
cd bootcamp
git remote set-url origin git@github.com:YOUR_USERNAME/bootcamp.git
git push origin main
# (optional) git remote add upstream git@github.com:devopsmalaysia/bootcamp.git

# ─── MAKE CHANGES & DEPLOY ─────────────────────────────
# Edit your files (.env, docker-compose, etc.)
git add .
git commit -m "feat: configure deployment"
git push origin main
# → GitHub Actions triggers → Images built → VPS auto-updates!

# ─── GET INSTRUCTOR UPDATES (if upstream added) ────────
git fetch upstream
git merge upstream/main
git push origin main

# ─── CHECK WHAT HAPPENED ───────────────────────────────
git status              # Current state
git log --oneline -5    # Last 5 commits
git remote -v           # Verify remotes

Emergency Commands

# "I want to undo everything I just did"
git reset --hard HEAD

# "I want to go back to what's on GitHub"
git fetch origin
git reset --hard origin/main

# "I committed secrets, make it go away"
git reset --soft HEAD~1
git rm --cached .env
git commit -m "remove secrets"
git push --force-with-lease

# "Everything is broken, start fresh"
cd ..
rm -rf bootcamp
git clone git@github.com:devopsmalaysia/bootcamp.git
cd bootcamp
git remote set-url origin git@github.com:YOUR_USERNAME/bootcamp.git
git push --force origin main

# "I want to save my work but switch tasks"
git stash push -m "WIP: my changes"
# (do other stuff)
git stash pop

Status Symbols Explained

git status

# ?? file.txt    → Untracked (new file, not in git)
# M  file.txt    → Modified (changed since last commit)
# A  file.txt    → Added (staged for commit)
# D  file.txt    → Deleted
# R  file.txt    → Renamed
# UU file.txt    → Conflict (needs manual resolution)

Visual: Git Stages

┌──────────────┐    git add     ┌──────────────┐   git commit   ┌──────────────┐   git push    ┌──────────┐
│   WORKING    │ ──────────────▶│   STAGING    │ ─────────────▶ │    LOCAL     │ ────────────▶│  REMOTE  │
│  DIRECTORY   │                │    AREA      │                │  REPOSITORY  │              │ (GitHub) │
│              │                │              │                │              │              │          │
│ (your edits) │ ◀──── git restore ──── │    │ ◀── git reset ─┘              │ ◀─ git pull ─┘          │
└──────────────┘                └──────────────┘                └──────────────┘              └──────────┘

CI/CD Trigger: How Push Triggers Deployment

After you git push origin main, the following happens automatically:

┌─────────────────────────────────────────────────────────────┐
│                                                              │
│  YOU: git push origin main                                   │
│        │                                                     │
│        ▼                                                     │
│  GITHUB: detects push to main branch                         │
│        │                                                     │
│        ▼                                                     │
│  GITHUB ACTIONS: .github/workflows/deploy.yml runs           │
│        │  • Builds Docker images (api, web, admin)           │
│        │  • Pushes to ghcr.io/USERNAME/bootcamp/...          │
│        │                                                     │
│        ▼                                                     │
│  GHCR: new :latest images available                          │
│        │                                                     │
│        ▼ (within ~5 minutes)                                 │
│  WATCHTOWER (on VPS): detects new images                     │
│        │  • Pulls new images                                 │
│        │  • Stops old containers                             │
│        │  • Starts new containers                            │
│        │                                                     │
│        ▼                                                     │
│  🎉 YOUR APP IS UPDATED! (zero SSH required)                 │
│                                                              │
└─────────────────────────────────────────────────────────────┘

You don't need to SSH into the server. Just push code and wait ~5-10 minutes.

Built with LogoFlowershow