Git's history tools answer different questions, and choosing the right one saves time. git log --oneline --graph --decorate --all renders the branch topology in the terminal so you can see merges and divergence at a glance. For blame-style questions, git blame file annotates each line with the commit that last touched it (add -w to ignore whitespace changes), while git log -L :funcName:file traces a function's life from introduction to removal. The pickaxe form git log -S 'searchString' finds every commit whose diff adds or removes that exact string, which is invaluable for tracking when a feature was added or removed across many refactors. To see the full commit message of a single commit, run git log -1 <sha> or git show <sha>. To inspect any object stored in Git (a commit, tree, blob, or tag), git cat-file -p <sha> prints its human-readable contents.
Diffs come in many useful variants. Plain git diff shows unstaged changes, git diff --staged (or --cached) shows what is staged, and git diff --word-diff highlights changes within lines. git show --name-only <sha> lists the files a commit changed, and git diff sha1 sha2 -- file compares a single file at two points in history. Comparing branches uses the dot notation: git log main..feature lists commits in feature not yet in main, while git log feature..main does the opposite. The three-dot form git log main...feature is special: it shows the diff from the merge base of the two branches to feature, which is exactly the change set a pull request would introduce; the same logic applies with git diff main...feature. To list branches sorted by recent activity, git for-each-ref --sort=-committerdate refs/heads/ --format='%(committerdate:short) %(refname:short)' produces a clean leaderboard of recent work.
For automatically locating the commit that introduced a bug, Git ships a binary search tool called bisect. Start it with git bisect start, mark the current commit as bad with git bisect bad, mark an earlier known-good commit with git bisect good <sha>, and Git will check out intermediate commits for you to test. When a test can be expressed as a script, git bisect run ./test.sh automates the search: exit 0 means good, exit 1 means bad, and exit 125 means skip. Always finish a session with git bisect reset to return HEAD to where you started.