Orienting in an unfamiliar codebase fast
Run it and read its tests first; let history show where change lands and why; ask only what history cannot say.
Predict first
Before you read: predict
ExamHall exam service, src/attempts/deadline.js. git log --oneline -- src/attempts/deadline.js prints:
b8be5cf deadline: name the minute constant
d9f025b style: re-indent src with 2 spaces
77abba7 deadline: allow 2 s for client clock skew
0864bcd app: exam service skeleton
You want to know why line 9 reads const skewMs = 2000;.
Which commit does git blame -L 9,9 src/attempts/deadline.js name?
The 30-second version
Run the code and its tests before reading widely, then read the tests and the data model as the spec. Let history explain the rest: churn shows where change lands, git blame names the last commit that changed a line, and git log -S finds commits that added or removed a string. Ask the owner only what history cannot say, and match conventions.
Run it and read its tests first; let history show where change lands and why; ask only what history cannot say.
How it works
Step 1 of 12
In the kitchen
- she works the morning round beside the head groom before changing anything → run it first (step 1)
Analogy: A new groom's first week at a livery yard
| At the livery yard | In the codebase |
|---|---|
| she works the morning round beside the head groom before changing anything | run it first (step 1) |
| the evening checklist says what "done" means; each door card lists feed, rug and turnout group | the tests and the data model as the spec (steps 2–3) |
| the yard diary shows which horses' routines keep changing | churn (step 4) |
| the initials beside a feed-board line belong to whoever last rewrote it; after the board was recopied, that is the copier | blame names the last change (steps 5–6) |
| a diary search for entries that added or dropped "haylage" finds a diet tried in spring and stopped | pickaxe (step 8) |
| she takes to the yard manager only what board and diary cannot say, such as which horses an owner wants kept in | ask the owner (step 11) |
| she ties haynets with the yard's knot until the yard changes it | match conventions (step 12) |
In real terms: you build a working model of a running system from what it does, what its tests and schema state, and what its history records, before you change it.
Breaks down when: a groom can skip the diary on a busy day. Git records every committed change exactly, but only what was committed: a decision made in a meeting and never written into a commit message is in no history, which is why some questions go to the owner.
Contrasting case: debugging (judgment-debugging-method) starts from a failure and tests hypotheses about it; orientation starts with no failure and builds the model your first change needs.
Examples, run for real
4.1 ExamHall: day one on the grace-period task
EXH-2210: asked to add a submission grace period, a new engineer edited the submit handler after reading only the current files, and the history held what the files did not. MR !2510 starts again from the method: run the suite, read the specs and the schema, then read the history.
4.1 run npm test (node --test test/*.spec.js): tests 5 · pass 5 · fail 0
4.1 model prisma/schema.prisma: Exam, Attempt, Answer · Attempt: id, examId, exam, startedAt, submittedAt, answers
The suite passes, so its tests describe what the service does today (step 2). The schema names what an attempt stores, including a nullable submittedAt (step 3).
4.2 Proof domain, checkout: churn is not size
4.2 churn cart/totals.js: 3 commits, 13 lines · legacy/invoice-pdf.js: 1 commit, 301 lines
The invoice layout is the largest file, but it was written once; cart/totals.js is where change keeps landing (step 4).
4.3 Proof domain, checkout: from a line to its reason
4.3 blame git blame -L 6,6 cart/totals.js -> 3a507dd checkout: round VAT on each line
4.3 why git show -s 3a507dd: Rounding each line makes the order total match the receipt lines the customer sees.
Blame names the commit, and the commit's message gives the reason that the line of code cannot (steps 5, 7).
4.4 Proof domain, checkout: what pickaxe counts
4.4 -S 'FREE_DELIVERY_MIN' -> 94b0293 checkout: order totals · 'FREE_DELIVERY_MIN = 40' -> d051703 checkout: free delivery from 40
Changing 50 to 40 left one occurrence of the name, so a search for the name lists only the commit that added it; a search for the new text finds the change (step 8).
Try it
Answer first, then check. Nothing is saved.
Question 1 of 7
EXH-2210: you are adding a grace period to POST /attempts/:id/submit. On main, git grep -n graceSeconds prints nothing. One unmerged branch, spike/grace-config, adds graceSeconds to src/config/exam.js. A teammate remembers that a grace period was tried on main last spring and taken out. On main you run git log -S'graceSeconds' --oneline.
How many commits does it list?
Question 2 of 7
In src/grading/score.js, line 11 reads if (q.type === 'multi') total += partial(q, answer);. git blame -L 11,11 src/grading/score.js names d9f025b (Eli Novak) style: re-indent src with 2 spaces. You want the commit that wrote the line, to read its message.
Which command's output names that commit?
Question 3 of 7
Ava wants to know which files the team keeps changing. She adds up the lines added and deleted per file over the whole history (git log --numstat): src/admin/console.service.js 363, src/attempts/submit.controller.js 52, src/grading/score.js 39, src/attempts/deadline.js 23. The console file has 123 lines today. git log --numstat --format= -- src/admin/console.service.js prints:
120 120 src/admin/console.service.js
123 0 src/admin/console.service.js
Why does her ranking put the console file first?
Question 4 of 7
Before you touch submit, you check what a second submit does today. Three places say:
README.md: "Candidates may resubmit until time-up; the last submit counts.- the comment above
submit():// A second submit is ignored: the first answers stand. test/submit.spec.js:test('a second submit is refused and changes nothing', …)
npm test passes on main. A candidate submits twice, 2 s apart, before time-up.
What does the second request get?
Question 5 of 7
Monday is your first day on the checkout team, and your first task, due Friday, changes the delivery fee. The service has 9 files under src/. Lia, who owns it, offers you an architecture tour on Wednesday.
What do you do first?
Question 6 of 7
You joined the seat-hold team this week, and npm test passes. Your terminal shows:
$ git log --oneline -- src/holds.js
edebaeb holds: answer 423 with the current hold's expiry
a10f570 Revert "holds: per-venue hold minutes
a685c42 holds: per-venue hold minutes
038c729 holds: hold seats for 7 minutes
ed3e545 holds: seat holds for checkout
$ git show -s --format=%b 038c729
The card provider ends a checkout session after 8 minutes, so 10-minute holds kept seats from buyers who could no longer pay.
Tomorrow Nia, who owns the seat-hold service, has a short slot for you.
Which question do you take to her?
Question 7 of 7
You are adding rate limiting to the checkout API's POST /orders. All five middleware functions refuse a request with throw new ApiError(status, code). You would rather return a Result object, which no file in the service uses. The team's style guide says nothing about error handling.
How do you write the rate limiter?
Go deeper
Pro tip
- Find who to ask with
git shortlog. It counts each author's commits to a path, so the names at the top are the people most likely to know the area.
When: before your first question to the team about one part of the code (step 11). Verify:git shortlog -sn HEAD -- src/attempts/git shortlog -sn HEAD -- src/attempts/ -> 4 Dee Patel · 3 Eli Novak · 1 Ana Ruiz · 1 Chen Wei · 1 Fay Ito. Status: RAN.
Source
Git's documented behaviour is version-specific; the pack ran git 2.52.0. Valid as of 2026-10-01.
- git-blame documentation: https://git-scm.com/docs/git-blame (
git-blame.txt), read 2026-10-01. Quoted: "Annotates each line in the given file with information from the revision which last modified the line.", for-w: "Ignore whitespace when comparing the parent's version and the child's to find where the lines came from.", for--ignore-rev: "Ignore changes made by the revision when assigning blame, as if the change never happened." and "The report does not tell you anything about lines which have been deleted or replaced". - git-log documentation: https://git-scm.com/docs/git-log (
git-log.txt), read 2026-10-01. Quoted, for-S: "Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file." Its description: "List commits that are reachable by following the parent links from the given commit(s)", and for--all: "Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as <commit>." - Pro Git, 7.10 Git Tools: Debugging with Git: https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git (
progit-debugging.txt), read 2026-10-01. Quoted: file annotation "shows you what commit was the last to modify each line of any file." Supports step 5. - Pro Git, 2.3 Viewing the Commit History: https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History (
progit-history.txt), read 2026-10-01. Quoted: "the -S option (colloquially referred to as Git's "pickaxe" option), which takes a string and shows only those commits that changed the number of occurrences of that string." Supports step 8. - gitdiffcore documentation: https://git-scm.com/docs/gitdiffcore (
gitdiffcore.txt), read 2026-10-01. Background for how pickaxe filters a diff; keys nothing. - Google, Software Engineering at Google, ch. 12 "Unit Testing": https://abseil.io/resources/swe-book/html/ch12.html (
swe-ch12.txt), read 2026-10-01. Quoted: tests "can serve as documentation and examples, showing engineers how to use the part of the system being tested and how that system is intended to work." Supports step 2. - Google, Software Engineering at Google, ch. 3 "Knowledge Sharing": https://abseil.io/resources/swe-book/html/ch03.html (
swe-ch03.txt), read 2026-10-01. Quoted: "One of the biggest mistakes that beginners make is not to ask for help when they're stuck." Supports step 11; keys nothing. - Google Engineering Practices, What to look for in a code review: https://google.github.io/eng-practices/review/reviewer/looking-for.html (
eng-looking-for.txt), read 2026-10-01. Quoted: "If no other rule applies, the author should maintain consistency with the existing code." - Google Engineering Practices, Small CLs: https://google.github.io/eng-practices/review/developer/small-cls.html (
eng-small-cls.txt), read 2026-10-01. Background only: its "Separate Out Refactorings" section belongs tojudgment-refactoring-safely's lane and keys nothing here. - Google C++ Style Guide: https://google.github.io/styleguide/cppguide.html (
google-cppguide.txt), read 2026-10-01. Quoted, under "Be consistent with existing code": rules that are attributed to "Be Consistent" boil down to "Just pick one and stop worrying about it". Supports step 12. - PEP 8, Style Guide for Python Code: https://peps.python.org/pep-0008/ (
pep8.txt), read 2026-10-01. Quoted: "Consistency within a project is more important. Consistency within one module or function is the most important."
Related lessons
Checked against the tools and docs as of 2026-10-01.