惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
B
Blog
IT之家
IT之家
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
量子位
博客园 - 叶小钗
T
Tailwind CSS Blog
小众软件
小众软件
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
雷峰网
雷峰网
博客园 - 三生石上(FineUI控件)
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
V
V2EX
博客园_首页
I
InfoQ
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Reset, revert, and reflog: the ultimate guide to undoing ...
Cristian Jonhson Alvarez · 2026-06-11 · via DEV Community
Cover image for Reset, revert, and reflog: the ultimate guide to undoing commits without losing your repo

Cristian Jonhson Alvarez

# How to undo commits in Git (locally and on GitHub) and recover “lost” files with reflog

It happens to everyone: you make a commit, push it to GitHub, realize something shouldn’t be there… and while trying to fix it you end up “losing” a file or a commit.

Good news: **Git almost always has a way out** (especially if you use `reflog`).

In this post you’ll learn:

- How to **undo the last commits** locally and on GitHub
- The difference between **reset** and **revert**
- How to **recover commits** after a `reset --hard`
- How to **restore a specific file** from an earlier commit
- How to **change the last commit message**
- A real example with commands and terminal output

---

## The real-world scenario

You’re working on a repo and you create commits like:

- `chore: remove compiled artifacts from the repository`
- `chore: add .gitignore to exclude unnecessary files`

Then you try to undo the last commit, you run `push --force-with-lease`, and later you say:  
> “I need to recover that file.”

Let’s go step by step.

---

## 1) Undo the last commits: reset vs revert

### Option A: `reset` (rewrites history)
Useful when you want those commits to **disappear from the history**.

- **Deletes commits and discards changes** (hard mode):
```bash
git reset --hard HEAD~2

  • Deletes commits but keeps changes staged (soft mode):
git reset --soft HEAD~2

If you already pushed to GitHub, to make the remote match you must force push:

git push --force-with-lease origin YOUR_BRANCH

Example:

git push --force-with-lease origin master

--force-with-lease is safer than --force because it prevents overwriting remote changes you don’t have locally.


Option B: revert (does NOT rewrite history)

Recommended when:

  • Other people are working on the repo
  • The branch is shared
  • The branch is protected (e.g., main/master)

It creates new commits that undo the changes:

git revert --no-edit HEAD~2..HEAD
git push origin YOUR_BRANCH


2) Recover commits after reset --hard with reflog

If you ran:

git reset --hard HEAD~1

and then regretted it, your lifeline is:

git reflog

Real example output:

dc65430 HEAD@{0}: reset: moving to HEAD~1
3bfb189 HEAD@{1}: commit: chore: add .gitignore to exclude unnecessary files
dc65430 HEAD@{2}: commit: chore: remove compiled artifacts from the repository

You can see the “lost” commit still exists: 3bfb189.

To return to that state:

git reset --hard 3bfb189

If you also want GitHub to match:

git push --force-with-lease origin master


3) Restore a specific file from an earlier commit

Sometimes you don’t want to move the whole branch—only recover one file that existed in a past commit.

Important

This command always requires a path:

git restore --source <COMMIT> -- <FILE_PATH>

Common example: restore .gitignore from 3bfb189:

git restore --source 3bfb189 -- .gitignore

Then save it in history:

git add .gitignore
git commit -m "chore: restore .gitignore"
git push origin master


“I don’t know the exact file path…”

First, list the files touched by that commit:

git show --name-status --pretty="" 3bfb189

Or list everything that exists in that commit:

git ls-tree -r 3bfb189 --name-only

Once you find the exact path, restore it:

git restore --source 3bfb189 -- real/path/to/file.ext


Restore EVERYTHING from a commit (warning: overwrites)

If you truly want to bring everything back exactly as it was in that commit:

git restore --source 3bfb189 -- .


4) Change the last commit message

If you have NOT pushed yet

git commit --amend -m "new message"

If you ALREADY pushed to GitHub

git commit --amend -m "new message"
git push --force-with-lease origin YOUR_BRANCH

Example:

git push --force-with-lease origin master


5) Tips to avoid Git pain (seriously)

  • Before doing an aggressive reset, create a “backup branch”:
git branch backup-before-reset

  • Prefer --force-with-lease over --force
  • If you’re working with a team, prefer revert over reset
  • reflog is your “secret history”: when something “disappears”, check git reflog

Wrap-up

If you ever feel like you “lost” commits or files, remember:

  • git reflog finds the commit you can’t see anymore
  • git restore --source restores specific files without breaking everything
  • reset rewrites history (requires force push)
  • revert is team-friendly