ترفندهای پیشرفته Git: بازگردانی کدهای از دست رفته با Reflog و Cherry-pick

آموزش گام‌به‌گام نجات کدهای از دست رفته، بازیابی کامیت‌های پاک شده با git reflog، انتقال دقیق تغییرات با cherry-pick و ترفندهای حرفه‌ای توسعه نرم‌افزار.

🎧 خلاصه صوتی مقاله (پادکست ۲ دقیقه‌ای):

فرصت مطالعه ندارید؟ چکیده این مطلب را همین‌جا گوش دهید:

یکی از ترسناک‌ترین لحظات در زندگی هر برنامه‌نویسی زمانی است که متوجه می‌شود با اجرای یک دستور اشتباه، ساعت‌ها کار مفید و کدهایی که نوشته بود را گم کرده است. احتمالاً شما هم تجربه‌ی اجرای دستوراتی مثل git reset --hard یا حذف تصادفی یک شاخه را داشته‌اید که ضربان قلب را بالا می‌برد. خوشبختانه سیستم کنترل نسخه گیت (Git) به گونه‌ای طراحی شده است که به ندرت چیزی را برای همیشه نابود می‌کند. حتی گاهی اوقات که روی پروژه‌های شخصی یا کارهای جانبی مثل توسعه افزونه‌ها یا بازی‌های جذاب مرورگرری کار می‌کنید، تسلط بر ابزارهای پیشرفته مدیریت کد می‌تواند نجات‌بخش باشد. در این مقاله قصد داریم به دور از روش‌های تخریبی و ترسناک، دقیقاً بررسی کنیم چطور می‌توان با چند دستور ساده، کدهای گم‌شده را به مخزن بازگرداند و کنترل کامل تاریخچه پروژه را به دست گرفت.

موضوعجزئیات فنی
ابزار اصلی نجاتدستور قدرتمند git reflog
انتقال کددستور git cherry-pick
سطح مهارتمتوسط تا پیشرفته
وضعیت دسترسی ایرانکاملاً آزاد (بدون محدودیت)

نجات از فاجعه با دستور طلایی Git Reflog

تصور کنید با عجله دستور git reset --hard HEAD~3 را اجرا کرده‌اید تا سه کامیت آخر را پاک کنید، اما ناگهان متوجه می‌شوید بخش مهمی از کدهای کاربردی پروژه که هنوز روی سرور دوردست (Remote) هم قرار نداشتند، از بین رفته‌اند. دستپاچه نشوید! فرمان git reflog مانند جعبه سیاه هواپیما عمل می‌کند. این دستور تمام تغییراتی که شاخص HEAD در مخزن محلی شما به خود دیده است (حتی کامیت‌های جدا شده یا پاک‌شده) را ثبت می‌کند.

برای شروع بازیابی، کافی است تاریخچه جابجایی‌های HEAD را در ترمینال خود بررسی کنید:

git reflog

پس از اجرای دستور بالا، خروجی مشابه زیر را مشاهده خواهید کرد که هر خط آن یک نقطه عطف یا جابجایی در مخزن شما را نشان می‌دهد:

ab12cd3 HEAD@{0}: reset: moving to HEAD~3
ef56gh7 HEAD@{1}: commit: اضافه کردن بخش احراز هویت کاربران
90ijkl1 HEAD@{2}: commit: رفع باگ صفحه اصلی
34mnop5 HEAD@{0}: checkout: moving from feature-auth to main

در این خروجی، مقدار ef56gh7 همان کامیت گمشده‌ی ما است که پیش از اجرای ریستِ مخرب روی آن بودیم. حالا برای اینکه پروژه را دقیقا به همان نقطه بازگردانیم، کافی است از دستور زیر استفاده کنیم:

git reset --soft ef56gh7
# یا اگر می‌خواهید کاملاً به آن وضعیت برگردید:
git checkout ef56gh7

با این کار، تمام فایل‌ها و کدهای از دست رفته به شاخه‌ی کاری شما بازمی‌گردند و هیچ زحمتی هدر نرفته است.

انتقال دقیق کدها با دستور Git Cherry-Pick

گاهی اوقات نیاز ندارید که کل یک شاخه (Branch) را با شاخه‌ی اصلی ادغام (Merge) کنید، بلکه فقط می‌خواهید یک کامیت خاص و بی‌نظیر را که روی یک شاخه‌ی دیگر نوشته شده است، به شاخه‌ی فعلی خود بیاورید. فرض کنید روی شاخه‌ی main کار می‌کنید و دوستتان در شاخه‌ی dev یک کامیت فوق‌العاده برای بهینه‌سازی سرعت پایگاه داده زده است. انتقال کل شاخه‌ی dev منطقی نیست، اما آن تک کامیت را نیاز دارید.

برای انجام این کار، دستور cherry-pick معجزه می‌کند. ابتدا به شاخه‌ای که می‌خواهید کدها به آن منتقل شوند بروید و سپس شناسه کامیت مورد نظر را وارد کنید:

# مطمئن شوید در شاخه‌ی مقصد هستید
git checkout main

# انتقال کامیت مشخص با شناسه فرضی 789abcd
git cherry-pick 789abcd

خروجی نمونه اجرای موفق این دستور به شکل زیر خواهد بود:

[main 987fedc] بهینه‌سازی سرعت پایگاه داده
 Date: Sat Oct 18 14:32:10 2026 +0330
 2 files changed, 45 insertions(+), 12 deletions(-)
 create mode 100644 db/optimize.sql

نکته مهم و خطای رایج در زمان استفاده از این دستور، وقوع تداخل یا Conflict است. اگر کدهای کامیت مقصد با کدهای شاخه‌ی فعلی شما تداخل داشته باشند، گیت متوقف می‌شود و از شما می‌خواهد تداخل را حل کنید. پس از ویرایش فایل‌های مشکل‌دار، کافی است دستور git add . را اجرا کرده و سپس با دستور git cherry-pick --continue فرآیند را به پایان ببرید.

ویرایش حرفه‌ای کامیت آخر بدون ساخت کامیت جدید

یکی از عادت‌های خوب برنامه‌نویسی، داشتن تاریخچه‌ی تمیز و خوانا است. همه‌ی ما حداقل یک بار این تجربه را داشته‌ایم که کامیت آخر را زده‌ایم (مثلاً با پیام «اصلاح جزئی استایل») و بلافاصله متوجه شده‌ایم که یادمان رفته یک فایل CSS یا پایتون را به کامیت اضافه کنیم، یا اینکه املای پیام کامیت اشتباه بوده است. راه حل آماتور این است که یک کامیت جدید با نام «رفع فراموشی» بسازیم که تاریخچه را شلوغ می‌کند. راه حل حرفه‌ای استفاده از پرچم --amend است.

اگر فایل جا مانده‌ای دارید که می‌خواهید به کامیت آخر بچسبانید، ابتدا آن را ایندکس کنید و سپس دستور زیر را بزنید:

# اضافه کردن فایل جامانده
git add forgotten-file.js

# ادغام این فایل و تغییر پیام کامیت آخر در یک مرحله
git commit --amend -m "تکمیل بخش جاوااسکریپت و اصلاح پیام کامیت"

اگر پروژه شما شامل اسکریپت‌های پیچیده پایتون یا توسعه ابزارهای گوناگون است، شاید گاهی دوست داشته باشید در کنار کارهای فنی، نگاهی به تنوع محتوای دیجیتال دیگر هم بیندازید؛ مثلاً اگر به ابزارهای جانبی وب علاقه دارید، مطالعه‌ی مقالاتی پیرامون معرفی افزونه ColorZilla؛ قطره‌چکان و پالت‌ساز حرفه‌ای رنگ در مرورگر می‌تواند ایده‌های جالب طراحی را برای رابط کاربری برنامه‌هایتان زنده کند.

خروجی نمونه پس از اجرای دستور اصلاح کامیت:

[main 45678ab] تکمیل بخش جاوااسکریپت و اصلاح پیام کامیت
 Date: Sat Oct 18 14:45:22 2026 +0330
 2 files changed, 12 insertions(+), 3 deletions(-)

پاکسازی ایمن مخزن از شاخه‌های مرده و قدیمی

بعد از گذشت چند هفته کار روی یک پروژه بزرگ تیمی، تعداد شاخه‌های محلی (Local) و دوربری (Remote) به شدت زیاد می‌شود و لیست کردن آن‌ها با git branch -a گیج‌کننده خواهد بود. بسیاری از این شاخه‌ها کارشان تمام شده و روی سرور اصلی ادغام شده‌اند اما هنوز در سیستم ما باقی مانده‌اند.

برای پاکسازی شاخه‌های محلی که دیگر به آن‌ها نیازی ندارید، دستور زیر به کار می‌آید:

# حذف ایمن شاخه‌ای که کارش تمام شده است
git branch -d feature/old-login-page

# اگر گیت ارور داد که شاخه هنوز کامل ادغام نشده اما مطمئن هستید که می‌خواهید آن را پاک کنید:
git branch -D feature/old-login-page

همچنین برای همگام‌سازی و پاک کردن شاخه‌های ریموتِ منقضی شده از لیست محلی خود (Pruning)، از ترکیب زیر استفاده کنید:

git fetch --prune

این دستور تمام رفرنس‌های شاخه‌هایی که روی سرور اصلی پاک شده‌اند را از سیستم شما نیز جارو می‌کند تا محیط کاری تمیز و سریعی داشته باشید.

پرسش‌های متداول

آیا با دستور git reflog می‌توانم کامیت‌هایی که ماه پیش حذف کرده‌ام را هم برگردانم؟

بله، تا زمانی که گیت به صورت خودکار عملیات پاکسازی مخزن (Garbage Collection یا به اختصار gc) را روی کامیت‌های یتیم (Orphaned commits) انجام نداده باشد، رکوردهای reflog باقی می‌مانند. به طور پیش‌فرض، گیت این اطلاعات را حداقل تا ۳۰ روز نگه می‌دارد.

تفاوت اصلی دستور git reset و git checkout چیست؟

دستور git reset شاخص HEAD و شاخه‌ی فعلی را به عقب یا جلو می‌کشد، در حالی که git checkout صرفاً شما را به یک کامیت یا شاخه‌ی خاص منتقل می‌کند تا در حالت detached HEAD یا شاخه‌ی جدید کار کنید بدون اینکه تاریخچه شاخه‌ی اصلی تغییر کند.

اگر هنگام استفاده از cherry-pick پشیمان شوم چطور عملیات را لغو کنم؟

اگر فرآیند انتقال به دلیل تداخل یا هر دلیل دیگری متوقف شده و نیمه‌کاره است، می‌توانید با اجرای دستور git cherry-pick --abort به دقیقاً همان نقطه‌ی پیش از شروع دستور بازگردید.

جمع‌بندی

مدیریت صحیح کدها با گیت تفاوت میان یک توسعه‌دهنده‌ی آرام و مسلط با فردی که همیشه نگران از دست رفتن کدهایش است را رقم می‌زند. دستوراتی مثل git reflog و git cherry-pick ابزارهای پیشرفته‌ای هستند که به شما اجازه می‌دهند بدون ترس، روی کدهای پیچیده کار کنید و هر زمان که خطایی رخ داد، به سادگی کنترل اوضاع را در دست بگیرید. با تمرین این دستورات در یک مخزن تستی، مهارت خود را ارتقا دهید و دیگر نگران کامیت‌های اشتباه نباشید.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *