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

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

Scenarios: lost a commit, force-push, detached HEAD

Scenario questions are the most valuable ones in an interview. Not "what is reflog," but "I wiped my own commits with reset --hard, what do you do first." These questions separate the candidate who read the textbook from the one who put out fires in a team repository. Every scenario here is real.

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

Questions

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

  1. 01You accidentally ran `git reset --hard HEAD~5`. Local, not pushed. What do you do?
  2. 02A colleague force-pushed to main and wiped 6 of someone else's commits. What do we do?
  3. 03I'm in detached HEAD. What is it and how do I get out safely?
  4. 04A merge failed with a conflict. What do you pick, abort or continue, and how do you decide?
  5. 05Someone committed a 2GB video file a year ago. The repo grew to 5GB. How do you get rid of it?
  6. 06`fatal: index file corrupt` on every command. What do you do?

#git-reset-hard-recovery

intermediateчасто

You accidentally ran `git reset --hard HEAD~5`. Local, not pushed. What do you do?

Что отвечать

`git reflog`, then find the entry "HEAD@{1}" (the state before the reset). It holds the SHA of what was there. From there you have two options: `git reset --hard HEAD@{1}` (move the branch back to the same place), or `git checkout -b restored HEAD@{1}` (create a branch from that point and leave the current one as it is). This works because reset moves only the branch pointer. The commits physically stay in `.git/objects/` until `git gc` runs.

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

The candidate should: - name `git reflog` as the first command, no panic and no gc - explain why this works: reset does not delete commits, it only moves the ref, and the commits stay dangling until gc (by default 90 days for ones reachable from the reflog) - name `HEAD@{1}` as the idiomatic "one step back in the reflog" - warn: **do not** run `git gc --prune=now` after the screwup. You can wipe the dangling commits - say that the same approach works for `branch -D`: until gc the branch is reachable through the reflog

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

  • ✗ Running `git gc --prune=now` right after the panic wipes exactly what you wanted to recover
  • ✗ Thinking reset physically erases commits. It does not, it only moves the ref
  • ✗ Counting on the reflog three months later when the entry has already expired

Follow-up

  • ? What does `git reflog HEAD` show after several resets?
  • ? How do you recover if the reflog has already been cleaned out?
  • ? Why is `git gc --prune=now` after a reset dangerous?

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

  • git reflog
  • Commit
tags: troubleshooting, reset, reflog

#git-force-push-snosed-main

seniorчасто

A colleague force-pushed to main and wiped 6 of someone else's commits. What do we do?

Что отвечать

Anyone whose main was up to date before the force-push has the old SHA in their local reflog. `git reflog refs/heads/main` or `git reflog origin/main` shows the last correct SHA. From there: restore main to that SHA locally (`git checkout -B main <sha>`), then force-push the correct history back. If everyone has already pulled the broken main, ask the person whose reflog still holds the old state, or check the server-side gc and backup.

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

The senior should: - name "everyone has their own reflog" as the key idea: the distributed nature of Git is the rescue - give the workflow: find a reflog with the correct SHA -> restore locally -> coordinated force-push back - say that if everyone has already run `git pull`, which dragged in the force-pushed version, then each reflog holds **both** entries, and you look for the one "before pull" - mention **prevention**: branch protection on main that forbids force-push, with a PR requirement through required reviewers - say that after recovery you need a postmortem: why a force-push to main was possible at all, usually a broken branch protection or an admin bypass

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

  • ✗ Panicking and not checking the reflog when the answer is right there
  • ✗ Running `git pull` after a force-push and hoping pull will sort it all out. You get a merge of the old and new history
  • ✗ Relying on the server: a bare repo usually has no reflog, the GitHub `Network` graph shows the past, but recovery from the UI is only through the REST API

Follow-up

  • ? What does `git reflog origin/main` show for someone who just ran a fetch?
  • ? How do you recover through the GitHub REST API when nobody has a reflog?
  • ? Which branch protection settings make this scenario impossible?

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

  • git reflog
  • Force push
  • Branch protection rules
tags: troubleshooting, force-push, recovery

#git-detached-head-explain

juniorчасто

I'm in detached HEAD. What is it and how do I get out safely?

Что отвечать

Detached HEAD is when HEAD points straight at a commit instead of at a branch. It happens after `git checkout <sha>`, `git checkout v1.2.3`, and during an interactive rebase. The danger is that commits you make in this state are not attached to any branch. After `git checkout main` they become dangling and disappear at the next gc. The safe way out: `git switch -c new-branch` (or `git checkout -b new-branch`). It creates a branch right here and attaches HEAD to it.

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

The candidate should: - explain "HEAD points at a SHA, not at a ref" and why this is a normal state, not a bug - name the typical causes: checking out a tag, checking out a SHA from bisect, being in the middle of a rebase - say that commits in detached HEAD are not lost right away. They are in the reflog of HEAD and can be recovered if you do not miss the gc - give the safe way out: `git switch -c branch` (or `git checkout -b`), which attaches HEAD to a new branch right here - mention that `git switch -` returns to the previous branch (like `cd -` in the shell)

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

  • ✗ Making commits in detached HEAD and then `git switch main`. The commits stay reachable only through `git reflog HEAD`
  • ✗ Thinking detached HEAD is a broken state. It is valid and sometimes needed
  • ✗ Using `git checkout <sha>` without understanding it. You land in detached HEAD without knowing why

Follow-up

  • ? How do you recover commits made in detached HEAD after `git switch main`?
  • ? Why does bisect use detached HEAD?
  • ? What does `cat .git/HEAD` show in a detached state versus a normal one?

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

  • Detached HEAD
  • git reflog
tags: troubleshooting, detached, head

#git-merge-abort-vs-continue

intermediateчасто

A merge failed with a conflict. What do you pick, abort or continue, and how do you decide?

Что отвечать

`git merge --abort` if there are more conflicts than you expected, you do not understand what came in, or you are unsure about the resolve strategy. It returns you to the state before the merge, safely. `git merge --continue` (or just `git add` + `git commit`) when you have resolved the conflicts, checked `git status` (no files with markers), run the local tests, and everything is fine. Do not rush continue. A merge commit stays in the history forever.

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

The senior should: - name `git merge --abort` as the safe default when unsure - give a checklist before continue: `git status` (nothing under "Unmerged paths"), `grep -r '<<<<<<<'` (no forgotten markers), local tests passed - say that `git merge.conflictStyle diff3` adds a `||||||| base` block to the markers, which often helps you see the original state - mention `git checkout --ours <file>` / `--theirs <file>` for the case where you want one whole side without going through it line by line - name `git rerere` for long-running branches with repeating conflicts. It remembers a resolve and applies it automatically

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

  • ✗ Committing a file with `<<<<<<<` markers. It lands in the history
  • ✗ Running `git commit` without `git add` after the resolve. It will not pick up the changes
  • ✗ Using `--ours`/`--theirs` without realizing their semantics are inverted during a rebase

Follow-up

  • ? What does `git status` show in the middle of a merge with a conflict?
  • ? How does `git checkout --ours` during a merge differ from during a rebase?
  • ? Why use `merge.conflictStyle diff3`?

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

  • git merge
  • PR merge strategies (GitHub)
  • Auto-merge for PRs
tags: troubleshooting, merge, conflict

#git-huge-file-bloat-repo

seniorиногда

Someone committed a 2GB video file a year ago. The repo grew to 5GB. How do you get rid of it?

Что отвечать

`git filter-repo --strip-blobs-bigger-than 100M` (or `--path huge.mp4 --invert-paths` for a specific file) rewrites the history and removes the large blobs from every commit. The commit SHAs change, so you need a force-push of all branches and tags, and every developer re-clones. Then `git gc --prune=now --aggressive` to physically delete the blobs. For the future: `git lfs` for large binaries and a pre-receive hook on the server with a size limit.

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

The senior should: - name `git filter-repo` (not filter-branch) as the standard tool in 2026 - say that filter-repo is a history rewrite -> force-push -> coordination with the team - explain that a plain `git rm huge.mp4` + commit will not shrink the repo. The blob stays in the history and in the clone - name LFS as **prevention**: large files are stored in a separate backend, and the commit holds only a pointer (~130 bytes) - mention `git count-objects -vH` to check the size before and after, and `git rev-list --objects --all | git cat-file --batch-check='%(objectsize) %(objectname)' | sort -nr | head` to find the top-N largest blobs

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

  • ✗ Running `git rm huge.mp4` + commit and thinking the repo will shrink. The blob stays in the history
  • ✗ Using filter-branch instead of filter-repo. It is outdated, slow, and buggy
  • ✗ Running filter-repo without a backup. If something goes wrong, there is nothing to roll back to
  • ✗ Not setting up LFS after the cleanup. The history repeats itself a month later

Follow-up

  • ? How do you find the top 10 largest blobs in history?
  • ? How does `git lfs` differ from a regular blob?
  • ? Which pre-receive hook rejects a commit with a file over 100MB?

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

  • git filter-repo: Rewriting History
  • Packfile
  • Force push
tags: troubleshooting, repo-size, filter-repo

#git-index-corrupted

seniorредко

`fatal: index file corrupt` on every command. What do you do?

Что отвечать

`.git/index` is a binary cache of the staged state, and you can rebuild it from the HEAD tree without losing data. Workflow: `rm .git/index` (or move it aside as a backup) -> `git reset` (with no arguments, which recreates the index from HEAD) -> `git status` to see what in the working tree differs from HEAD. The working tree and `.git/objects/` are left untouched. Once the index is rebuilt, you can `git add` again whatever you planned to commit.

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

The senior should: - name that the index is **derived**, not the source of truth. It is safe to delete and rebuild from HEAD - give the concrete commands: `rm .git/index` -> `git reset` (= `git reset --mixed HEAD`) -> `git status` - say that the working tree is not harmed. Your files are there as they are, the changes are kept (then `git add` again) - mention that corruption usually comes from killing Git in the middle of a write (power loss, OOM, kill -9) or from a bad disk - name `git fsck --full` as the way to check the rest of the repository for damage after a corrupted index

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

  • ✗ Deleting the whole `.git/` instead of `.git/index`. You wipe the entire repo
  • ✗ Running `git reset --hard` thinking it is the fix. --hard overwrites the working tree
  • ✗ Not running `git fsck` after the recovery. If the disk is bad, the damage may be in objects too

Follow-up

  • ? What does `git fsck --full` show after you rebuild the index?
  • ? How does `git reset` with no flags differ from `git reset --hard`?
  • ? When can the index get corrupted during normal work, with no kill?

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

  • git status
  • git reflog
tags: troubleshooting, index, corruption
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies