TL;DR: git cherry-pick <sha> یک commit را از هر شاخهای روی شاخه فعلی شما کپی میکند — همان patch، SHA جدید، بدون جابهجایی تاریخچه. برای چند commit، فهرست SHA ها یا یک بازه (git cherry-pick A..B)؛ دقت کنید بازه A را کنار میگذارد، پس برای شمول آن بنویسید A^..B. اگر روی تعارض ایست، رفعش کنید، git add، بعد git cherry-pick --continue. cherry-pick برای جابهجا کردن یک fix مشخص است — وقتی همهچیز شاخه مقابل را میخواهید، merge یا rebase بهکار ببرید.
git cherry-pick دقیقاً چه میکند؟
cherry-pick یک commit موجود را برمیدارد و diff آن را بهعنوان یک commit جدید روی شاخه فعلی اعمال میکند. commit اصلی سر جایش میماند؛ نسخه کپی SHA تازه میگیرد. Git هیچ چیز را «جابهجا» نمیکند — کسانی که بعداً تعجب میکنند چرا commit هنوز روی شاخه قدیمی دیده میشود، دقیقاً همین را میبینند.
همین مدل کپی-بهجای-جابهجایی تعیین میکند cherry-pick کِی ابزار درست است:
- یک fix واحد از شاخه feature لازم دارید همین حالا روی
mainبنشیند، بدون merge بقیه. - یک hotfix که روی شاخه اشتباه commit شده باید روی شاخه درست فرود بیاید.
- یک patch باید روی شاخه release تکرار شود که هرگز از
mainmerge نمیکند.
مهارت مکملش این است که بدانید چطور یک commit اشتباه را پس بگیرید — سازوکارش در لغو آخرین commit در Git: تغییرات بماند پوشش داده شده.
چطور یک commit را از شاخه دیگری cherry-pick کنم؟
SHA را پیدا کنید، به شاخه مقصد بروید، بردارید:
# 1. Locate the commit on the source branch
git log feature/payment-fix --oneline -5
# 2. Switch to the branch that should receive it
git switch main
# 3. Copy it over
git cherry-pick 1a2b3c4 دو راحتی که دانستنش میارزد:
git cherry-pick <branch>commit نوکِ آن شاخه را برمیدارد — کاربردی، ولی آسان اتفاقی میشود با تصویر ذهنی کهنه از اینکه «نوک» الان کجاست.- بعد از برداشتن،
git log -1 --statتأیید میکند چه فرود آمده. یک ثانیه خواندن، یک revert کمتر.
commit ها روی feature/payment-fix میمانند؛ هر وقت خواستید آن شاخه را حذف کنید — نسخه برداشتهشده روی main SHA خودش را دارد و به نسخه قدیمی هیچ وابستگی ای ندارد.
چطور چند commit را cherry-pick کنم؟
سه شکل، به ترتیب کاربرد:
# 1. Explicit list — picked in the order you list them
git cherry-pick 1a2b3c4 5d6e7f8
# 2. Range — everything after A up to and including B
git cherry-pick A..B
# 3. Range including A
git cherry-pick A^..B تمایز A..B با A^..B همان سورپرایز کلاسیک است: A..B شامل A نیست. اگر بازه را از git log تجسم کنید و oldest..newest بردارید، بیسروصدا قدیمیترین commit را جا میاندازید. وقتی هدف «چند commit قدیمی، به ترتیب» است، بنویسید oldest^..newest و off-by-one محو میشود.
برای تاشدن چند برداشت در یک commit بهجای سهتا، بدون commit مرحلهبندی کنید با -n / --no-commit، بعد یک بار commit بزنید:
git cherry-pick -n 1a2b3c4 5d6e7f8
git commit -m "Backport: payment retry fixes" چرا git cherry-pick کار نمیکند؟
چهار علت واقعی، به ترتیب بسامد:
1. یک تعارض برداشت را متوقف کرده. Git patch را اعمال میکند، به خطی میرسد که روی هر دو شاخه تغییر کرده، و وسط دنباله میایستد:
# resolve the files, then:
git add <resolved-files>
git cherry-pick --continue # or --abort to return to the pre-pick state --continue اختیاری نیست و ضمنی هم نمیشود — تا اجرایش نکنید، داخل یک دنباله cherry-pick متوقفشده هستید و git status مدام همان را میگوید.
2. برداشت خالی است («The previous cherry-pick is now empty»). تغییر از قبل روی این شاخه وجود دارد، اغلب از یک cherry-pick قبلی یا یک merge فشرده. با git cherry-pick --skip ردش کنید، یا اگر واقعاً نشانگر را لازم دارید با --allow-empty یک commit خالی بسازید.
3. آن commit یک merge commit است. merge دو والد دارد، پس «این diff را اعمال کن» مبهم است — git حدس نمیزند، رد میکند. بگویید نسبت به کدام والد diff میگیرید:
git cherry-pick -m 1 <merge-sha> # parent 1 = the branch you merged *into* 4. working tree اشتباه یا HEAD جداشده. برداشت هر جا فرود میآید که HEAD اشاره میکند. قبل از برداشتن git branch --show-current؛ اگر چیزی چاپ نکرد، در detached HEAD هستید و commit موقع جابهجایی یتیم میشود.
cherry-pick در مقابل merge در مقابل rebase: کدام کجا؟
| دستور | چه چیزی روی مقصد مینشیند | تاریخچه | کِی استفاده کنید |
|---|---|---|---|
git cherry-pick <sha> | فقط commit های نامبرده | کپی، SHA های جدید | یک fix مشخص باید همین حالا جابهجا شود |
git merge <branch> | همهچیز روی شاخه | merge commit یا fast-forward | کل شاخه را میخواهید، واگرایی دیده شود |
git rebase <base> | همه commit های شاخه، بازپخششده | خطی، SHA های بازنویسیشده | شاخه را یک دنباله خطی تمیز میخواهید |
git revert <sha> | وارونه یک commit | یک commit باطلکننده اضافه میکند | یک commit فرودآمده باید روی تاریخچه مشترک باطل شود |
قاعده یکخطی: cherry-pick یک انتخاب را جابهجا میکند؛ merge و rebase همهچیز را. سراغ cherry-pick رفتن برای «sync» شدن با یک شاخه علامت این است که در واقع merge میخواهید — و اگر بحث main فورک شما در مقابل upstream باشد، روال کامل در همگامسازی fork با upstream در Git: 3 روش امن است.
یک عادت که باید رها شود: cherry-pick کردن بلندمدتِ همان commit به چند شاخه. هر fix آینده روی شاخه مبدا یک برداشت دیگر میخواهد، و بالاخره شاخهها وا میروند. Backport به شاخههای release الگوی نرمالی است؛ یک جهان موازی دائمی نه.
گردشکار cherry-pick، فشرده
git log <source-branch> --oneline -5 # find the SHA(s)
git switch <target-branch> # land in the right place
git cherry-pick A^..B # range, list, or single SHA
# on conflict: resolve → git add → git cherry-pick --continue
git log -1 --stat # confirm what landed پیدا کن، برو، بردار، راستیآزمایی کن. این دستور آوازه خطرناکبودنی دارد که لایقش نیست — یا diff اعمال میشود یا میایستد و میگوید چرا. تنها اشتباه واقعاً مخرب، برداشتن روی شاخه اشتباه است، و git log -1 قبل از push باعث میشود آن بهسختی از چشم بیفتد.
FAQ
git cherry-pick چه میکند؟
تفاوت یک commit را بهعنوان یک commit جدید روی شاخه فعلی شما کپی میکند — همان تغییر، SHA جدید.
چطور چند commit را cherry-pick کنم؟
git cherry-pick A^..B یک بازه را به ترتیب تکرار میکند. تعارض اجرا را متوقف میکند؛ رفع کنید، بعد cherry-pick --continue.
آیا cherry-pick بهتر از merge است؟
برای بردن یک fix به شاخه release، بله. cherry-pick های تکراریِ کل شاخه بدهی merge است — merge یا rebase بهکار ببرید.
— mrsaynothing
— mrsaynothing
یادداشتهای میدانی درباره AI، لینوکس و self-hosting.
این نوشته را در dev.to بحث کنید dev.to ↗
آموزش بعدی با ایمیل
هر نوشته یک ایمیل. درستش کن، برو سراغ بعدی.
این چیست؟cron در مقابل timer های systemd: کدام را بهکار ببرید؟
این نوشتهها را میپسندید؟ این همان کاری است که برای زندگی از آن درمیآورم. استخدامم کنید