Git & GitHub

Advanced Git Commands

13 min Lesson 30 of 35

Advanced Git Commands

Beyond the basic Git commands, there are powerful advanced tools that can save you in critical situations and enhance your productivity. In this lesson, we'll explore cherry-pick, reflog, bisect, blame, and other advanced Git commands that every professional developer should know.

Git Cherry-Pick: Applying Specific Commits

Cherry-pick allows you to apply a specific commit from one branch to another without merging the entire branch.

Basic Cherry-Pick: # You're on main branch git checkout main # Apply commit from feature branch git cherry-pick abc123 # Commit abc123 is now on main (with new hash) Use Cases: ✓ Apply hotfix to multiple branches ✓ Pick specific features from experimental branch ✓ Backport fixes to older release branches ✓ Move commits to correct branch after mistake
Important: Cherry-pick creates a NEW commit with the same changes but a different hash. It doesn't move the original commit.

Cherry-Pick Examples

Cherry-Pick Multiple Commits: # Pick a range of commits git cherry-pick abc123..def456 # Pick specific commits git cherry-pick abc123 def456 ghi789 Cherry-Pick Without Auto-Commit: # Stage changes without committing git cherry-pick -n abc123 # or git cherry-pick --no-commit abc123 # Review changes, then commit manually git commit -m "Cherry-picked feature from abc123" Resolve Cherry-Pick Conflicts: # If conflict occurs git cherry-pick abc123 # CONFLICT (content): Merge conflict in file.php # Fix conflicts manually # Then: git add file.php git cherry-pick --continue # Or abort: git cherry-pick --abort
Pro Tip: Use cherry-pick sparingly. If you find yourself cherry-picking many commits, consider merging or rebasing instead.

Git Reflog: The Safety Net

Reflog (reference log) records every change to HEAD. It's your safety net for recovering "lost" commits.

View Reflog: $ git reflog abc123 HEAD@{0}: commit: Add user authentication def456 HEAD@{1}: checkout: moving from feature to main ghi789 HEAD@{2}: commit: Fix payment bug jkl012 HEAD@{3}: reset: moving to HEAD~1 mno345 HEAD@{4}: commit: Add payment feature (LOST!) Reflog Explanation: - HEAD@{0} = Current HEAD position - HEAD@{1} = Previous HEAD position - HEAD@{2} = Two moves ago - etc.

Recovering Lost Commits with Reflog

Scenario: Accidentally Reset Hard # You accidentally did: git reset --hard HEAD~3 # Oh no! 3 commits are gone! # Solution: Use reflog git reflog # Find the commit hash before reset abc123 HEAD@{4}: commit: Add payment feature # Restore to that commit git reset --hard abc123 # Your commits are back! 🎉 Scenario: Deleted Branch Recovery # You accidentally deleted a branch git branch -D feature/important-work # Find the last commit on that branch git reflog | grep "feature/important-work" # Recreate the branch git branch feature/important-work abc123 git checkout feature/important-work
Note: Reflog entries expire after 90 days by default. Don't wait too long to recover lost work!

Git Bisect: Finding Bugs with Binary Search

Bisect uses binary search to find which commit introduced a bug.

Basic Bisect Workflow: # Start bisect git bisect start # Mark current commit as bad (bug exists) git bisect bad # Mark a known good commit (bug didn't exist) git bisect good v1.2.0 # Git checks out middle commit # Test if bug exists # If bug exists: git bisect bad # If bug doesn't exist: git bisect good # Repeat until Git finds the problematic commit # When done: git bisect reset

Automated Bisect with Tests

Run Bisect Automatically: # Start bisect git bisect start HEAD v1.2.0 # Run bisect with test command git bisect run php artisan test --filter=PaymentTest # Git will automatically test each commit # Mark as good/bad based on test exit code # Exit code 0 = good, non-zero = bad # Bisect will find the exact commit that broke tests Example Output: abc123 is the first bad commit commit abc123 Author: John Doe <john@example.com> Date: Mon Jan 15 10:30:00 2024 +0000 Refactor payment calculation This commit introduced the bug!
Power Move: Bisect can check hundreds of commits in minutes by using binary search. Manual testing would take hours!

Git Blame: Track Changes by Author

Blame shows who last modified each line of a file and when.

Basic Blame: $ git blame app/Http/Controllers/PaymentController.php abc123 (John Doe 2024-01-15 10:30:00 +0000 1) <?php abc123 (John Doe 2024-01-15 10:30:00 +0000 2) def456 (Jane Smith 2024-02-01 14:20:00 +0000 3) public function process($order) { def456 (Jane Smith 2024-02-01 14:20:00 +0000 4) $tax = $order->total * 0.08; ghi789 (Bob Johnson 2024-03-10 09:15:00 +0000 5) // TODO: Fix tax calculation def456 (Jane Smith 2024-02-01 14:20:00 +0000 6) return $order->total + $tax; abc123 (John Doe 2024-01-15 10:30:00 +0000 7) } Useful Blame Options: # Show line numbers and commit info git blame -L 10,20 file.php # Show only specific line range git blame -L 10,+5 file.php # Show email instead of names git blame -e file.php # Ignore whitespace changes git blame -w file.php
Pro Tip: Use blame to find who wrote code, not to blame them! It's for understanding context and asking questions.

Git Grep: Search Repository Content

Grep searches file contents across your entire Git repository.

Basic Grep: # Search for text in all tracked files git grep "calculateTax" # Search with line numbers git grep -n "calculateTax" # Case-insensitive search git grep -i "calculatetax" # Show count of matches per file git grep -c "calculateTax" # Search in specific branch git grep "calculateTax" main # Search in specific commit git grep "calculateTax" abc123 Advanced Grep: # Search with regex git grep "function.*calculate" # Search for whole words only git grep -w "tax" # Show context (3 lines before/after) git grep -C 3 "calculateTax" # Search only PHP files git grep "calculateTax" -- "*.php" # Search multiple patterns (AND) git grep -e "tax" --and -e "calculate"

Git Submodules: Managing Dependencies

Submodules allow you to include another Git repository inside your repository.

Add Submodule: # Add submodule git submodule add https://github.com/vendor/library.git lib/library # This creates .gitmodules file Clone Repository with Submodules: # Clone and initialize submodules git clone --recurse-submodules https://github.com/user/repo.git # Or if already cloned: git submodule init git submodule update Update Submodules: # Update all submodules to latest git submodule update --remote # Update specific submodule git submodule update --remote lib/library Remove Submodule: # Remove submodule git submodule deinit lib/library git rm lib/library rm -rf .git/modules/lib/library
Note: Submodules are complex and have gotchas. Consider using Composer (PHP) or npm (JavaScript) for dependency management instead.

Git Worktree: Multiple Working Directories

Worktree allows you to check out multiple branches simultaneously in different directories.

Use Case: You're working on a feature but need to quickly fix a production bug without losing your current work. Create Worktree: # Create worktree for hotfix git worktree add ../hotfix-dir hotfix/urgent-bug # Now you have: # - /project (main working directory) # - /hotfix-dir (separate directory with hotfix branch) # Work in hotfix directory cd ../hotfix-dir # Make changes, commit, push git add . git commit -m "Fix urgent bug" git push # Return to main work cd /project # Your feature work is untouched! Manage Worktrees: # List all worktrees git worktree list # Remove worktree git worktree remove ../hotfix-dir # Prune deleted worktrees git worktree prune
Benefit: Worktrees eliminate the need to stash, commit WIP, or clone the repo again. Work on multiple branches simultaneously!

Git Show: Inspect Commits and Objects

Show Commit Details: # Show latest commit git show # Show specific commit git show abc123 # Show specific file from commit git show abc123:app/Models/User.php # Show file from different branch git show main:README.md Show Tag: # Show annotated tag details git show v1.2.0 Show Stash: # Show latest stash git show stash@{0} # Show specific stash git show stash@{2}

Git Archive: Create Release Archives

Create Archive: # Create zip archive of main branch git archive --format=zip --output=release-v1.2.0.zip main # Create tar.gz archive git archive --format=tar.gz --output=release.tar.gz main # Archive specific tag git archive --format=zip --output=v1.2.0.zip v1.2.0 # Archive with prefix directory git archive --prefix=myapp/ --format=zip --output=myapp.zip main Archive Specific Files: # Archive only app/ directory git archive --format=zip --output=app-only.zip main app/ # Archive excluding vendor/ git archive --format=zip --output=no-vendor.zip main \ $(git ls-files | grep -v "^vendor/")

Git Clean: Remove Untracked Files

Clean Untracked Files: # Dry run (show what would be deleted) git clean -n # Remove untracked files git clean -f # Remove untracked files and directories git clean -fd # Remove ignored files too git clean -fdx # Interactive clean git clean -i Common Use Case: # After switching branches, remove build artifacts git clean -fdx # Clean but keep .env file git clean -fdx -e .env
Danger: git clean -fdx permanently deletes files! Always run git clean -n first to preview.

Git Shortlog: Summarize Contributors

View Contributor Summary: # Show commit counts by author git shortlog -sn # Output: 150 John Doe 87 Jane Smith 45 Bob Johnson # Show with email addresses git shortlog -sne # Show for specific branch git shortlog -sn main # Show for date range git shortlog -sn --since="2024-01-01" --until="2024-12-31" # Show detailed commit messages git shortlog

Git Log Advanced Queries

Powerful Log Queries: # Commits by specific author git log --author="John Doe" # Commits in date range git log --since="2024-01-01" --until="2024-12-31" # Commits affecting specific file git log -- app/Models/User.php # Search commit messages git log --grep="fix bug" # Search commit content (code changes) git log -S "calculateTax" # Commits that added or removed specific text git log -G "function.*calculate" # Show files changed in each commit git log --name-only # Show stats (insertions/deletions) git log --stat # Custom format git log --pretty=format:"%h - %an, %ar : %s" # Commits on branch but not on main git log main..feature/new-feature # Merge commits only git log --merges # Non-merge commits only git log --no-merges

Practice Exercise:

Scenario: Your production app has a bug. The bug didn't exist in v1.0.0 (released 3 months ago), but exists now. You need to find which commit introduced it.

Tasks:

  1. Use git bisect to find the problematic commit
  2. Use git blame to see who wrote the buggy line
  3. Use git show to examine the commit details
  4. Use git log to understand the context

Solution:

# 1. Start bisect git bisect start git bisect bad # Current version has bug git bisect good v1.0.0 # v1.0.0 was working # Git checks out middle commit # Test the app... # Bug exists: git bisect bad # Continue until Git finds the commit: # abc123 is the first bad commit # 2. Use blame to find who wrote the buggy code git blame app/Services/PaymentService.php # Output shows line 45 was modified in commit abc123 # 3. Show commit details git show abc123 # See full diff and commit message # 4. Get context with log git log abc123~5..abc123 # See commits around the problematic one # 5. Cherry-pick the fix to hotfix branch git checkout -b hotfix/payment-bug git cherry-pick def456 # The commit that fixes it # 6. Done! git bisect reset

Summary

In this lesson, you learned:

  • git cherry-pick: Apply specific commits to another branch
  • git reflog: Recover "lost" commits and branches
  • git bisect: Find bug-introducing commits with binary search
  • git blame: Track who modified each line of code
  • git grep: Search repository content efficiently
  • git worktree: Work on multiple branches simultaneously
  • git clean: Remove untracked files safely
  • Advanced git log: Powerful commit history queries
Congratulations! You've completed the Git & GitHub tutorial. You now have the skills to confidently use Git for version control, collaborate with teams on GitHub, and handle advanced scenarios. Keep practicing, and you'll master Git in no time!