وقتی همهچیز خراب شد
When everything goes wrong: Git recovery scenarios
وقتی کسی میگوید «همهچیز پرید»، بدترین واکنش این است که سریع چند دستور پاککننده بزنیم. این فصل یک اتاق نجات است: اول میفهمیم Git هنوز چه چیزی دارد، بعد فقط همان چیزی را که لازم است حرکت میدهیم.
A teammate messages: “I think I lost a day of work.” Your hand reaches for reset, checkout, clean, or even recloning. Pause. First we need to learn what Git still has: perhaps the work was committed, staged, stashed, kept in another clone—or never entered Git at all.
اول چه چیزی را نباید بزنیم؟What should we not run first?
قبل از هر کاری دستت را از روی reset --hard و clean -f بردار. اول بپرس کار کجا بوده: commit شده؟ ناحیه آمادهسازی شده؟ stash شده؟ فقط ردیابینشده بوده؟ clone دیگری آن را دارد؟ همین جواب تعیین میکند Git چه شانسی برای نجات دارد.
Before trying a fix, ask: was it committed, only staged, stashed, left in the working tree or untracked, pushed, kept in another clone, or recorded as a reflog clue? Each answer leads to a different path.
Git یک دکمهٔ «برگرداندن روز گذشته» ندارد. فصل ۰۲ نشان داد commit، tree و blob چه هستند؛ فصل ۰۳ سه ناحیه را جدا کرد؛ فصل ۰۹ تفاوت reset، revert و restore را ساخت؛ و فصل ۱۰ reflog و شیءهای بینام را بررسی کرد. حالا همینها را در یک اتاق نجات به کار میگیریم، بیآنکه فرض کنیم هر چیزی حتماً قابلبازیابی است.
Git has no “restore yesterday” button. Chapter 02 established commits, trees, and blobs; Chapter 03 separated the three areas; Chapter 09 distinguished reset, revert, and restore; Chapter 10 examined reflogs and unnamed objects. Now we apply those ideas in one rescue room without assuming every bit is recoverable.
قاعدهٔ تکراری این فصل: اول چیزی را پاک نکن. اول بفهم Git الان چه چیزهایی را هنوز دارد. تا وقتی نمیدانی کدام اشارهگر یا فایل تنها نسخهٔ کارت است، reset --hard، checkout، clean، gc و prune را اجرا نکن.
The recurring rule is: Do not delete first. First find out what Git still has. Until you know which ref or file may be the only copy, do not run reset --hard, destructive checkout, clean, gc, or prune.
پروتکل نجات: یک قدم در هر نوبتRescue protocol: one change at a time
اول وضعیت را ثبت کن، نه اینکه «تمیزش» کنی. این فرمانها فقط نمایی از مخزن فعلی میدهند؛ خروجی را در پروندهٔ حادثه نگه دار. اگر فرمانی خطا داد، همان خطا هم مدرک است.
Record the state before trying to “clean it up.” These commands inspect the current repository; keep their output with the incident notes. A failed command is evidence too.
git status --short --branch git branch --show-current git rev-parse --verify HEAD git log --all --graph --decorate --oneline -30 git reflog --all --date=iso git stash list git remote -v git ls-files --others --exclude-standard
در status دنبال فایلهای آمادهشده، تغییرهای ردیابیشده و ??های ردیابینشده بگرد. rev-parse شناسهٔ commit فعلی را ثبت میکند؛ در مخزن تازه و بدون commit ممکن است شکست بخورد، و این خودش بخشی از وضعیت است. log --all تاریخچهٔ متصل به اشارهگرهای فعلی را میبیند؛ commit بینام ممکن است آنجا نباشد. reflog فقط دفترچهٔ محلی همین clone است.
In status, look for staged paths, tracked edits, and untracked ?? entries. rev-parse records the current commit ID; it may fail in a repository with no commits, which is itself part of the state. log --all shows history reachable from current refs; an unnamed commit may be absent. A reflog belongs only to this local clone.
# نمونه است؛ branch، شناسه و فایلها در مخزن تو فرق میکنند.
## HEAD (no branch)
M src/app.js
?? notes.txt
7ac31f2 (HEAD) HEAD@{0}: reset: moving to HEAD~2
9bd8a61 HEAD@{1}: commit: finish parser
stash@{0}: On main: wip layout
origin https://example.invalid/team/app.gitاین نمونه میگوید پوشه کاری هم تغییر دارد، یک فایل ردیابینشده هست، و reflog از reset قبلی سرنخ داده. اما ثابت نمیکند کدام نسخهٔ فایل روی دیسک بهتر است یا هیچ نسخهٔ دیگری وجود ندارد. قبل از حرکت دادن اشارهگر، اگر HEAD commit دارد، میتوانی فقط همان commit را با یک اشارهگر تازه حفظ کنی؛ تغییرهای index/پوشه کاری را جدا ذخیره کن.
This sample shows working-tree changes, an untracked file, and a previous reset in the reflog. It does not prove which on-disk file is best or that no other copy exists. Before moving a ref, if HEAD names a commit, you can preserve that commit with a new ref; save index and working-tree changes separately.
git branch rescue/pre-recovery HEAD git diff --binary > ../working-tree.patch git diff --cached --binary > ../index.patch git ls-files --others --exclude-standard
شاخهٔ rescue/pre-recovery فقط commitی را نگه میدارد که HEAD همین حالا به آن اشاره میکند؛ ناحیه آمادهسازی، تغییرهای آمادهنشده و ردیابینشده را ذخیره نمیکند. دو patch بالا تغییرهای ردیابیشده را جدا ثبت میکنند. فایلهای ردیابینشده را در پوشهای امن کپی کن. اگر اصل مخزن مشکوک به خرابی است، اول از کل پوشهٔ مخزن یک کپی جدا برای بررسی بساز. این کپیها هم فقط همان چیزی را حفظ میکنند که واقعاً در آنها بوده؛ چیزی را که قبلاً پاک شدهاند جادو نمیکنند.
The rescue/pre-recovery branch preserves only the commit HEAD currently names; it does not save the index, unstaged edits, or untracked files. The two patches capture tracked changes separately. Copy untracked files to a safe directory. If repository corruption is suspected, first make a separate filesystem copy of the repository for inspection. These copies preserve only what they actually contain; they cannot recreate something already deleted.
| قدمStep | کارAction | چیزی که هنوز ثابت نشدهWhat remains unproven |
|---|---|---|
| ۱ | دستورهای مخرب را متوقف کنStop destructive commands | هنوز نمیدانیم کار کجا ماندهWe do not yet know where the work remains |
| ۲–۴ | وضعیت، شاخه/HEAD، گراف و reflog را ثبت کنRecord status, branch/HEAD, graph, and reflog | log عادی، شیء بینام را الزاماً نشان نمیدهدOrdinary log may omit unnamed objects |
| ۵ | اشارهگر، patch و کپی فایلهای ردیابینشده را نگه دارPreserve refs, patches, and untracked-file copies | اشارهگر نجات همهٔ فایلهای روی دیسک نیستA rescue ref is not a copy of every disk file |
| ۶–۸ | یک چیز را تعمیر و همان شاهد را دوباره بررسی کنRepair one thing and repeat the same check | موفقیت یک فرمان بهتنهایی صحت همهچیز را ثابت نمیکندOne successful command does not prove everything is correct |
نام گم شد یا خودِ شیء؟ این دو یکی نیستندWas the name lost—or the object?
فصل ۰۵ گفت شاخه یک اشارهگر سبک است؛ فصل ۰۲ گفت commit به tree و blob میرسد. حذف شاخه میتواند نام را بردارد، در حالی که شیءهای commit هنوز مدتی در مخزن مانده باشند. از طرف دیگر اگر شیء خراب یا واقعاً حذف شده باشد، ساختن شاخه تازه چیزی برای پرکردن ندارد.
Chapter 05 showed that a branch is a lightweight ref; Chapter 02 showed how a commit reaches trees and blobs. Deleting a branch can remove the name while commit objects remain in the repository for a time. But if an object is corrupt or actually gone, creating another branch gives it nothing to point to.
git reflog --all را برای حرکت نامها بخوان؛ اگر شناسهای پیدا شد، قبل از تغییر، خود commit را با git show --stat --oneline OID بشناس و با git cat-file -e 'OID^{commit}' وجود commit را بررسی کن. اگر قرار است نگهش داری، یک rescue شاخه بساز و با git show-ref بررسی کن که نام تازه واقعاً به همان شناسه اشاره میکند.
Read ref movements with git reflog --all. If you find an ID, inspect the commit with git show --stat --oneline OID before changing anything, and test its existence with git cat-file -e 'OID^{commit}'. If you need to keep it, create a rescue branch and confirm with git show-ref that the new name points to that ID.
اگر اشارهگر پیدا نشد، git log --all کافی نیست؛ این دستور همهٔ شیءهای بینام را نمیگردد. روی مخزن سالم یا کپیِ جداشده میتوانی git fsck --full --no-reflogs --unreachable را بررسی کنی. خروجی ممکن است commitهای unreachable بدهد؛ هر کدام را با git show بخوان. fsck ابزار جستوجو/بررسی است، نه تعمیرکار جادویی.
If no ref appears, git log --all is not enough; it does not enumerate every unnamed object. On a healthy repository or a separate copy, inspect git fsck --full --no-reflogs --unreachable. It may list unreachable commits; examine candidates with git show. Fsck is an inspection tool, not a magic repair service.
unreachable commit 71ab23c... unreachable tree 22cd901... dangling blob 4fe1a02...
این خروجی میگوید چند شیء در مخزن هستند ولی از ریشههایی که این اجرا بررسی کرده reachable نیستند. شناسهٔ commit را میتوانی وارسی و در صورت نیاز اشارهگر کنی؛ blob بهتنهایی ممکن است اسم فایل یا زمان ویرایش را نداشته باشد. حتی یک شیء سالم هم ثابت نمیکند تمام تغییرهای روز گمشده ذخیره شدهاند.
This output says some objects exist but are not reachable from the roots checked by this run. You can inspect a commit ID and, if useful, create a ref for it. A blob alone may have no filename or edit timestamp. Even a healthy object does not prove that every change from the lost day was stored.
دفترچهٔ reflog محلی است و ردهایش نگهداری ابدی ندارند؛ زمان نگهداری میتواند با تنظیم Git فرق کند. وقتی سرنخ معتبر پیدا شد، با ساختن اشارهگر آن را زود از حالت بینام بیرون بیاور. در دوران نجات git gc، git prune یا expire کردن reflog را اجرا نکن. مرجعها: reflog و fsck.
Reflogs are local, and their entries are not retained forever; the period can vary with Git configuration. Once you have a credible clue, promptly protect it with a ref. During recovery, do not run git gc, git prune, or reflog expiration. See the official git-reflog and git-fsck manuals.
rebase بد: اگر هنوز وسطش هستی، زور نزنA bad rebase: if it is still in progress, do not force through
rebase وسط تعارض متوقف شده و حالا نمیدانی کدام فایل باید بماند. هنوز operation فعال است؟ اول git status را بخوان و تغییرهای قبل از rebase را تا جایی که میتوانی جدا نگه دار. اگر تصمیم گرفتی همین تلاش را کنار بگذاری، git rebase --abort مسیر استاندارد پایاندادن به rebase نیمهکاره است؛ بعد دوباره همان وضعیت و گراف را بررسی کن.
A rebase stopped at a conflict, and you no longer know which version should remain. Is the operation still active? Read git status first and preserve pre-rebase changes separately where possible. If you decide to abandon this attempt, git rebase --abort is the standard way to end an in-progress rebase; then inspect the same status and graph again.
interactive rebase in progress; onto 42bc113 Last command done (1 command done): pick 8af0312 add parser No commands remaining. You are currently editing a commit while rebasing branch 'feature' on 'main'.
پیام بالا میگوید Git هنوز در وضعیت rebase است؛ هنوز ثابت نمیکند کار شروعشده قبل از rebase یا ناحیه آمادهسازی بیخطر است. اگر rebase قبلاً کامل شده و نتیجه بد است، --abort دیگر کار نمیکند. reflog و پیامهای rebase را پیدا کن، شناسه شیء قبلی را با show بررسی کن و قبل از حرکت دادن شاخه، آن را با اشارهگر نجات حفظ کن. ORIG_HEAD ممکن است سرنخ باشد، اما بعد از عملیات دیگر هم میتواند عوض شده باشد؛ بدون بررسی کورکورانه reset نکن.
The output says Git is still in a rebase; it does not prove that pre-rebase work or the index is safe. If the rebase already completed, --abort no longer applies. Find the reflog entries and rebase messages, inspect the old OID with show, and preserve it with a rescue ref before moving the branch. ORIG_HEAD may help, but later operations can change it; never reset to it blindly.
اگر تعارض فقط از merge میآید، git merge --abort را بعد از ثبت وضعیت و حفظ تغییرهای مهم به کار ببر. اگر توالی cherry-pick هنوز ادامه دارد، git cherry-pick --abort را انتخاب کن. abort برای operation درحالاجراست؛ بعد از commit نهایی باید با توجه به خصوصی یا مشترک بودن نتیجه، ادامه بدهی. مستند pull نیز پایاندادن به merge/rebase نیمهکاره را شرح میدهد.
If the conflict is from a merge, use git merge --abort only after recording state and preserving important changes. If a cherry-pick sequence is still active, choose git cherry-pick --abort. Abort applies to an operation in progress; after a final commit, the next step depends on whether the result is private or shared. The git-pull documentation also describes ending an in-progress merge or rebase.
commit روی شاخهٔ اشتباه: commit را پیدا کن، بعد جابهجایش کنCommitted on the wrong branch: locate the commit before moving it
یک commit درست ساختهای، اما روی main بوده نه روی feature. اول با git status --short --branch و git log --all --graph --decorate --oneline مطمئن شو کدام اشارهگر جلو رفته و آیا commit از قبل در مقصد هست. یک نام نجات برای شناسه شیء بساز، بعد روی شاخهٔ مقصد برو و فقط وقتی patch را لازم داری cherry-pick کن.
You made a valid commit, but on main instead of feature. First use git status --short --branch and git log --all --graph --decorate --oneline to see which ref moved and whether the target already contains the commit. Name the OID with a rescue ref, switch to the intended branch, and cherry-pick only if that patch is needed there.
* 94ac210 (HEAD -> main) add export option * 122bc40 (feature/export) start exporter
قبل از جابهجایی، commit را با git show --stat 94ac210 بررسی کن. اگر commit خصوصی و فقط روی شاخهٔ غلط است، نگهداشتن یک کپی روی شاخهٔ مقصد معمولاً امنتر از پاککردن عجولانهٔ شاخهٔ اول است. اگر قبلاً push یا با دیگران share شده، تاریخچهٔ آنها را با reset بازنویسی نکن؛ راه جبران را با تیم انتخاب کن، معمولاً با commit تازه یا revert.
Inspect the commit with git show --stat 94ac210 before moving anything. If it is private and only on the wrong branch, preserving a copy on the intended branch is usually safer than hurriedly deleting the first branch. If it was pushed or shared, do not rewrite teammates’ history with reset; agree on a forward correction, often a new commit or revert.
secret در commit: اول اعتبارنامه را باطل کنA secret in a commit: revoke the credential first
یک token واقعی وارد commit شده و شاید push هم شده. اولین کار پاککردن commit نیست؛ اعتبارنامه را فوراً revoke یا rotate کن. تا وقتی secret معتبر است، حتی مخفیکردن شاخه هم کسی را که قبلاً آن را دیده متوقف نمیکند.
A real token entered a commit and may have been pushed. The first action is not deleting the commit; revoke or rotate the credential immediately. While it remains valid, hiding a branch cannot stop someone who already saw it.
مقدار را در خروجی تمرین، issue، chat، screenshot یا همین گزارش رخداد نچسبان. دسترسی و زمان push را مشخص کن، مسئول سامانه را با مسیر امن خبر کن، کلید جایگزین بساز و مصرف کلید قدیمی را بررسی کن.
Do not paste the value into exercise output, an issue, chat, screenshot, or the incident report. Identify its access and push time, contact the system owner securely, issue a replacement, and review use of the old key.
بعد از باطلکردن، تیم میتواند با هماهنگی تاریخچه را بازنویسی و نسخهٔ میزبان را اصلاح کند؛ اما push اجباری رمز را از cloneها، forkها، cacheها یا فایلهای دانلودشده پس نمیگیرد. برای حذف کاملتر ممکن است پشتیبانی میزبان هم لازم باشد. راهنمای GitHub صریحاً چرخاندن اعتبارنامه را قدم اول میداند: Removing sensitive data from a مخزن. برای GitLab یا میزبان دیگر، فرایند و پشتیبانی همان سرویس را بررسی کن.
After revocation, the team may coordinate a history rewrite and hosted-repository cleanup, but force-pushing cannot recall the secret from clones, forks, caches, or downloaded files. The host may need to assist with complete removal. GitHub explicitly makes credential rotation the first step in its sensitive-data removal guide. For GitLab or another host, check that service’s process and support.
شیء خراب شده یا فایل اصلاً ذخیره نشده؟Is an object corrupt—or was the file never stored?
دو جمله ممکن است هر دو با «فایلم نیست» شروع شوند، ولی پاسخشان یکی نیست. در حالت اول Git شیء را قبلاً داشته و حالا خطای اتصال، شیء گمشده یا hash mismatch میدهد. در حالت دوم فایل ردیابینشده بوده، هرگز ناحیه آمادهسازی نشده و کسی پاکش کرده. git fsck --full برای بررسی صحت و اتصال شیءهاست؛ خودش شیء خراب را تعمیر یا نسخهٔ سالم را از هیچجا تولید نمیکند.
Two reports can both begin with “my file is gone” but need different answers. In the first, Git once had an object and now reports a connectivity error, a missing object, or a hash mismatch. In the second, an untracked file was never staged and somebody deleted it. git fsck --full checks object validity and connectivity; it does not repair a corrupt object or manufacture a healthy copy.
git fsck --full # نمونههای ممکن، بسته به مخزن: missing blob 4fe1a02... error: hash mismatch 7bd83d...
این نمونه فقط نشان میدهد شیء مورد انتظار در مخزن فعلی مشکل دارد. عملیات housekeeping را متوقف کن، از مخزن کپی بگیر، شناسهٔ شیء را ثبت کن و یک clone یا نسخه پشتیبان سالم را بیاب. اگر آن شیء در نسخهٔ سالم موجود و قابلدسترسی باشد، میشود از آن منبع دوباره fetch/نسخهبرداری کرد؛ بدون آن، fsck چیزی برای جایگزینی ندارد. به سراغ gc، prune یا fsck --lost-found روی تنها نسخهٔ اصلی نرو.
This sample only says an expected object has a problem in the current repository. Stop housekeeping, copy the repository, record the object ID, and locate a healthy clone or backup. If that object exists in an accessible healthy copy, it may be fetched or copied from there; without such a source, fsck has nothing to replace it with. Avoid gc, prune, or fsck --lost-found on the only original copy.
اگر فایلی ردیابینشده و هیچوقت ناحیه آمادهسازی نشده بود، Git هیچ blobی از آن نگرفته است. بررسی status یا fsck نمیتواند محتوایی را که هرگز وارد پایگاه اشیا نشده برگرداند. سطل زباله، محلی تاریخچه ویرایشگر، عکس فوری سیستم، نسخه پشتیبان یا نسخهٔ همکار را جدا بررسی کن؛ اگر هیچکدام نیست، صادقانه بگو بازیابی از Git ممکن نیست. همین مرز، فرق «اشارهگر گمشده» با «دادهای که هرگز ذخیره نشد» است.
If a file was untracked and never staged, Git never received a blob for it. Neither status nor fsck can restore content that never entered the object database. Check the recycle bin, editor local history, system snapshots, backups, or a teammate’s copy; if none exists, say honestly that Git cannot recover it. That is the boundary between a lost ref and data that was never stored.
git clean ابزار نجات نیستgit clean is not a rescue command
این فرمان ردیابینشدهها را حذف میکند؛ همان جایی که ممکن است تنها کپی فایل هنوز آنجا باشد. اگر فقط میخواهی ببینی چه چیزهایی هدف حذفاند، از حالت پیشنمایش استفاده کن:
This command removes untracked files—the very place where the only remaining copy might live. If you only want to see what would be targeted, use its preview mode:
git clean -nd
نمونهٔ خروجی میتواند مسیرهای ردیابینشده را فهرست کند؛ -n یعنی حذف واقعی انجام نمیشود و -d پوشهها را هم در پیشنمایش میآورد. حتی با خروجی ظاهراً بیخطر، فرمان واقعی را در اتاق نجات اجرا نمیکنیم. -x دامنه را به فایلهای ignored هم گسترش میدهد. این فرمان برای پاکسازی آگاهانه است، نه پیدا کردن فایل گمشده. مستند رسمی clean تفاوت preview و حذف را توضیح میدهد.
Representative output may list untracked paths; -n means no deletion happens, and -d includes directories in the preview. Even if the list looks harmless, we do not run the real deletion command in a rescue room. -x expands the target to ignored files too. This is for deliberate cleanup, not finding a missing file. See the official git-clean manual.
اگر مسیر ناشناخته است، از آن بیرون کپی بگیر یا مالکیتش را روشن کن. فهرست git clean -n فقط میگوید Git چه چیزی را حذف میکند؛ نمیگوید آن فایل برای تو بیارزش است.
If a path is unfamiliar, copy it elsewhere or identify its owner. git clean -n only says what Git would remove; it does not say the file is disposable.
مینیپروژه: اتاق نجاتMini-project: the rescue room
چهار نشانه، دو clone، بدون پاکسازی قهرمانانه
Four symptoms, two clones, no heroic cleanup
این پروژه مثل یک اتاق نجات است: چند مشکل همزمان جلویت میگذاریم، ولی هیچ دستور مرحلهبهمرحلهای در شروع نمیدهیم. اول باید وضعیت را ثبت کنی، بعد بفهمی کدام داده هنوز در Git یا clone دیگر وجود دارد و فقط بعد از آن دست به تعمیر بزنی.
A team reports that feature history vanished, an important commit is missing from log, a teammate’s branch moved backward after a force-push, and a local note disappeared. Your job is not to find the fastest command; show what evidence locates stored data, what you preserved safely, and where Git has no answer.
مرز ایمنی
Safety boundary
فقط زیر پوشهای تازه به نام rescue-room کار کن. دستورات ساخت رخداد عمداً شاخه را حذف، reset یا push اجباری میکنند؛ آنها را هرگز در مخزن کاری اجرا نکن. همهٔ تمرین روی دو clone دورریختنی و یک bare مخزن راه دور محلی است. هیچجا gc یا prune اجرا نکن.
Work only beneath a newly created rescue-room directory. The incident setup deliberately deletes a branch, resets, and force-pushes; never run it in a working repository. Everything happens in two disposable clones and a local bare remote. Do not run gc or prune.
مخزن حادثه را بساز
Create the incident repositories
mkdir rescue-room cd rescue-room git init --bare --initial-branch=main remote.git git clone remote.git writer git -C writer config user.name "Rescue Learner" git -C writer config user.email "rescue@example.test" printf 'base\n' > writer/app.txt git -C writer add app.txt git -C writer commit -m "base" git -C writer push -u origin main git clone remote.git witness git -C witness config user.name "Witness" git -C witness config user.email "witness@example.test"
حالا رخدادهای محلی را دقیقاً با فرمانهای زیر در writer بساز. همهٔ reset --hardها فقط روی clone دورریختنیاند. در پایان شناسه شیءها را یادداشت کن؛ قرار نیست جواب نجات در صفحه داده شود.
Create the local incidents in writer with the commands below. Every reset --hard is confined to the disposable clone. Record the OIDs; the rescue answer is intentionally not supplied.
git -C writer switch -c lost-feature printf 'feature one\n' > writer/feature.txt git -C writer add feature.txt git -C writer commit -m "feature one" printf 'feature two\n' >> writer/feature.txt git -C writer commit -am "feature two" git -C writer switch main git -C writer branch -D lost-feature git -C writer switch -c reset-case printf 'reset one\n' > writer/reset.txt git -C writer add reset.txt git -C writer commit -m "reset checkpoint one" printf 'reset two\n' >> writer/reset.txt git -C writer commit -am "reset checkpoint two" git -C writer rev-parse HEAD git -C writer reset --hard HEAD~2 git -C writer switch --detach main printf 'detached work\n' > writer/detached.txt git -C writer add detached.txt git -C writer commit -m "detached work" git -C writer rev-parse HEAD git -C writer switch main
برای رخداد مشترک یک commit تازه روی main بساز و push کن؛ clone دوم آن را fetch کند. سپس فقط writer را به عقب ببر و با --force-with-lease push کن. شاهد را fetch دوباره نکن تا اشارهگر قدیمیاش بماند.
Create and push one new commit on main; fetch it in the second clone. Then move only writer backward and push with --force-with-lease. Do not fetch again in witness, so its older remote-tracking ref remains available.
git -C writer switch main printf 'shared commit\n' >> writer/app.txt git -C writer commit -am "shared work" git -C writer push git -C witness fetch origin git -C writer reset --hard HEAD~1 git -C writer push --force-with-lease origin main
برای پروندهٔ ردیابینشده، فایل را داخل writer بساز تا وضعیت آن را با ?? نشان دهد؛ بعد فقط همان فایل آزمایش را حذف کن. Git Bash فرض شده است.
For the untracked-file ticket, create the file inside writer so status shows ??, then delete only that named lab file. These shell examples assume Git Bash.
printf 'never staged or committed\n' > writer/never-tracked.txt git -C writer status --short rm writer/never-tracked.txt
پروندههایی که باید حل کنی
Incident tickets to solve
- شاخهٔ حذفشدهDeleted branch
نام
lost-featureدیگر وجود ندارد. دو commit موردنیاز را با مدرک پیدا کن، قبل از حرکت شاخه آنها را بشناس و به نامی پایدار وصل کن.The name
lost-featureno longer exists. Locate its two commits with evidence, inspect them, and give them stable names before moving any branch. - reset سختHard reset
در
reset-caseدو commit در log عادی دیده نمیشوند. شناسهها را پیدا کن، اشارهگر نجات بساز و ثابت کن پوشه کاری اکنون و commit بازیابیشده را با هم اشتباه نگرفتهای.Two commits on
reset-caseno longer appear in ordinary log. Find their IDs, create rescue refs, and prove you have not confused the current working tree with the recovered commits. - commit در جداشده HEADCommit made in detached HEAD
یک commit ساخته شده، اما نام شاخهای جلو نرفته. شناسه شیء را مشخص کن و یک اشارهگر بساز تا از حالت بینام بیرون بیاید.
A commit exists, but no branch name advanced. Identify its OID and create a ref so it is no longer unnamed.
- push اجباری اشتباهAccidental force-push
در
witnessشناسه شیء قدیمی را پیدا و بررسی کن؛ یک شاخهٔ rescue با push معمولی منتشر کن. تا وقتی تیم تأیید نکرده،mainرا دوباره force نکن.In
witness, locate and inspect the old OID, then publish a rescue branch with a normal push. Do not force-push main again until the team agrees. - فایل ردیابینشده حذفشدهDeleted untracked file
در
writerفایل یادداشت را بساز تا وضعیت آن را??نشان دهد؛ آن را نه ناحیه آمادهسازی و نه commit کن، سپس فقط همان فایل تمرینی را حذف کن. گزارش بده Git چه چیزی برای بازیابی دارد و بیرون Git کجا باید دنبال نسخه بگردی.Create a note inside
writerso status shows??; never stage or commit it, then delete only that lab file. Report what Git has to recover and which external locations you would check.
معیار تحویل
Acceptance criteria
- برای هر رخداد: نشانه، خروجی/شناسهٔ مدرک، تشخیص، تعمیر یا محدودیت بازیابی، و یک بررسی نهایی ثبت شده باشد.
- For each incident, record the symptom, evidence/ID, diagnosis, repair or recovery limit, and one final verification.
- هیچ شناسه شیء نجاتیافتهای بدون بررسی با
showبه شاخه اصلی وصل نشده باشد. - No recovered OID is attached to a primary branch without being inspected with
show. - نسخهٔ commit گمشده در clone دوم با یک اشارهگر تازه قابل مشاهده باشد؛ reflog سرور را مفروض نگرفته باشی.
- The missing commit is visible under a new ref from the second clone; no server reflog was assumed.
- برای فایل ردیابینشده فقط نسخهٔ بیرونی را بررسی کرده باشی و قول بازیابی Git نداده باشی.
- For the untracked file, you checked external copies and made no Git-recovery promise.
git status --short --branchوgit log --all --graph --decorate --onelineبرای وضعیت پایانی نگه داشته شده باشد.- Keep final
git status --short --branchandgit log --all --graph --decorate --onelineoutput.
اگر یک commit در خروجی اول پیدا نشدIf a commit is missing from the first view
تفاوت سه پرسش را نگه دار: branch/ref هنوز هست؟ reflog محلی حرکتی ثبت کرده؟ شیء در مخزن مانده؟ اگر جواب همه منفی است، clone دوم و نسخههای بیرونی را بررسی کن؛ و اگر باز هم مدرکی نداری، نتیجه را بهعنوان «نامعلوم/غیرقابلتضمین» گزارش کن.
Keep three questions separate: does a branch/ref remain, did a local reflog record movement, and does the object remain in the repository? If all are negative, inspect a second clone and external copies; if evidence is still absent, report the result as unknown/not guaranteed.
۱۸ پروندهٔ رخداد18 incident tickets
هر پرونده را با دستور شروع نکن؛ با مشاهده شروع کن. گاهی حرفهایترین جواب این است که «فعلاً هیچ دستور مخربی نزن» و گاهی هم باید صریح بگویی «Git این فایل را هرگز ذخیره نکرده و بازیابیاش را تضمین نمیکند».
Start every answer with evidence. If the right answer is “do nothing destructive yet” or “Git cannot guarantee recovery,” say so and name the next check.
معیار موفقیت هر پرونده: وضعیت را از روی شاهد درست تشخیص بده، اقدام امن بعدی یا مرز بازیابی را روشن بگو و ادعایی فراتر از مدرک نکن.
Success criterion for every ticket: diagnose from the right evidence, state the safe next action or recovery limit, and claim no more than the evidence supports.
همکارت میگوید روز کاریاش گم شده. هنوز چیزی اجرا نکرده. در یک دقیقهٔ اول چه چیزهایی ثبت میکنی و کدام فرمانها را فعلاً ممنوع میکنی؟
A teammate says a day of work is gone and has run nothing yet. What do you record in the first minute, and which commands do you temporarily rule out?
راهنماHint
پوشهٔ کاری، ناحیه آمادهسازی، شاخه/HEAD، stash، clone دیگر را جدا بپرس.
Ask separately about working tree, index, branch/HEAD, stash, and another clone.
پاسخ و دلیلReasoning
وضعیت، شاخه/HEAD، گراف و reflog را ثبت میکنم؛ مسیرهای ردیابینشده و stash را هم میشمارم و میپرسم چه چیزی push شده یا در clone دیگر هست. تا آنجا reset --hard، clean، gc و prune ممنوعاند. این فهرست محلهای احتمالی را باز میکند، ولی هنوز وجود نسخه را ثابت نمیکند.
Record status, branch/HEAD, graph, and reflog; enumerate untracked paths and stashes, and ask what was pushed or exists in another clone. Until then, rule out reset --hard, clean, gc, and prune. This list opens possible locations but does not prove a copy exists.
خروجی ## HEAD (no branch)، M src/app.js و ?? notes.txt است. کدام دو نسخهٔ فایل در Git معلوماند و کدام مسیر نیازمند بررسی بیرونی است؟
Output shows ## HEAD (no branch), M src/app.js, and ?? notes.txt. Which file versions are represented in Git, and which path needs an external check?
راهنماHint
M برای فایل ردیابیشده است؛ ?? هنوز وارد ناحیه آمادهسازی نشده.
M marks a tracked file; ?? has not entered the index.
بیا بازش کنیمInterpretation
src/app.js نسخهٔ commit/index و نسخهٔ پوشه کاری دارد؛ ابتدا diff و آمادهشده diff را جدا ببین. notes.txt در این لحظه ردیابینشده است، پس اگر پاک شده و هرگز ناحیه آمادهسازی نشده، Git محتوا ندارد. ممکن است نسخهٔ بیرونی یا stash/worktree دیگری وجود داشته باشد؛ وضعیت بهتنهایی تاریخچهٔ کامل فایل را نمیگوید.
src/app.js has commit/index and working-tree versions; inspect unstaged and staged diffs separately. notes.txt is currently untracked, so if deleted and never staged, Git has no content for it. An external copy or another stash/worktree may exist; status alone does not reveal the file’s whole history.
commit add export option روی main است، ولی باید در قابلیت باشد. همکار میگوید «همین الان main را reset کن». پاسخ امنتر و شرطش چیست؟
Commit add export option landed on main but belongs on a feature branch. A teammate says, “Reset main now.” What is safer, and under what condition?
راهنماHint
ابتدا ببین commit push یا share شده یا نه و مقصد آن را ندارد.
First check whether it was pushed/shared and whether the target already contains it.
راهحل و توضیحDecision
شناسه شیء را با show وارسی و اشارهگر نجات بساز. اگر commit فقط محلی و خصوصی است، میتوانی با هماهنگی مقصد شاخه آن را cherry-pick کنی؛ اما اگر مشترک شده، reset شاخهٔ مشترک را جابهجا میکند. از commit تازه یا revert طبق وضعیت استفاده کن، نه پاککردن کور.
Inspect the OID with show and create a rescue ref. If the commit is private and local, it can be cherry-picked to the target; if shared, resetting moves a shared branch. Prefer a new commit or revert according to state over blind deletion.
git branch -D feature/report اجرا شد. آیا حالا حتماً commitها gone هستند؟ کدام دو سرچشمه را جدا میگردی؟
git branch -D feature/report was run. Are the commits necessarily gone? Which two sources do you inspect separately?
راهنماHint
نام شاخه و شیءهای زیرش را یکی نگیر.
Do not confuse the branch name with the objects it pointed to.
چرا این جواب درست استAnswer
خیر. reflogهای در دسترس را برای شناسه شیء بگرد؛ حذف شاخه ممکن است reflog همان شاخه را هم برداشته باشد، پس HEAD reflog و git fsck --full --no-reflogs --unreachable را نیز در مخزن مناسب بررسی کن. هر commit نامزد را با show بشناس و قبل از پاکسازی اشارهگر بساز. وجود نسخه تضمین نیست.
No. Search available reflogs for an OID; deleting a branch may also remove its branch reflog, so inspect HEAD’s reflog and git fsck --full --no-reflogs --unreachable in the appropriate repository. Identify candidates with show and create refs before cleanup. A surviving copy is not guaranteed.
بعد از reset --hard HEAD~3 سه commit از log رفتهاند. HEAD@{1} را دیدهای، اما کافی است همان را فوراً reset کنی؟
After reset --hard HEAD~3, three commits vanished from log. You see HEAD@{1}; is it safe to reset to it immediately?
راهنماHint
شمارهٔ reflog با هر حرکت عوض میشود؛ اول شناسه شیء و محتوا را بازرسی کن.
Reflog indices move as actions occur; inspect the OID and content first.
بررسی جوابReasoning
نه. reflog را تازه بخوان، شناسه شیء دقیق را بردار، با show --stat و والدهایش تأیید کن، بعد شاخه نجات بساز. این کار commitهای ذخیرهشده را نگه میدارد؛ تغییرهای آمادهنشده که hard reset قبلاً overwrite کرده تضمیناً داخل reflog نیستند.
No. Reread the current reflog, copy the exact OID, inspect it and its parents with show, then create a rescue branch. This preserves stored commits; unstaged edits overwritten by hard reset are not guaranteed to be in a reflog.
rebase هنوز تعارض دارد. همکار پیشنهاد میدهد دستی فایلها را پاک و از نو بسازی. گزینهٔ کمریسک چیست و قبل از آن چه میکنی؟
A rebase is still conflicted. A teammate suggests deleting files and rebuilding them manually. What is the lower-risk option, and what do you do first?
راهنماHint
در این مورد operation هنوز فعال است.
Here the operation is still in progress.
پاسخ پیشنهادیAnswer
اول وضعیت، ناحیه آمادهسازی و تغییرهای محلی را ثبت/حفظ کن. اگر تغییرهای مهمی نیست و میخواهی rebase را کنار بگذاری، git rebase --abort را اجرا کن، بعد همان وضعیت و گراف را دوباره مقایسه کن. اگر operation تمام شده، abort دیگر راهحل نیست؛ شناسه شیء قبلی را از reflog پیدا و قبل از حرکت اشارهگر نامگذاری کن.
Record status, index, and local edits first. If there is no valuable unpreserved work and you want to abandon the rebase, run git rebase --abort, then compare the same status and graph again. If it already completed, abort no longer applies; locate the old OID in reflog and name it before moving refs.
از اینجا پروندهها سختتر میشوند، چون چند سرنخ همزمان وجود دارد. قبل از حرکت، یک جدول کوچک برای خودت بساز: «چه چیزی گم به نظر میرسد؟ آخرین بار کجا ذخیره شده؟ چه نام یا clone دیگری ممکن است هنوز به آن برسد؟»
From here the incidents get harder because several clues exist at once. Before moving anything, make a small table: “what looks lost, where was it last stored, and which name or clone may still reach it?”
در جداشده HEAD یک commit ساختهای و حالا هنوز همانجا هستی. سادهترین قدم پیشگیرانه چیست؟ اگر قبلاً شاخه عوض کردهای، چه مدرکی میخواهی؟
You made a commit in detached HEAD and are still there. What is the simplest preventive step? If you already switched branches, what evidence do you need?
راهنماHint
اگر HEAD هنوز روی همان commit است، نیازی به جستوجوی کور در شیءها نیست.
If HEAD still points at the commit, there is no need for a blind object hunt.
پاسخ و دلیلLow-risk path
در همان لحظه git switch -c rescue/detached-work اجرا کن تا commit نام بگیرد. اگر قبلاً جابهجا شدی، reflog/known شناسه شیء را بخوان، commit را با show بررسی کن و سپس شاخه بساز. اگر شناسه شیء پیدا نشد یا شیء نگهداری نشده، بازیابی را تضمین نکن.
Run git switch -c rescue/detached-work immediately to name the commit. If you already moved away, inspect the reflog or known OID, verify it with show, then create a branch. If no OID is found or the object was not retained, do not guarantee recovery.
یک cherry-pick تعارض خورده و تغییرهای قبل از آن هم مهماند. آیا --abort را بیثبت وضعیت میزنی؟
A cherry-pick conflicts, and pre-existing changes matter too. Would you run --abort without recording state?
راهنماHint
abort operation را لغو میکند، اما یادداشت وضعیت قبل، امکان مقایسه میدهد.
Abort cancels the operation; a before-state record lets you compare what happened.
بیا بازش کنیمAnswer
نه. وضعیت، diff و ناحیه آمادهسازی را نگه دار و اگر ممکن است patch/کپی امن بساز. بعد اگر قصد لغو داری git cherry-pick --abort بزن و دوباره همانها را بخوان. abort را با recovery دلخواه یکی ندان؛ نتیجه را با شاهد قبل مقایسه کن.
No. Save status, diff, and index evidence and make a safe patch/copy if possible. If you choose to cancel, run git cherry-pick --abort and inspect them again. Do not equate abort with arbitrary recovery; compare against the recorded before-state.
merge commit اشتباه به شاخهٔ مشترک push شده. reset --hard HEAD^ یا revert -m 1؟ چه چیزی انتخاب را تعیین میکند؟
A wrong merge commit was pushed to a shared branch. reset --hard HEAD^ or revert -m 1? What determines the choice?
راهنماHint
آیا تاریخچه را دیگران گرفتهاند؟ اگر merge revert میشود، کدام والد خط اصلی بود؟
Have others consumed the history? If reverting a merge, which parent was the mainline?
راهحل و توضیحReasoning
روی شاخه مشترک معمولاً commit تازهای با revert میسازیم تا اشارهگر مشترک را عقب نکشیم. برای merge باید والد اصلی را با گراف/show مشخص کرد؛ -m 1 را حفظ نکن مگر والد اول واقعاً خط مقصد باشد. اگر merge هنوز commit نشده، ابتدا حفظ وضعیت و سپس merge --abort را بسنج.
On a shared branch, usually add a revert commit rather than moving the shared pointer backward. For a merge, identify the mainline parent from graph/show; do not use -m 1 unless the first parent is actually the target line. If it is uncommitted, preserve state and consider merge --abort.
همکار میگوید «مخزن راه دور reflog را ببین» تا شاخه حذفشده را پیدا کند. کاربر عادی به کدام شواهد واقعیتر تکیه میکند؟
A teammate says, “Check the remote reflog” to find a deleted branch. Which evidence is more realistic for an ordinary user?
راهنماHint
چه کسی محلی reflog دارد؟ clone دوم چه چیزی از قبل fetch کرده؟
Who owns local reflogs? What did a second clone fetch earlier?
چرا این جواب درست استAnswer
دنبال clone همکار، اشارهگر رهگیریِ مخزن راه دور قدیمی، شناسه شیء ثبتشده در log/build یا branch/tag نجات بگرد. reflog در clone خود هر نفر محلی است و معمولاً کاربر به دفترچهٔ سرور دسترسی ندارد. هر شناسه باید قبل از push دوباره با show بررسی شود.
Look for a teammate’s clone, an old remote-tracking ref, an OID recorded by logs/builds, or an existing rescue branch/tag. Reflogs are local to each clone, and ordinary users generally cannot inspect the server’s journal. Verify every ID with show before publishing it.
بعد از push اجباری، شاخه مخزن راه دور به commit قدیمی برگشته ولی clone دوم شناسه شیء تازه را دارد. اولین push تو باید به main force شود؟
After a force-push, the remote branch moved back but a second clone has the newer OID. Should your first push force main forward?
راهنماHint
اول commit را نامگذاری و از حذف دوباره محافظت کن.
Name and protect the commit before changing a shared branch again.
بررسی جوابAnswer
نه. شناسه شیء را در clone دوم بازرسی کن، یک شاخه rescue بساز و با push معمولی همان شاخهٔ جدید را منتشر کن. سپس با صاحب شاخه، CI و مصرفکنندهها هماهنگ کن که آیا main باید جابهجا شود. push نجات یک اشارهگر جدا میسازد؛ بهتنهایی همهٔ cloneها را اصلاح نمیکند.
No. Inspect the OID in the second clone, create a rescue branch, and publish that new branch with a normal push. Then coordinate with branch owners, CI, and consumers about whether main should move. The rescue push creates a separate ref; it does not repair every clone.
یک API key روی شاخه خصوصی commit و push شده، اما PR هنوز باز است. آیا اول commit را از شاخه پاک میکنی؟
An API key was committed and pushed to a private branch, but the PR is still open. Do you remove the commit from the branch first?
راهنماHint
خصوصیبودن شاخه اعتبار اعتبارنامه را تضمین نمیکند.
A private branch does not guarantee credential safety.
پاسخ پیشنهادیCorrect order
اول دسترسی را revoke/rotate کن و مسئول سرویس را امن مطلع کن. secret را دوباره در گزارش یا issue کپی نکن. بعد از ارزیابی دامنه و هماهنگی cloneها، تاریخچه را پاکسازی و از میزبان دربارهٔ cacheها بپرس. پاککردن شاخه رمز قبلاً افشاشده را زنده نمیکند.
First revoke/rotate access and securely notify the service owner. Do not repeat the secret in a report or issue. Then assess exposure, coordinate clones, rewrite history if appropriate, and ask the host about caches. Deleting the branch does not revive an exposed credential.
تمرینهای آخر عمداً یک مورد غیرقابلنجات هم دارند. مهارت حرفهای فقط برگرداندن داده نیست؛ تشخیص جایی است که Git هیچ مدرکی ندارد و نباید وعدهٔ بیپشتوانه بدهی.
The final exercises deliberately include an unrecoverable Git case. Professional recovery is not only about bringing data back; it is also about recognizing when Git has no evidence and refusing to make an unsupported promise.
git fsck --full گزارش missing blob داده. آیا تکرار fsck با flagهای بیشتر blob را بازسازی میکند؟
git fsck --full reports a missing blob. Will rerunning it with more flags reconstruct the blob?
راهنماHint
ابزار صحتسنجی با منبع نسخه پشتیبان یکی نیست.
A verifier is not a backup source.
پاسخ و دلیلAnswer
نه. کپی مخزن را حفظ کن، شناسه شیء را ثبت کن و clone/backup سالمی پیدا کن که همان blob را داشته باشد. fsck میگوید چه رابطه یا شیءی ناقص است؛ اگر هیچ منبع سالمی وجود ندارد، نمیتواند محتوای مفقود را بسازد.
No. Preserve a repository copy, record the OID, and find a healthy clone/backup containing that blob. Fsck identifies a missing object or link; without a healthy source, it cannot create the missing content.
فایل ideas.md در وضعیت به شکل ?? بود، پاک شده و هیچکس ناحیه آمادهسازی نکرده است. چه چیزی را میتوانی با اطمینان بگویی؟
ideas.md showed as ??, was deleted, and nobody staged it. What can you state confidently?
راهنماHint
Git فقط شیءی میتواند پیدا کند که زمانی گرفته باشد.
Git can only search for an object it once received.
بیا بازش کنیمRecovery boundary
در این فرض Git blobی از فایل نساخته، پس reflog/fsck از خود Git محتوایی ندارد که برگرداند. نسخه پشتیبان، سطل زباله، ویرایشگر تاریخچه، عکس فوری یا clone انسانی را بررسی کن. نمیتوانی بگویی هیچ نسخهای در دنیا نیست؛ فقط Git نسخهای ذخیره نکرده است.
Under these assumptions Git never made a blob, so reflog/fsck has no Git-stored content to restore. Check backups, recycle bin, editor history, snapshots, or a teammate’s clone. You cannot claim no copy exists anywhere—only that Git did not store one.
مشاور میگوید برای دیدن فایلهای زائد، git clean -fd اجرا کن و بعد از روی Trash برگردان. قدم امن جایگزین چیست؟
A consultant says to run git clean -fd to see junk files and restore them from Trash later. What is the safe alternative?
راهنماHint
پیشنمایش هم فرمان جدا دارد.
There is a separate preview mode.
راهحل و توضیحAnswer
هیچوقت برای «دیدن» فرمان حذف واقعی را اجرا نمیکنم. در پوشهٔ درست git clean -nd فقط فهرست احتمالی را نشان میدهد؛ مسیرها را بررسی و هر مورد مهم را بیرون مخزن کپی میکنم. Trash راه برگشت تضمینی نیست.
Never run the real deletion command merely to preview. In the correct repository, git clean -nd lists candidates only; inspect paths and copy anything valuable outside the repository. A trash bin is not a guaranteed undo.
commit روی شاخه فعلی نیست، اما git log --all هم آن را نشان نمیدهد. آیا میتوان نتیجه گرفت شیء پاک شده؟
The commit is not on the current branch, and git log --all does not show it. Can you conclude its object was deleted?
راهنماHint
--all همهٔ اشارهگرهاست، نه همهٔ شیءهای مخزن.
--all means all refs, not all repository objects.
چرا این جواب درست استAnswer
نه. log تاریخچهٔ قابلدسترسی از اشارهگرها را نمایش میدهد. reflog و در کپی مناسب fsck را بررسی کن؛ clone دیگر و شناسه شیء شناختهشده را هم بپرس. اگر پیدا نشد فقط میگویی در سرچشمههای فعلی با شواهد فعلی پیدا نشد، نه اینکه حتماً پاک شده یا حتماً هست.
No. Log displays history reachable from refs. Inspect reflogs and, on an appropriate copy, fsck; also ask about another clone and known OIDs. If absent, report only that current sources did not find it—not that it is certainly gone or present.
یک commit بد به main مشترک رسیده و همه آن را fetch کردهاند. owner میخواهد «log را تمیز کند». بین reset و revert چه مدرکی مهم است؟
A bad commit reached shared main and everyone fetched it. The owner wants to “clean up the log.” What evidence matters when choosing reset or revert?
راهنماHint
تاریخچهٔ عمومی را چه cloneهایی مصرف کردهاند و هدف اصلاح چیست؟
Which clones consumed the shared history, and what is the correction meant to achieve?
بررسی جوابDecision and cost
چون commit را همه گرفتهاند، reset تاریخچهٔ مشترک را بازنویسی و مصرفکنندهها را مجبور به هماهنگی میکند. revert معمولاً commit تازهای میسازد که اثر قبلی را معکوس میکند و اصل را در تاریخچه نگه میدارد. اگر secret بوده، اول rotate؛ انتخاب فنی آن را پس نمیگیرد.
Since everyone consumed the commit, reset rewrites shared history and forces consumers to coordinate. Revert usually adds a new commit that reverses the effect while preserving the original in history. If it contained a secret, rotate it first; neither choice recalls the credential.
دو ساعت گذشته؛ reflog محلی رد نشان نمیدهد، fsck هم شناسه شیء نامزد نداده و clone همکار در دسترس نیست. مدیر میخواهد قول بدهی تا ظهر همهچیز برمیگردد. چه میگویی و چه گزینهای هنوز باقی است؟
Two hours have passed; the local reflog has no entry, fsck found no candidate OID, and the teammate’s clone is unavailable. A manager wants you to promise everything will be back by noon. What do you say, and what options remain?
راهنماHint
نبودن شاهد در چند جا هنوز برابر اثبات حذف ابدی نیست؛ اما مجوز قول هم نیست.
Missing evidence in several places does not prove permanent deletion—but it does not justify a promise.
پاسخ پیشنهادیHonest report
میگویم در مخزن فعلی ref/object قابلتأیید پیدا نشده و بازیابی Git فعلاً اثباتپذیر نیست؛ زمان تحویل را تضمین نمیکنم. از teammate نسخه پشتیبان، ویرایشگر محلی تاریخچه، system عکس فوری، لپتاپ دیگر و فایل تولیدیهای ساخت را با رضایت و دسترسی امن میخواهیم. تا آن زمان اصل داده را دستنخورده نگه میداریم و جستوجو را ثبت میکنیم.
I would report that no verifiable ref/object was found in the current repository and Git recovery is not yet demonstrated; I would not promise a delivery time. Ask about teammate backups, editor local history, system snapshots, another laptop, and build artifacts through authorized access. Preserve the original data and document the search.
برای هر commitی که پیدا کردی: شناسه شیء را با show بشناس، اشارهگر نجات بساز، با show-ref آن را تأیید کن و بعد برای تغییر بعدی تصمیم بگیر. این چهار کار را با «همهچیز درست شد» یکی نگیر؛ فایلهای پوشه کاری، pushها و cloneهای دیگر جداگانه تأیید میخواهند.
For every commit you find: inspect the OID with show, create a rescue ref, verify it with show-ref, then decide the next change. Do not confuse these steps with “everything is fixed”; working-tree files, pushes, and other clones need separate verification.
از اینجا به بعد فرمان تازهای پشتش پنهان نیستFrom here, there is no new command to hide behind
اینجا آموزش ابزار تازه تمام میشود. سه پروژهٔ پایانی دیگر نردهٔ آموزشی ندارند: اول باید تاریخچه را خودت طراحی کنی، بعد با یک تیم واقعیتر جلو بروی و در آخر یک مخزن خراب را با شاهد و بدون حدس نجات بدهی.
Chapter 16 ends the teaching arc for new tools, not the practice of Git. The final projects ask you to design history, collaborate with a team, and recover when something slips using the model built since Chapter 01. A good question does not always begin with “Which command should I run?” Sometimes it starts with “What does Git still have right now?”
گزارش نجات منMy rescue report
- نشانه و زمان وقوع را ثبت کردم.
- I recorded the symptom and when it happened.
- وضعیت، اشارهگرها، شناسه شیءها و cloneهای بررسیشده را مشخص کردم.
- I listed status, refs, OIDs, and clones examined.
- ref/patch/copyهای حفاظتی و محدودیت هرکدام را میدانم.
- I know which refs/patches/copies protect what—and their limits.
- پس از تعمیر، همان بررسی اولیه را تکرار کردم.
- After repair, I repeated the original check.
- برای چیزی که Git ذخیره نکرده، قول بازیابی ندادهام.
- I made no recovery promise for content Git never stored.
نقشهٔ سریع اتاق نجاتRescue-room quick reference
| نشانهSymptom | اولین شاهدFirst evidence | مرزLimit |
|---|---|---|
| commit از log گم استCommit missing from log | reflog --all؛ بعد fsck در مخزن مناسب | ممکن است شیء منقضی یا حذف شده باشدThe object may have expired or been removed |
| شاخه اشتباه حرکت کردهWrong branch moved | status، graph، show | اگر مشترک است reset را خودسرانه تحمیل نکنDo not unilaterally reset a shared branch |
| push اجباری کار همکار را پنهان کردهForce-push hid a teammate’s work | clone دوم یا شناسه شیء قدیمیSecond clone or known old OID | reflog سرور را برای کاربر مفروض نگیرDo not assume user access to server reflog |
| secret وارد commit شدهSecret entered a commit | اعتبار و زمان انتشار اعتبارنامهCredential validity and exposure time | اول revoke/rotate؛ rewrite افشا را پس نمیگیردRevoke/rotate first; rewrite cannot recall exposure |
| ردیابینشده حذف شدهUntracked file deleted | نسخه پشتیبان، ویرایشگر، clone یا عکس فوریBackup, editor, clone, or snapshot | اگر Git هرگز ذخیره نکرده، Git چیزی برای برگرداندن نداردIf Git never stored it, Git has nothing to restore |
| شیء ناقص/خرابMissing/corrupt object | git fsck --full و clone سالم | fsck تشخیص میدهد؛ منبع سالم لازم استFsck diagnoses; a healthy source is required |
قاعدهٔ آخر دوره همان قاعدهٔ اول اتاق نجات است: قبل از پاککردن چیزی، بفهم Git هنوز چه چیزی دارد. بعد یک تغییر کوچک بده و همان چیزی را که اول اندازه گرفتی دوباره بررسی کن.
The final rule is the one we began with: do not delete first; find out what Git still has. Then make one change, verify it, and report honestly.
اگر خواستی جزئیات فرمان را دنبال کنیFor the exact command behavior
برای گزینهها و رفتار نسخهٔ نصبشده، راهنماهای رسمی reflog، fsck، reset، clean و push را ببین. دستور نجات را در مخزن دورریختنی تمرین کن؛ نام نسخهٔ تاریخچه، تنظیمات و مدت نگهداری reflog میتواند فرق کند.
For options and behavior in your installed Git version, consult the official manuals for reflog, fsck, reset, clean, and push. Practice recovery commands in a disposable repository; revision names, configuration, and reflog retention can differ.