Undo در Git یک فرمان نیست — چهار کار مختلف است. قبل از اجرا باید بدانی فایل روی دیسک را برمیگردانی، پیشنویس را خالی میکنی، اشارهگر شاخه را حرکت میدهی، یا یک کامیت جدیدِ خنثی میسازی.
🎯 اهداف یادگیری
- نقشهٔ Undo را از حفظ بکشی
restoreرا جایگزین checkout فایل کنی- سه حالت reset را از هم جدا کنی
- با
reflogکامیت «گمشده» را زنده کنی
شکل ۷ — قانون طلایی: تاریخچهٔ عمومی را فقط با revert لمس کن.
🧹 Working Tree و Index
git restore src/auth.ts # Working ← Index git restore --staged src/auth.ts # Index ← HEAD git restore --source=HEAD --staged --worktree src/auth.ts # هر دو درخت فایل = HEAD (معادل checkout -- file) git restore --source=main~3 README.md # نسخهٔ قدیمی را بیاور
- Changes → آیکون ↩ Discard Changes =
restore - Staged → - Unstage =
restore --staged - منوی
...→ Commit → Undo Last Commit =reset --soft - Timeline فایل را بعد از Discard هم گاهی نجات میدهد
- Discard All خطرناک است
git restore file
git restore --staged file
git reset --soft HEAD~1
git reflog برای نجات
🧱 سه چهرهٔ reset
فرض: A--B--C (HEAD) و میخواهی به B برگردی.
| فرمان | HEAD | Index | Working | استفاده |
|---|---|---|---|---|
--soft B |
B | محتوای C | محتوای C | کامیت را بشکن، تغییرات بماند staged |
--mixed B (پیشفرض) |
B | B | محتوای C | کامیت را بشکن، تغییرات unstaged |
--hard B |
B | B | B | همهچیز برود |
git reset --soft HEAD~1 # پیام/فایلها را دوباره بچین git reset HEAD~1 # همان، اما unstaged # git reset --hard HEAD~1 # فقط اگر مطمئنی
در VS Code منوی ... در Source Control: Commit → Undo Last Commit معمولاً --soft.
اگر push شده، تاریخچهٔ دیگران را تکهپاره میکنی. بهجایش git revert.
↩️ revert — Undo عمومی
git revert HEAD # آخرین را خنثی کن git revert -m 1 <merge-sha> # خنثیکردن merge (والد ۱ = شاخهٔ هدف)
Revert یک کامیت جدید میسازد که تغییرات را برعکس اعمال میکند. تاریخچه دروغ نمیگوید.
در GitHub: روی PR دگمهٔ Revert همین کار را تمیزتر انجام میدهد.
🛟 reflog — ماشین زمان اشارهگرها
هر حرکت HEAD در reflog ثبت میشود (معمولاً ۹۰ روز).
git reflog # e3a1... HEAD@{0}: reset: moving to HEAD~1 # 9f3a... HEAD@{1}: commit: feat(auth): ... git switch -c rescue HEAD@{1} # یا git reset --hard 9f3a1c
فایلی که هرگز add/commit نشده و Discard شده. Git آن را ندیده. از Local History خود VS Code (Timeline) کمک بگیر.
در VS Code: Timeline گاهی نسخههای محلی ذخیره میکند حتی بدون Git — آخرین تور ایمنی برای Untracked.
Junior — تفاوت restore و reset؟ restore فایلمحور است؛ reset اشارهگر شاخه را حرکت میدهد.
Mid — soft در برابر mixed؟ هر دو HEAD را حرکت میدهند؛ soft ایندکس را نگه میدارد.
Senior — revert یک merge چرا -m 1 میخواهد؟ چون merge دو والد دارد. باید بگویی «خط اصلی کدام است» تا diff معکوس معنا داشته باشد.
✅ چکلیست فهم
- نقشهٔ Undo را بلدی
restoreرا بهجای checkout فایل میزنی--hardرا برای کار عمومی ممنوع میدانی- یکبار با reflog نجات دادهای
فصل بعد: gitignore، attributes و LFS.