DaleSchool

History Exploration and Advanced Features

Beginner25min

Learning Objectives

  • Use advanced git log search options
  • Track code change history with git blame
  • Find the bug-introducing commit with git bisect
  • Cherry-pick specific commits with git cherry-pick

Working Code

Example 1: Advanced git log searches

Set up a repository with some history:

git init
echo "v1" > app.py && git add app.py && git commit -m "feat: initial app"
echo "login" >> app.py && git add app.py && git commit -m "feat: add login feature"
echo "bug fix" >> app.py && git add app.py && git commit -m "fix: fix login bug"
echo "profile" >> app.py && git add app.py && git commit -m "feat: add profile page"
echo "style" >> app.py && git add app.py && git commit -m "style: format code"

Search by commit message:

git log --grep="feat" --oneline

Output:

e4f5g6h feat: add profile page
b2c3d4e feat: add login feature
a1b2c3d feat: initial app

Find commits that changed specific content:

# Commits where "login" was added or removed
git log -S "login" --oneline

Output:

c3d4e5f fix: fix login bug
b2c3d4e feat: add login feature

Example 2: Search by author

git log --author="John Doe" --oneline

# Date range
git log --after="2024-01-01" --before="2024-02-01" --oneline

# History of a specific file
git log --oneline app.py

Example 3: git blame

See who wrote each line and when:

git blame app.py

Output:

a1b2c3d (John Doe  2024-01-15 10:30:01 +0900 1) v1
b2c3d4e (John Doe  2024-01-15 10:31:00 +0900 2) login
c3d4e5f (Jane Kim  2024-01-16 09:00:00 +0900 3) bug fix
e4f5g6h (John Doe  2024-01-17 14:00:00 +0900 4) profile

Each line shows:

  • Commit hash (first 8 characters)
  • Author
  • Date/time
  • Line number
  • Content

Try It Yourself

git log -S: tracking specific code changes

When you need to find "when was this code added?":

# Commits where "getUserById" was added or removed
git log -S "getUserById" --oneline

# Include the full diff
git log -S "getUserById" -p

# Regex search
git log -G "user.*[Bb]y[Ii]d" --oneline

git blame in depth

# Specific line range only (lines 10-20)
git blame -L 10,20 app.py

# Shorter hashes
git blame --abbrev=7 app.py

# Ignore whitespace changes
git blame -w app.py

Using blame results to explore history:

git blame app.py
# c3d4e5f (Jane Kim ...) 3) bug fix

# View that commit in detail
git show c3d4e5f

# View blame before that commit
git blame c3d4e5f~1 app.py

git cherry-pick: grabbing specific commits

Apply a specific commit from another branch to the current branch:

git checkout -b feature-a
echo "Feature A" >> app.py && git add app.py && git commit -m "feat: add feature A"
echo "Bug fix A" >> app.py && git add app.py && git commit -m "fix: fix feature A bug"

git checkout main
git log --oneline --all

Output:

f1g2h3i (feature-a) fix: fix feature A bug
e0f1g2h (feature-a) feat: add feature A
a1b2c3d (HEAD -> main) style: format code
...

Bring only the bug fix to main:

git cherry-pick f1g2h3i   # Pick only the fix commit
git log --oneline

Output:

j0k1l2m (HEAD -> main) fix: fix feature A bug  <- Copied with a new hash
a1b2c3d style: format code

Cherry-pick copies a commit. The original stays on its branch and the copy gets a new hash on the current branch.

Cherry-picking multiple commits:

# Pick 2 commits
git cherry-pick a1b2c3d e4f5g6h

# Pick a range (a exclusive, b inclusive)
git cherry-pick a1b2c3d..e4f5g6h

# Pick a range (a inclusive)
git cherry-pick a1b2c3d^..e4f5g6h

git bisect: finding the bug-introducing commit

"This feature broke at some point. Which commit caused it?"

# Start bisect
git bisect start
git bisect bad HEAD           # Current state: has the bug
git bisect good a1b2c3d      # This commit was working fine

# Git auto-checks out a middle commit
# Test and report the result
git bisect good   # This commit works
# or
git bisect bad    # This commit has the bug

# After a few rounds, Git pinpoints the guilty commit
# Return to normal
git bisect reset

"Why?" -- When you need history exploration

| Scenario | Tool | | ------------------------------------------------- | ------------------- | | "When was this feature added?" | git log -S "code" | | "Who wrote this line?" | git blame | | "When did this bug start?" | git bisect | | "I need just that one commit from another branch" | git cherry-pick | | "Show me only this person's commits" | git log --author |

Real-world debugging scenario

# 1. Bug found: a function behaves incorrectly
# 2. Find who last touched it with blame
git blame -L 45,60 src/auth.js

# 3. Inspect that commit
git show c3d4e5f

# 4. Compare before and after
git diff c3d4e5f~1 c3d4e5f

# 5. Narrow the range with bisect
git bisect start
git bisect bad HEAD
git bisect good v1.0.0

Common Mistakes

Mistake 1: Not knowing how to handle cherry-pick conflicts

git cherry-pick f1g2h3i   # Conflict occurs
# CONFLICT: ...

# Resolve the conflict, then
git add filename
git cherry-pick --continue

# Or abort
git cherry-pick --abort

Mistake 2: Confusing git log -S and --grep

# --grep: searches commit MESSAGES
git log --grep="login"   # Commits with "login" in the message

# -S: searches code CHANGES
git log -S "login"       # Commits where "login" was added/removed in the code

Mistake 3: Using blame to assign blame

The purpose of git blame is to understand code context, not to find someone to blame. Check the commit message and PR to understand why the code was written that way.

Deep Dive

Customizing git log --format
# Hash, author, date, message
git log --format="%h %an %ar %s"

# Colorized output
git log --format="%C(yellow)%h%C(reset) %C(blue)%an%C(reset) %s"

# Register as an alias
git config --global alias.lg "log --format='%C(yellow)%h%C(reset) %C(blue)%an%C(reset) %ar %s' --graph --all"
git lg
git shortlog: contributor summary
# Commit count by contributor
git shortlog -sn

# For a specific time period
git shortlog -sn --after="2024-01-01"

Output:

    45  John Doe
    23  Jane Kim
    12  Bob Lee

Useful for open-source contributor lists or team activity summaries.

git stash vs cherry-pick vs patch

Ways to move code between branches:

# cherry-pick: copy a specific commit
git cherry-pick commit-hash

# patch: export changes as a file and apply
git format-patch -1 commit-hash
git am 0001-commit-message.patch

# Quick file copy
git show commit-hash:path/file.txt > copy.txt
  1. Create several commits and search for feat commits with git log --grep="feat" --oneline.
  2. Find commits that changed specific code with git log -S "specific-code" --oneline.
  3. Run git blame filename to see each line's author and commit.
  4. Create a feature branch with 2 commits, then use git cherry-pick commit-hash to bring just one to main.
  5. Simulate git bisect (create multiple commits, then alternate between good/bad to find the guilty commit).

Q1. What is the difference between git log -S "getUserById" and git log --grep="getUserById"?

  • A) -S searches authors, --grep searches content
  • B) -S finds commits where the text was added/removed in code, --grep searches commit messages
  • C) -S is a fast search, --grep is an exact search
  • D) Both commands show the same result