Git Navigation Brownbag

Exploring Code with Command Line

A guide to navigating source code using Git commands for read-only exploration

Setup: Clone the example repository first:
git clone https://github.com/apache/kafka.git
cd kafka

Understanding Git Concepts

Branches, HEAD, and Origin

Before diving into navigation commands, let's clarify some key Git concepts.

Local vs Remote Branches

Local Branches

  • What: Branches on your machine
  • Where: In your local .git folder
  • View: git branch
  • Example: trunk, my-feature

Remote Branches

  • What: References to server branches
  • Where: References in local .git
  • View: git branch -r
  • Example: origin/trunk, origin/4.0
Key Point: Remote branches are read-only snapshots of what was on the server when you last fetched.

Branch Comparison Example

# Local branches - you can modify these
git branch
* trunk
  my-local-branch

# Remote branches - read-only references
git branch -r
  origin/trunk
  origin/4.0
  origin/3.9
  origin/3.8

# All branches together
git branch -a
* trunk                    # Local branch (current)
  my-local-branch         # Local branch  
  remotes/origin/trunk    # Remote branch
  remotes/origin/4.0      # Remote branch

Key Git Terms

HEAD

  • Pointer to current location
  • Usually points to latest commit of current branch
  • HEAD~1 = one commit before
  • HEAD~5 = five commits before

origin

  • Default name for primary remote
  • The server you cloned from
  • Just a nickname - not magic!
  • origin/trunk = trunk branch on origin

Detached HEAD

What it means: HEAD points directly to a commit instead of a branch

When it happens:

git checkout origin/trunk
git checkout 4.0.0
git checkout abc1234

Why it's useful:

  • Safe exploration
  • No branch modifications
  • Perfect for read-only navigation

1. Check Current Branch

Basic Branch Information

# Show current branch name
git branch --show-current

# Alternative: shows current branch with asterisk
git branch

# Show current branch with more detail
git status

Getting More Context

# Show current branch with last commit info
git log --oneline -1

# Show all branches with current marked
git branch -a
Pro tip: Configure your terminal prompt to show the current branch automatically!

2. Switch to Different Branch

Switching to Remote Branches

# List all remote branches first
git branch -r

# Switch to a remote branch (creates detached HEAD)
git checkout origin/trunk
git checkout origin/4.0

# Switch to an existing local branch
git checkout trunk

Ensuring Everything is Updated

# Fetch latest changes from remote before switching
git fetch origin

# Switch after fetching
git fetch origin && git checkout origin/4.0
Important: When checking out remote branches directly, you'll be in "detached HEAD" state, which is perfect for read-only exploration.

Switching to Tags

# List available tags
git tag -l

# Switch to a specific tag
git checkout 4.0.0
git checkout 3.9.1

# Switch to latest tag matching pattern
git checkout $(git describe --tags --abbrev=0)

3. Compare Remote Branches

Basic Branch Comparison

# Compare two remote branches
git diff origin/trunk..origin/4.0

# Show only file names that differ
git diff --name-only origin/trunk..origin/4.0

# Show summary of changes
git diff --stat origin/trunk..origin/4.0

File-Specific Diff Between Branches

# Compare specific file between branches
git diff origin/trunk..origin/4.0 -- build.gradle

# Compare with enhanced options
git diff --word-diff origin/trunk..origin/4.0 -- README.md

# Ignore whitespace changes
git diff -w origin/trunk..origin/4.0 -- build.gradle

Multiple Files & Patterns

# Compare multiple specific files
git diff origin/trunk..origin/4.0 -- build.gradle README.md LICENSE

# Compare all files in a directory
git diff origin/trunk..origin/4.0 -- clients/src/main/java/

# Compare files matching a pattern
git diff origin/trunk..origin/4.0 -- "*.gradle" "*.md"

4. Search Across Branches & Tags

Searching in Current Branch

# Search for text in current branch
git grep "KafkaProducer"

# Search with line numbers
git grep -n "bootstrap.servers"

# Search in specific file types
git grep "StreamsConfig" -- "*.java" "*.scala"

# Case-insensitive search
git grep -i "kafka"

Searching Across Multiple Branches

# Search across all remote branches
git grep "ConsumerConfig" $(git branch -r)

# Search in specific branches
git grep "TopologyBuilder" origin/trunk origin/4.0 origin/3.9

# Search with context (3 lines before/after)
git grep -C 3 "bootstrap.servers"

Historical Search

# Search in commit history
git log --all --grep="KIP-"

# Search for when a line was added/removed
git log -S "StreamsConfig" --all --oneline

# Search in specific file's history
git log --all -- clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java

5. View History & Blame

Git Blame - Who Changed What

# Basic blame - shows author, commit, and date
git blame build.gradle

# Blame with line numbers
git blame -n clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java

# Blame specific line range
git blame -L 10,20 README.md

# Blame on specific branch/tag
git blame origin/4.0 -- build.gradle
git blame 4.0.0 -- clients/build.gradle

File History

# Complete history of a file
git log --follow -- build.gradle

# File history with diff summary
git log --stat --follow -- README.md

# File history with actual changes
git log -p --follow -- clients/build.gradle
The --follow flag: Continues listing history beyond renames. Without it, Git stops showing history when a file was renamed.

Version-Specific History

# Show file history up to specific version
git log 4.0.0 --follow -- build.gradle

# Show changes between versions
git log 3.9.0..4.0.0 --follow -- clients/build.gradle

# View file content at specific version
git show 4.0.0:build.gradle
git show origin/trunk:README.md

Finding Pull Request Information

# Find PR merge commits
git log --grep="Merge pull request" --oneline
git log --grep="KAFKA-" --oneline

# From blame to PR workflow
COMMIT=$(git blame -L 25,25 build.gradle | awk '{print $1}')
git log --merges --ancestry-path $COMMIT..HEAD --oneline

Understanding the -- Separator

What -- Means

The -- tells Git: "Everything after this point is a file path, not a command option or branch name."
# Structure: git [command] [options] [branches] -- [files]
git log --oneline --follow -- build.gradle
git diff origin/trunk..origin/4.0 -- clients/src/
git blame -n -w -- README.md

Why -- is Important

Protects you from:

  • Files named like branches
  • Files starting with dashes
  • Files named like Git options
  • Ambiguous arguments

Examples:

# Clear intent
git log -- build.gradle
git log -- README.md
git diff HEAD~1 -- clients/

# Without -- (potentially ambiguous)
git log build.gradle
git log README.md

Quick Reference Commands

Essential Navigation

git branch --show-current    # Current branch
git branch -r               # List remote branches  
git tag -l                  # List tags
git checkout origin/trunk   # Switch to remote branch
git checkout origin/4.0     # Switch to version branch
git checkout 4.0.0          # Switch to specific tag
git fetch origin           # Update remote references

Essential Comparison

git diff origin/trunk..origin/4.0              # Compare branches
git diff origin/trunk..origin/4.0 -- build.gradle  # Compare specific file
git log origin/trunk..origin/4.0     # Commits unique to 4.0 branch
git diff --name-only origin/trunk..origin/4.0 # Just show changed files
git show origin/trunk:build.gradle            # View file on branch

Essential Search & History

git grep "KafkaProducer"                    # Search current branch
git grep "StreamsConfig" $(git branch -r)   # Search all remote branches
git blame build.gradle                      # See who changed each line
git log --follow -- clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java
git log -S "bootstrap.servers" -- clients/  # Find when code added/removed
git log --grep="KAFKA-" --oneline          # Find JIRA ticket commits

Pro Tips for Read-Only Exploration

  1. Always fetch first: git fetch origin
  2. Use detached HEAD: Checkout remote branches directly for safe exploration
  3. Combine commands: git fetch && git checkout origin/trunk
  4. Pipe to less: Add | less to paginate long outputs
  5. Understand structure: In Kafka, trunk is main, numbered branches are releases
  6. Start broad: Use git grep "KafkaProducer" first, then narrow down
  7. Follow breadcrumbs: Use blame → commit → merge history for full story

Happy Code Exploring! 🔍

Key Takeaways

  • Remote branches are safe to explore
  • Always fetch before exploring
  • Use -- for clarity
  • Blame + history tells the full story

Next Steps

  • Try these commands on the Kafka repo
  • Create aliases for frequent commands
  • Practice the safe exploration pattern
  • Share what you learn!