# Rebase = replay commits on top of another branch
# Result: LINEAR history (vs merge = branch graph)
# Before rebase:
main A ── B ── C
feature A ── B ── D ── E
# After: git rebase main (on feature branch)
main A ── B ── C
feature A ── B ── C ── D' ── E' (D,E replayed on top of C)
# Commands
git switch feature/login
git rebase main # rebase feature onto latest main
# Interactive rebase — rewrite history (local commits only!)
git rebase -i HEAD~3 # last 3 commits
# In editor:
# pick abc1234 add login form
# pick def5678 fix typo
# pick ghi9012 add validation
# Change to:
# pick abc1234 add login form
# squash def5678 fix typo ← squash = combine with previous
# reword ghi9012 add validation ← reword = change message
⚠️ Rebase = rewrites history — NEVER rebase commits already pushed to shared branch!
2. git reset — Undo Commits
# git reset — move HEAD and branch pointer backward
# --soft: undo commit, KEEP changes staged
git reset --soft HEAD~1
# → commit gone, files still staged (ready to recommit)
# --mixed (default): undo commit, KEEP changes unstaged
git reset HEAD~1
git reset --mixed HEAD~1 # same
# → commit gone, files unstaged (need to re-add)
# --hard: undo commit, DISCARD changes completely
git reset --hard HEAD~1
# ⚠️ Changes GONE — use carefully!
# Use cases:
git reset --soft HEAD~1 # "I want to redo the commit message"
git reset HEAD~1 # "I committed too early, need more changes"
git reset --hard HEAD~1 # "This commit was totally wrong, throw it away"
# Reset to specific commit
git reset --hard abc1234
# SAFE alternative: git revert (keeps history, adds new commit)
git revert HEAD # creates new "undo" commit — safe for pushed commits
3. git reflog — Emergency Recovery
# reflog = git's safety net — records EVERY HEAD movement
git reflog
# abc1234 HEAD@{0}: commit: add footer
# def5678 HEAD@{1}: reset: moving to HEAD~2 ← oops!
# ghi9012 HEAD@{2}: commit: add contact page ← want this back!
# Recover lost commits!
git reset --hard ghi9012 # restore to that point
# OR
git switch -c recovery-branch ghi9012 # create branch from lost commit
# reflog saves for ~90 days by default
# "git reset --hard" nightmare? reflog will save you!
# View branch-specific reflog
git reflog show main
💡 "I lost my commits with git reset --hard!" → git reflog → restore → 안전!
4. Tags — Version Releases
# Tag = named pointer to a specific commit (releases)
# v1.0.0, v2.1.3, etc.
# Lightweight tag (just a pointer)
git tag v1.0.0
# Annotated tag (recommended — includes message + metadata)
git tag -a v1.0.0 -m "Version 1.0.0 — first stable release"
# Tag specific commit
git tag -a v0.9.0 abc1234 -m "Beta release"
# List tags
git tag
git tag -l "v1.*" # filter pattern
# View tag details
git show v1.0.0
# Push tags to GitHub
git push origin v1.0.0 # push one tag
git push origin --tags # push all tags
# Delete tag
git tag -d v0.1.0 # local
git push origin --delete v0.1.0 # remote
5. Useful Git Tricks
# Aliases — shortcuts for long commands
git config --global alias.st "status"
git config --global alias.co "checkout"
git config --global alias.br "branch"
git config --global alias.lg "log --oneline --graph --all"
# Now: git lg, git st, git co main
# git blame — who wrote each line?
git blame src/app.js
# abc1234 (Ko Ko 2024-01-15) const app = express();
# def5678 (Ma Ma 2024-01-20) app.use(express.json());
# git bisect — binary search for bug
git bisect start
git bisect bad # current commit has bug
git bisect good v1.0.0 # this version was OK
# Git checks out midpoint → you test → mark good/bad
# Repeats until finds first bad commit!
git bisect reset # end bisect
# Search commit messages
git log --grep="login" --oneline
# Search code changes
git log -S "username" --oneline # commits that added/removed "username"
git log -G "function login" --oneline # regex search
# Show files changed in commit
git show --name-only abc1234
git diff HEAD~1 HEAD --name-only