linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Chapters
  • How it works
  • Lessons
  • Knowledge base
  • Interview prep
Cluster

← все кластеры

History recovery and archaeology

Reflog as a time machine, bisect for finding the commit that broke things, blame with its limits, rev-parse as a universal ref resolver, and cat-file for reading objects by hand. This block immediately shows who has "worked through incidents by hand" versus who "read the textbook."

6 вопросов · ~30 мин чтения

Questions

На этой странице

  1. 01What is the reflog, how do you use it, and how long do entries live?
  2. 02Bisect: how does it find the bad commit? When do you use it?
  3. 03What does `git blame` show, and what are its limits?
  4. 04You deleted a branch with `git branch -D` and have not pushed the commits yet. How do you recover it?
  5. 05Why do you need `git rev-parse`, and what kinds of refs does it resolve?
  6. 06`git cat-file -p`: why read objects by hand?

#git-reflog-time-machine

juniorчасто

What is the reflog, how do you use it, and how long do entries live?

Что отвечать

The reflog is a local log of HEAD and ref movements. Every time a branch moves (commit, reset, rebase, checkout), Git writes an entry to `.git/logs/HEAD` and `.git/logs/refs/heads/<branch>`. `git reflog` shows "where I have been," and `HEAD@{2}` means "two steps back." Entries live 90 days by default for reachable ones and 30 days for unreachable ones, and they get cleaned up by `git gc`. **This is local only.** A server usually has no reflog.

Что хотят услышать

The candidate should: - name the reflog as a rescue after a `reset --hard`, a failed rebase, or an accidental `branch -D` - show the recovery workflow: `git reflog` -> find the SHA -> `git checkout -b restored <sha>` or `git reset --hard <sha>` - explain that the reflog is LOCAL. If a colleague force-pushed to main, you have your own reflog (until you run gc), they have theirs, but there is no history on the server - name the settings `gc.reflogExpire` (90 days) and `gc.reflogExpireUnreachable` (30 days), plus `git gc --prune=now` as the way to clean up (or, conversely, to keep things) - mention `git reflog <branch>` for viewing the reflog of a specific branch, not just HEAD

Подводные камни

  • ✗ Thinking the reflog exists on the server. It does not, and on a bare repo it is usually disabled
  • ✗ Running `git gc --prune=now --aggressive` right after a screwup. You can wipe out exactly what you wanted to recover
  • ✗ Relying on the reflog after 3 months. The entry has most likely already expired and been collected by gc

Follow-up

  • ? How do you configure the reflog so it never expires?
  • ? What does `git reflog refs/heads/main` show?
  • ? Why does the reflog not help other developers after your force-push?

Глубина в базе знаний

  • git reflog
  • Commit
tags: recovery, reflog, safety

#git-bisect-find-bad-commit

intermediateчасто

Bisect: how does it find the bad commit? When do you use it?

Что отвечать

Binary search through history. `git bisect start` -> `git bisect bad` (broken now) -> `git bisect good <old-sha>` (it worked there). Git drops you in the middle of the range, you check, you say `git bisect good` or `bad`, and so on for log2(N) steps. To finish: `git bisect reset`. When to use it: a regression appeared "somewhere between releases," there are many commits, and finding the point is easier than reading the diff.

Что хотят услышать

A senior should: - name the complexity log2(N). 1000 commits is 10 steps - say that bisect works only if **every commit builds and a test can check it**, otherwise a falsely-bad commit breaks the binary search - name `git bisect run <script>` for automation: the script returns 0 for good, 1-127 (except 125) for bad, and 125 for skip - mention `git bisect skip` for commits that do not build or are not relevant (Git will try another) - say that bisect does not fit commits with subtle mutual dependencies (for example, `feature_flag = false` plus the code behind the flag)

Подводные камни

  • ✗ Running bisect on a repo with broken commits. The binary search gives a false result, and you need `git bisect skip`
  • ✗ Forgetting `git bisect reset` at the end. You get stuck in bisect mode and every command complains
  • ✗ Bisecting by hand when you have a test. `git bisect run` is faster

Follow-up

  • ? How does `git bisect skip` differ from `bad` and `good`?
  • ? How do you write a bisect-run script to check for a regression?
  • ? What happens if the test itself is flaky?

Глубина в базе знаний

  • git bisect
  • Commit
  • Atomic Commit
tags: recovery, bisect, debugging

#git-blame-limitations

intermediateиногда

What does `git blame` show, and what are its limits?

Что отвечать

For each line of a file, it shows the commit that last changed it, the author, and the date. Limits: it does not track a file rename (the link is lost), it does not track a block of code moved to another file, and it gets noisy on reformatting commits (for all lines: that commit). You fix this with flags: `-w` ignores whitespace, `-M` detects a move within a file, `-C` detects a copy between files, and `--ignore-rev <sha>` skips noisy commits (for example, after a migration to prettier).

Что хотят услышать

A senior should: - name `-w -M -C` as the standard set for blame in large projects with a history of refactorings - mention the `.git-blame-ignore-revs` file: a list of "noisy" commit SHAs to ignore, which GitHub picks up automatically in the UI - mention `git log -L :func_name:file.c` as an alternative to blame for tracking the history of a specific function - say that blame is useful for understanding-why, not for blaming-who: "why is this line here" rather than "who is at fault" - say that blame through the GitHub UI exists, but without `-w -M -C` the quality is worse than locally

Подводные камни

  • ✗ Running blame without `-w` and thinking a reformatting commit means "someone rewrote everything"
  • ✗ Using blame to assign blame. The team burns out fast
  • ✗ Not setting up `.git-blame-ignore-revs` after a mass refactor. Blame in the UI becomes unusable

Follow-up

  • ? How do you set up `.git-blame-ignore-revs` to hide a prettier-migration commit?
  • ? Why is `git log -L` better than blame for tracking a function?
  • ? What does `git blame -C -C -C file.c` show?

Глубина в базе знаний

  • git blame
  • git log
tags: recovery, blame, archaeology

#git-restore-deleted-branch

intermediateчасто

You deleted a branch with `git branch -D` and have not pushed the commits yet. How do you recover it?

Что отвечать

Through the reflog. `git reflog` (or specifically `git reflog --date=iso --all`) shows the last place the branch was. Before the deletion, there was an entry "checkout: moving to ..." there. Take the SHA of the tip commit of the deleted branch and run `git checkout -b restored-feature <sha>`. If the reflog no longer contains that SHA, `git fsck --lost-found` helps, since it looks for "dangling commits" in `.git/objects/`.

Что хотят услышать

A senior should: - name `git reflog` as the first command, not fsck. The reflog works until gc has run - say that commits are not physically deleted on `branch -D`. The ref to them simply disappears, and the objects stay "dangling" until gc - name `git fsck --lost-found` as a fallback when the reflog is already lost (or for branches you did not touch personally) - mention that after a force-push to main you can recover the old history from the local reflog of any developer who fetched it earlier, since their reflog holds the old SHAs - say that `git reflog` accepts time: `HEAD@{yesterday}`, `HEAD@{2.hours.ago}`, which is handy when you do not remember how many steps back it was

Подводные камни

  • ✗ Running `git gc --prune=now` right after `branch -D`. You can wipe out dangling commits that fsck would have found
  • ✗ Thinking `branch -D` physically erases the objects. It does not, and until gc they stay reachable through the reflog
  • ✗ Relying on fsck without the reflog a month later. The default gc has already run and the objects are gone

Follow-up

  • ? What does `git fsck --lost-found` show after `branch -D`?
  • ? How do you recover a branch that was force-pushed away a week ago?
  • ? Why is `HEAD@{yesterday}` handier than `HEAD@{42}` for recovery?

Глубина в базе знаний

  • git reflog
  • Branch
tags: recovery, reflog, fsck

#git-rev-parse-universal

seniorредко

Why do you need `git rev-parse`, and what kinds of refs does it resolve?

Что отвечать

A universal "resolver" of any ref into a SHA. `git rev-parse HEAD`, `git rev-parse main`, `git rev-parse origin/main~3`, `git rev-parse v1.2.3^{commit}`, `git rev-parse :/fix login` (search by commit message): all of these give a 40-character SHA. It is used in scripts to get the full SHA for later commands. Plus a lot of utility output: `--show-toplevel` (the repo root), `--git-dir` (the path to `.git/`), `--abbrev-ref HEAD` (the name of the current branch).

Что хотят услышать

A senior should: - name `rev-parse` as the "best command for scripts," since it works with any form of ref - list the notations: `~N` (N commits back along the first parent), `^N` (the N-th parent of a merge commit), `^{tree}`/`^{commit}`/ `^{tag}` (peel to the type you need), `@{N}` (the N-th reflog entry), `@{u}` (upstream) - name the utility flags: `--show-toplevel`, `--git-dir`, `--show-cdup`, `--abbrev-ref`, everything a script needs so it does not depend on cwd - mention `git rev-parse --verify <ref>` as a way to check that a ref is valid without returning garbage (exit 0/1) - say that `git rev-parse` is cheaper than `git log -1 --format=%H`, because it does not build a log

Подводные камни

  • ✗ Parsing `git log` output with a regex instead of `git rev-parse`. Fragile
  • ✗ Mixing up `^` (parent) and `^{commit}` (peel to type). The syntax looks alike, the meaning differs
  • ✗ Not using `--verify` in a script. You get a garbage SHA on a typo in the ref

Follow-up

  • ? What does `git rev-parse HEAD^2` return on a non-merge commit?
  • ? Why is `git rev-parse --show-toplevel` better than `pwd` in a script?
  • ? How do you find a commit by a substring of its message using rev-parse?

Глубина в базе знаний

  • git rev-parse
  • git reflog
tags: recovery, plumbing, scripting

#git-cat-file-read-objects

seniorредко

`git cat-file -p`: why read objects by hand?

Что отвечать

To understand what is inside a commit, tree, or blob without any middleman. `git cat-file -t <sha>` shows the type, and `-p <sha>` unpacks and prints it: a blob gives the file contents, a tree gives a list of entries with permissions and SHAs, a commit gives tree+parent+author+committer+message, and a tag gives a wrapped commit with a signature. This is useful when debugging strange behavior ("why does this commit see a file that should not be there"), when explaining the object model to a junior, and when working through packfile problems by hand.

Что хотят услышать

A senior should: - name the four object types and what `-p` shows for each - demonstrate `git cat-file -p HEAD^{tree}` for viewing what sits in the root tree of a commit - mention `git cat-file --batch-check` for bulk checking of object existence and type (used in scripts for GC and audit) - say that `cat-file` follows alternate objects (`info/alternates`) and shared packs. It sees everything Git considers available - say that together with `git ls-tree -r HEAD` (a recursive tree walk), `cat-file` gives full control over objects without dropping into the low-level plumbing commands of libraries

Подводные камни

  • ✗ Thinking `-p` works only on a blob. It works on any type, with a different output format
  • ✗ Mixing up a commit SHA and a tree SHA. `git cat-file -p HEAD` is a commit, `git cat-file -p HEAD^{tree}` is a tree
  • ✗ Using `cat-file` on an abbreviated SHA in a script without `--verify`. On a short-prefix collision you get an error

Follow-up

  • ? What does `git ls-tree -r HEAD` show, and how does it differ from `cat-file -p`?
  • ? How do you check an object's size with `cat-file` without unpacking it?
  • ? What is the `--batch` mode of cat-file for?

Глубина в базе знаний

  • git cat-file
  • Blob
  • Tree
  • Commit
tags: recovery, plumbing, debuggingbook: edu/Git_book/03-object-model.md
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies