GitHub Foundations study materials
GitHub Foundations study resources

The force push that deleted a teammate's work

GitHub Foundations · Put your knowledge to work in context.

All case studies

The force push that deleted a teammate's work

A two-person team keeps product specs in a GitHub repository alongside their code. Priya edits files through the GitHub web editor; Sam works locally from the command line. On Monday Sam adds specs/billing.md, commits, and runs git push. The push is rejected with ! [rejected] main -> main (fetch first). Sam re-runs the push with --force. It succeeds, but Priya's Tuesday edits to specs/onboarding.md are gone from the remote. Separately, Sam creates secrets.env in the repository root on their laptop and it never appears in git status, even though the file is definitely there.

1. Priya's edits vanished after the force push. What should Sam have done when the push was first rejected, and what recovery options remain now?

Read the worked answer

The rejection means the remote branch has commits Sam does not have. The correct response is to fetch and integrate, never to overwrite:

git fetch origin
git log --oneline HEAD..origin/main   # what Priya added
git pull --rebase origin main         # or: git merge origin/main
git push origin main

Recovery now, in order of reliability:

  1. Priya's own clone or her still-open browser session holds the commits; she can simply push them again.
  2. A force push moves the branch pointer but does not immediately delete the old commits. If anyone captured the previous SHA, GitHub can still render it by commit URL for a period.
  3. git reflog on any machine that had fetched her work.

The lesson is not that force is always wrong, but that rewriting a shared branch discards other people's work. Protect main with Do not allow force pushes, and reserve --force-with-lease for personal feature branches where nobody else commits.

2. Why does `git status` never show secrets.env, and what should Sam check before doing anything else?

Read the worked answer

git status omits untracked files that match an ignore rule, so something is matching. Have Sam run git check-ignore -v secrets.env, which prints the exact file and line responsible. Likely candidates: a pattern in the repository's .gitignore, a rule in .git/info/exclude (local only, not shared), a global core.excludesFile, or an ignored parent directory. git status --ignored shows what is being suppressed.

The judgement call is what not to do: do not fix this with git add -f. A committed secrets file must be treated as compromised and rotated immediately, and removing it in a later commit does not remove it from history. If other, harmless files in the same directory are being caught by an overly broad rule, add a negation pattern after the broad rule rather than force-adding individual files.

3. Recommend a working model that prevents a repeat of both problems for a team of two.

Read the worked answer

Both failures share one root cause: Sam and Priya were editing the same shared branch with no integration point.

  • Both clone the repository and work on short-lived branches; main becomes append-only.
  • Enable branch protection or a ruleset on main: require a pull request, require one approval, block force pushes, and apply the rule to administrators too, since a two-person team almost certainly has admin rights.
  • Priya's web-editor edits land as commits on a branch that opens a PR, not directly on main.
  • Agree on a one-line convention: fetch before you start, push to a branch, never to main.

With two people the PR review is light, but the rule still does the real work: it makes non-fast-forward rejections impossible to hit, because nobody pushes to the protected branch at all. Cheap ceremony, and it removes the entire class of lost-work incident.