کدنامهمرجع‌های مهندسی نرم‌افزار، به فارسی
گیت · فصل ۱۱Git · Chapter 11

stash، cherry-pick، tag

Stash, cherry-pick, and tags

گاهی وسط یک قابلیت هستی و هنوز وقت commit نیست، اما یک اصلاح فوری فوری می‌رسد. همین وقفه سه ابزار کوچک را معنی‌دار می‌کند: stash برای کنارگذاشتن موقت کار، cherry-pick برای آوردن یک تغییر مشخص و tag برای نام‌گذاری نسخه.

You are midway through a feature when an urgent release hotfix arrives. You do not need to commit unfinished work or copy the folder: we will set it aside, bring one known fix to the right branch, and name the tested release.

۱۵بخشsections
۸۰دقیقهminزمان مطالعهreading time
۱۸تمرین با پاسخsolved exercises
۶نمودارdiagrams

قابلیت نیمه‌کاره است؛ اصلاح فوری منتظر نمی‌ماندThe feature is unfinished; the hotfix cannot wait

روی feature/search در دو فایل کار کرده‌ای؛ یکی را هم ناحیه‌ آماده‌سازی کرده‌ای. هم‌تیمی می‌گوید باگ پرداخت در نسخهٔ انتشار باید همین حالا رفع شود. اگر شاخه عوض کنی چه می‌شود؟ اگر commit عجولانه بسازی، آیا واقعاً آمادهٔ تاریخچهٔ محصول است؟

You have edited two files on feature/search, staging one. A teammate reports that a payment bug in the release must be fixed now. What happens if you switch branches? If you make a hurried commit, is it ready for product history?

فصل‌های ۳ و ۵ سه ناحیه و شاخه را جدا کردند؛ فصل ۶ نشان داد merge چه‌طور دو خط تاریخچه را نگه می‌دارد؛ فصل ۱۰ هم ردّ اشاره‌گرها را دنبال کرد. اینجا سه نیاز جدا داریم: کار نیمه‌تمام را موقت نگه داریم، تغییر انتخابی را روی شاخهٔ دیگر بسازیم و نسخهٔ آزموده‌شده را نام‌گذاری کنیم.

Chapters 03 and 05 separated the three areas and branches; Chapter 06 showed how merge preserves history lines; Chapter 10 followed ref movements. Now we have three distinct needs: preserve unfinished work temporarily, apply one selected change on another branch, and name a tested release.

Dirty work is stashed, the worktree is cleared, and the saved edits are later reapplied feature/searchstaged + unstaged stash@{0}local saved state working treeedits reapplied stash pushapply / pop temporary context · inspect before dropping
نمودار ۱ — stash تغییرهای فعلی را ثبت و پوشه را تمیز می‌کند؛ apply/pop دوباره آن‌ها را اعمال می‌کند. تا نتیجه را ندیده‌ای رد را حذف نکن.
Diagram 1 — Stash records current edits and cleans the worktree; apply/pop reapplies them. Do not drop the entry before inspecting the result.

اول کار نیمه‌تمام را کنار بگذارFirst, set unfinished work aside

در مخزن تمرینی جدا، یک فایل ردیابی‌شده را تغییر بده و فایلی را ناحیه‌ آماده‌سازی کن. قبل از اجرا حدس بزن: بعد از stash پوشه و ناحیه‌ آماده‌سازی چه وضعی دارند؟

In a separate practice repository, edit a tracked file and stage another. Predict before running: what happens to the worktree and index?

bash · disposable repository
git status --short
git stash push -m "pause search for payment hotfix"
git status --short
git stash list

فرمان اول تغییرها را نشان می‌دهد. پس از stash push معمولاً پوشه و ناحیه‌ آماده‌سازی به وضعیت HEAD برمی‌گردند؛ stash list پیام رد تازه را نشان می‌دهد. این ثبت محلی است، نه commit روی شاخه و نه چیزی که همکار خودکار دریافت کند.

The first command shows the edits. After stash push, the worktree and index normally return to HEAD; stash list shows the new entry. This is local storage, not a branch commit or something a teammate automatically receives.

Git چیزی را که ندیده ثبت نمی‌کندGit cannot record what it cannot see

قبل از stash، status را بخوان. stash عادی تغییر فایل‌های ردیابی‌شده را می‌گیرد؛ فایل ردیابی‌نشده و ignored قواعد جدا دارند. ویرایشی که فقط در ادیتور است و هنوز ذخیره نشده، برای Git وجود ندارد.

Read status before stashing. A normal stash records tracked-file changes; untracked and ignored files have separate rules. An edit that exists only in an unsaved editor buffer does not exist for Git.

قبل از برگرداندن، داخل stash را ببینInspect before restoring

پس از چند وقفه، stash@{0} لزوماً کار همین قابلیت نیست. فهرست و patch را بخوان؛ اسم رد محتوایش را ثابت نمی‌کند.

After several interruptions, stash@{0} may not belong to this feature. Read the list and patch; the entry name does not prove its contents.

inspect without restoring
git stash list
git stash show --stat "stash@{0}"
git stash show -p "stash@{0}"

list ترتیب و پیام‌ها را نشان می‌دهد؛ show --stat فایل‌های درگیر و -p خود diff را می‌دهد. خروجی را با کاری که یادت هست بسنج. دیدن patch ثابت نمی‌کند روی شاخهٔ تازه بی‌تعارض اعمال می‌شود.

list shows order and messages; show --stat summarizes paths, while -p displays the diff. Compare it with what you remember. Seeing the patch does not prove it will apply cleanly on a new branch.

The stash ref points to the newest entry and its reflog keeps older entries addressable refs/stashlatest entry ref stash@{0}newest entry stash@{1}, stash@{2}…older reflog entries current refreflog history
نمودار ۲ — refs/stash به تازه‌ترین رد می‌رسد و reflog آن ردهای قدیمی‌تر را نام‌پذیر می‌کند. شماره‌ها با افزودن یا حذف تغییر می‌کنند و شناسهٔ پایدار نیستند.
Diagram 2 — refs/stash reaches the newest entry; its reflog names older ones. Indices change as entries are added or removed and are not permanent IDs.

ردیابی‌نشده را جداگانه انتخاب کنInclude untracked files explicitly

فایل تازه‌ای مثل draft-plan.md ساخته‌ای، اما add نکرده‌ای. stash معمولی آن را نمی‌گیرد؛ -u فایل‌های ردیابی‌نشده را هم می‌گیرد، اما ignoredها نه. -a ignored را هم شامل می‌کند و می‌تواند فایل‌های تولیدی یا محلی را از پوشه بردارد؛ بی‌دلیل سراغش نرو.

You created draft-plan.md but did not add it. A normal stash excludes it; -u includes untracked files but not ignored ones. -a also includes ignored files and may remove generated or local data from the worktree; do not use it casually.

include untracked and inspect it
git status --short
git stash push -u -m "include new draft"
git stash show -p -u "stash@{0}"
نوع تغییرChangestash pushstash push -ustash push -a
tracked✓✓✓
untracked—✓✓
ignored——✓

پس از اجرای فرمان، status و show -p -u را بخوان. یک فایل نبودنش دلیل نیست که حتماً در stash است؛ patch باید خود محتوای مورد انتظار را نشان دهد.

After running the command, inspect status and show -p -u. A missing file is not proof that it is in the stash; the patch must show the expected content.

apply نگه می‌دارد؛ pop بعد از موفقیت حذف می‌کندapply keeps it; successful pop removes it

هر دو تغییر را برمی‌گردانند؛ تفاوت در عمر رد است. apply آن را نگه می‌دارد تا بررسی کنی. pop فقط بعد از اعمال موفق حذفش می‌کند. اگر تعارض پیش بیاید، رد معمولاً می‌ماند.

Both restore the changes; the difference is the entry's lifetime. Apply keeps it for inspection. Pop removes it only after successful application. If a conflict occurs, the entry normally remains.

فرمانCommandاعمالApplyحذف ردRemove entryمناسب برایUse when
stash apply✓خیرNoمی‌خواهی نتیجه را ببینی یا بعداً دوباره لازم داری.You want to inspect it or may need it again.
stash pop✓پس از موفقیتAfter successرد درست است و دیگر نباید در فهرست بماند.It is the right entry and should leave the list.
stash dropخیرNo✓پس از بررسی و اطمینان از بی‌نیازی.After verifying it is no longer needed.

در تعارض، وضعیت را بخوان، فایل‌ها و ناحیه‌ آماده‌سازی را حل کن، ناحیه‌ آماده‌سازی و تست بگیر؛ بعد از اثبات نتیجه رد را drop کن. اگر می‌خواهی فایل‌هایی که قبل از stash ناحیه‌ آماده‌سازی بودند دوباره آماده‌شده شوند، apply --index را امتحان کن؛ بازسازی ناحیه‌ آماده‌سازی هم ممکن است با تعارض روبه‌رو شود. stash مدیریت وقفه است، نه پشتیبان بلندمدت. برای کاری که باید بماند commit یا شاخه بساز.

On conflict, inspect status, resolve files and index, stage and test; drop only after proving the result. If you want paths that were staged before stashing to become staged again, try apply --index; restoring the index can also conflict. A stash manages an interruption, not long-term backup. Create a commit or branch for work that must persist.

Apply retains the stash entry while pop removes it after successful restoration stash entrykept until verified apply / poprestore attempt working treeinspect + test apply keeps · successful pop removes
نمودار ۳ — تفاوت در ماندن رد است؛ تعارض دلیل حذف دستی فوری نیست.
Diagram 3 — The difference is whether the entry remains; a conflict is no reason to drop it immediately.

stash کلیپ‌بورد جادویی نیستA stash is not a magical clipboard

فصل ۲ نشان داد Git محتوا را در شیءهایی مثل blob، tree و commit نگه می‌دارد. stash هم با commitهای مخصوص وضعیت پوشه و ناحیه‌ آماده‌سازی را ثبت می‌کند و اشاره‌گر محلی refs/stash به تازه‌ترین رد می‌رسد؛ reflog همان اشاره‌گر ردهای قبلی را قابل‌نام‌بردن می‌کند.

Chapter 02 showed Git storing content in objects such as blobs, trees, and commits. A stash is represented by special commits recording worktree and index states; the local ref refs/stash points to the newest entry, and its reflog makes earlier entries addressable.

این ساختار توضیح می‌دهد چرا می‌توانی stash را diff کنی؛ اما نکتهٔ روزمره این است: محلی است، شاخه نیست، به مخزن راه دور نمی‌رود و بعد از حذف/پاک‌سازی ممکن است بازیابی نشود.

This structure explains why a stash can be diffed. The practical point is that it is local, not a branch, not sent to a remote, and may be unrecoverable after deletion and pruning.

اصلاح فوری آماده است؛ فقط همان تغییر را به نسخه‌ انتشار بیاورThe hotfix is ready; bring only that change to release

هم‌تیمی روی hotfix/payment-timeout تغییری ساخته و آزموده؛ شاخهٔ جست‌وجو هنوز نیمه‌کاره است. merge رابطهٔ دو شاخه را وصل می‌کند، اما امروز فقط یک commit مشخص باید روی release/2.4 هم باشد.

A teammate has made and tested a change on hotfix/payment-timeout, while search is unfinished. Merge connects branch histories, but today one known commit must also appear on release/2.4.

اگر commit هنوز در clone نیست، fetch کن؛ رهگیریِ مخزن راه دور شاخه فقط آخرین وضعیت fetchشده است. اینجا شناسه‌ شیء محلی داریم. قبل از اجرا، مقصد و patch را ثابت کن:

If the commit is not in your clone, fetch; a remote-tracking branch is only the last fetched state. Here the OID is local. Prove the target and patch first:

inspect · choose target · apply
git status --short --branch
git show --stat --oneline HOTFIX_OID
git switch release/2.4
git status --short --branch
git cherry-pick HOTFIX_OID
git show --stat --oneline HEAD

HOTFIX_OID را با شناسهٔ واقعی عوض کن. show می‌گوید چه patchی را انتخاب کرده‌ای؛ cherry-pick آن را روی والد جاری بازمی‌سازد. معمولاً commit تازه شناسه‌ شیء تازه دارد چون والد یا فراداده فرق می‌کند؛ commit اصلی سر شاخهٔ اصلاح فوری می‌ماند.

Replace HOTFIX_OID with the real ID. show identifies the selected patch; cherry-pick reconstructs it on the current parent. The new commit normally has a new OID because its parent or metadata differs; the source remains on hotfix.

Cherry-pick applies a source commit change and creates a new commit on the target branchhotfix branchrelease branch H · parentshared base F · hotfixselected patch H · parenttarget base F′ · new commitsame change, new parent apply F's change
نمودار ۴ — F فرزند H روی اصلاح فوری است. cherry-pick تغییرش را روی نسخه‌ انتشار اعمال و F′ را با والد همان مقصد می‌سازد؛ دو commit یکی نیستند.
Diagram 4 — F descends from H on hotfix. Cherry-pick applies its change on release and creates F′ with the target parent; these are not the same commit.

merge رابطه را می‌آورد؛ cherry-pick تغییر راmerge brings the relationship; cherry-pick brings the change

اگر کل خط کار و رابطهٔ والدها آن باید وارد نسخه‌ انتشار شود، merge را بررسی کن. اگر فقط patch مشخصی لازم است و شاخهٔ مبدا نباید یک‌جا ادغام شود، cherry-pick محدودتر است. انتخاب را بر اساس تاریخی بکن که تیم بعداً باید بخواند.

If the whole line of work and its ancestry should enter release, consider merge. If only one patch is needed and the source branch should not be integrated wholesale, cherry-pick is narrower. Choose based on the history your team needs to read.

نیازNeedmergecherry-pick
چه چیزی می‌آید؟What comes over?رابطهٔ شاخه و commitهای قابل‌دسترسیBranch relationship and reachable commitsاثر commit انتخابیEffect of selected commit
والد commitCommit parentتاریخچه حفظ؛ fast-forward یا merge commitHistory preserved; fast-forward or merge commitcommit تازه فرزند مقصدNew commit descends from target
پرسشQuestionآیا این خط کار باید ادغام شود؟Should this line of work be integrated?کدام patch دقیقاً لازم است؟Which exact patch is needed?
Merge preserves branch ancestry while cherry-pick applies only a selected changetwo integration choices · one source branch merge: branch + ancestryconnect histories cherry-pick: selected patchcreate a new commit target history reflects intent
نمودار ۵ — merge پیوند شاخه‌ها را نگه می‌دارد؛ cherry-pick patch را در مقصد بازمی‌سازد. هیچ‌کدام همیشه بهتر نیست؛ نیاز تعیین‌کننده است.
Diagram 5 — Merge retains branch ancestry; cherry-pick reconstructs a patch on the target. Neither is always better; the need decides.

تعارض آمد؟ اول وضعیت را بخوانConflict? Read the state first

اگر cherry-pick با تعارض متوقف شد، کورکورانه تکرارش نکن. وضعیت فایل‌های حل‌نشده را نشان می‌دهد؛ بعد انتخاب کن تغییر را نگه داری یا عملیات را لغو کنی.

If cherry-pick stops with a conflict, do not repeat it blindly. Status identifies unresolved files; then decide whether to keep the change or cancel.

resolve and continue OR abort
git status
# resolve intentionally
git add path/to/resolved-file
git cherry-pick --continue

# alternatively, cancel the operation
git cherry-pick --abort

بعد از حل و ناحیه‌ آماده‌سازی، --continue commit را می‌سازد؛ --abort به قبل از عملیات جاری برمی‌گردد. با درخت تمیز شروع کن تا تغییرهای نامرتبط درگیر نشوند. اگر patch خالی یا تکراری شد، log و diff را بسنج؛ شاید تغییر پیش‌تر آمده یا مقصد اشتباه است. commit خالی را فقط برای خاموش‌کردن خطا نساز.

After resolving and staging, --continue creates the commit; --abort returns to the pre-operation state. Start with a clean worktree so unrelated edits are not involved. If the patch is empty or redundant, inspect log and diff; it may already exist or the target may be wrong. Do not create an empty commit just to silence an error.

روی شاخهٔ اشتباه commit کردی؟ فوری reset نزنCommitted on the wrong branch? Do not reset reflexively

اول بپرس push شده؟ هم‌تیمی بر آن بنا کرده؟ وضعیت فایل‌ها چیست؟ فصل ۹ بین کار محلی و تاریخچهٔ مشترک فرق گذاشت؛ اشاره‌گر امن بساز و مرز را رعایت کن.

First ask whether it was pushed, whether a teammate built on it, and what the worktree contains. Chapter 09 distinguished local work from shared history; create a safety ref and respect that boundary.

نسخهٔ آزموده‌شده را با tag نام‌گذاری کنName the tested release with a tag

شاخه خط کاری‌ای است که حرکت می‌کند؛ tag نامی است که روی نقطه‌ای از تاریخچه می‌گذاری تا نسخه یا رویدادی را مشخص کنی. فصل ۲ ساختارش را معرفی کرد: tag سبک اشاره‌گر مستقیم به شیء است؛ tag نشانه‌دار شیء جدا با پیام، زمان و tagger می‌سازد. برای نسخه‌ انتشار معمولاً tag نشانه‌دار مناسب‌تر است.

A branch is a moving line of work; a tag names a point in history as a release or event. Chapter 02 introduced the structure: a lightweight tag is a ref directly to an object; an annotated tag creates a separate object with message, date, and tagger. Annotated tags are usually more useful for releases.

نوعKindساختارStructureکاربردUse
سبکLightweightاشاره‌گر مستقیم به شیء هدفRef directly to target objectموقت یا محلیTemporary or local marker
نشانه‌دارAnnotatedtag شیء با پیام/زمان/tagger؛ امضا اختیاریTag object with message/date/tagger; optional signatureنسخهٔ انتشارRelease version
Lightweight tag points directly to commit and annotated tag points through a tag object v2.4.1lightweight ref tag objectmessage + tagger commitrelease snapshot annotated ref → tag object → commit lightweight ref points directly to commit
نمودار ۶ — tag سبک مستقیم به commit می‌رسد؛ tag نشانه‌دار ابتدا به tag شیء و بعد به commit. ظاهر نام‌ها مشابه است، فراداده نه.
Diagram 6 — A lightweight tag points directly to a commit; an annotated tag points first to a tag object. The names may look alike, but their metadata differs.

قبل از انتشار، مقصد tag را ثابت کنVerify the tag target before publishing

tag روی commit اشتباه نسخهٔ درست نمی‌سازد. شاخه، تست و commit جاری را بررسی کن؛ سپس tag بساز و با show مقصدش را بخوان.

A tag on the wrong commit does not make a correct release. Verify branch, tests, and current commit; create the tag, then inspect its target with show.

create and publish one annotated release tag
git status --short --branch
git log -1 --oneline
git tag -a v2.4.1 -m "Release 2.4.1: payment timeout fix"
git show --no-patch --decorate v2.4.1
git push origin release/2.4
git push origin v2.4.1
git ls-remote --tags origin

show پیام و مقصد commit را نشان می‌دهد. اگر نام از قبل هست، توقف کن و مقصد محلی و مخزن راه دور را بررسی کن؛ tag منتشرشده ممکن است مبنای ساخت دیگران باشد. push شاخه تضمین نمی‌کند tag هم رفته؛ tag مشخص را جدا push کن. push --tags همهٔ tagهای محلی، حتی آزمایشی/خصوصی را می‌فرستد؛ فرمان پیش‌فرض انتشارش نکن.

show displays message and target. If the name exists, stop and inspect local and remote targets; a published tag may anchor other builds. Pushing a branch does not guarantee its tag was sent; push the exact tag separately. push --tags sends all local tags, including experimental or private ones; do not make it the default.

Git اجازهٔ جابه‌جایی tag محلی یا حذف مخزن راه دور را می‌دهد، اما نسخه‌گذاری قرارداد تیمی است. برای tag منتشرشدهٔ اشتباه با مصرف‌کنندگان هماهنگ کن؛ نام تازه معمولاً از عوض‌کردن معنای نام عمومی کم‌خطرتر است. امضای کوتاه: tag -s با کلید تنظیم‌شده امضا می‌کند و tag -v آن را می‌سنجد؛ اعتماد به هویت امضاکننده هم لازم است.

Git permits moving a local tag or deleting one remotely, but release naming is a team contract. Coordinate if a published tag is wrong; a new name is often safer than changing a public name's meaning. Briefly: tag -s signs with a configured key, and tag -v verifies it; trust in the signer's identity still matters.

پروژهٔ کوچک: وقفه، اصلاح فوری، انتشارMini-project: interruption, hotfix, release

مخزن دورریختنی · حدود ۳۰ دقیقهDisposable repository · about 30 minutes

سه کار جدا، یک جریان پیوسته

Three distinct jobs, one continuous story

این پروژه یک وقفهٔ واقعی را شبیه‌سازی می‌کند: وسط یک قابلیت هستی، یک اصلاح فوری می‌رسد و بعد باید نسخه را منتشر کنی. کار نیمه‌تمام نباید قاطی اصلاح فوری شود و نباید هم گم شود. هر مرحله را با وضعیت و log ثابت می‌کنیم تا معلوم باشد دقیقاً چه چیزی کجا رفته است.

In a fresh repository, leave a feature unfinished, bring the hotfix to release, and tag it after testing. Prove the feature can continue and the tag points to the inspected version.

ساخت سناریو

Set up the scenario

فقط در پوشهٔ تازهٔ interrupt-release-lab اجرا کن؛ مخزن واقعی را جایگزین نکن.

Run only in a new interrupt-release-lab folder; do not substitute a real repository.

bash · isolated history
mkdir interrupt-release-lab && cd interrupt-release-lab
git init -q
git config user.name "Git Learner"
git config user.email learner@example.test
printf 'timeout=30\nsearch=off\n' > app.conf
git add app.conf && git commit -m "Create release baseline"
git branch -M main
git switch -c release/2.4
git switch -c hotfix/payment-timeout
printf 'timeout=10\nsearch=off\n' > app.conf
git commit -am "Reduce payment timeout"
git switch release/2.4
git switch -c feature/search
printf 'timeout=30\nsearch=partial\n' > app.conf
git add app.conf
printf 'unfinished parser\n' > search-draft.txt

اکنون status --short باید تغییر آماده‌شده و فایل ردیابی‌نشده نشان دهد. ایستگاهها را یکی‌یکی انجام بده و قبل از drop همیشه محتوا را ثابت کن:

Now status --short should show a staged change and an untracked file. Complete the checkpoints one at a time, verifying content before any drop:

  1. وقفه را ثبت کنRecord the interruption

    هر دو فایل را با پیام روشن و گزینهٔ مناسب stash کن. با وضعیت و فهرست stash ثابت کن پوشه تمیز و رد موجود است.

    Stash both files with a clear message and the right option. Use status/list to prove the worktree is clean and the entry exists.

  2. اصلاح را انتخاب کنSelect the fix

    روی نسخه‌ انتشار برو، شناسه‌ شیء اصلاح فوری را با log/show بشناس و cherry-pick کن. مقصد، diff و والد commit تازه را بررسی کن.

    Switch to release, identify the hotfix OID with log/show, and cherry-pick. Inspect the target, diff, and new parent.

  3. آزمون و tagTest and tag

    فایل را بخوان، tag نشانه‌دار v2.4.1-lab بساز و با show مقصدش را ثابت کن. اگر bare مخزن راه دور اختیاری ساختی، tag را جدا push و با ls-remote بررسی کن.

    Inspect the file, create annotated tag v2.4.1-lab, and verify its target with show. If you make an optional bare remote, push the tag separately and inspect with ls-remote.

  4. کار قابلیت را برگردانRestore the feature work

    به قابلیت برگرد و stash را با apply اعمال کن. status/diff ثابت کند فایل آماده‌شده و ردیابی‌نشده برگشته‌اند. بعد از این مدرک، رد را drop کن یا نگه دار.

    Return to feature and apply the stash. Prove with status/diff that staged and untracked files returned. Afterward, drop or keep the entry.

اگر ترتیب یادت رفتIf you lose the sequence

اول پوشه را امن کن؛ بعد patch را روی مقصد درست بساز؛ tag فقط بعد از آزمون. فایل تازه به -u نیاز دارد؛ apply رد را نگه می‌دارد.

First make the worktree safe; then apply the patch on the right target; tag only after testing. The new file needs -u; apply keeps the entry.

اگر cherry-pick تعارض دادIf cherry-pick conflicts

وضعیت را بخوان، نتیجه را آگاهانه بنویس، ناحیه‌ آماده‌سازی و continue کن. اگر مقصد غلط است، abort؛ تا علت را نفهمیده‌ای ادامه نده.

Read status, write the intended result, stage, and continue. If the target is wrong, abort; do not continue before understanding the cause.

شاهد قبولیAcceptance evidence
  • وضعیت هر دو شاخه با git status --short --branch
  • Both branches with git status --short --branch
  • گراف با git log --oneline --graph --decorate --all
  • Graph with git log --oneline --graph --decorate --all
  • مقصد tag با git show --no-patch --decorate v2.4.1-lab
  • Tag target with git show --no-patch --decorate v2.4.1-lab
  • diff قابلیت بعد از apply و توضیح اینکه چرا شناسه‌ شیء اصلاح فوری و نسخه‌ انتشار یکی نیستند.
  • Feature diff after apply and an explanation of why hotfix and release OIDs differ.

تمرین‌ها: انتخاب درست، نه حفظ فرمانExercises: choose well, do not memorise

برای هر سؤال فقط بپرس «چه چیزی را می‌خواهم جابه‌جا کنم؟» کار ثبت‌نشده، تغییر داخل یک commit و نام یک نسخه سه جنس متفاوت‌اند. stash، cherry-pick و tag هم به همین دلیل سه ابزار جدا هستند؛ اگر مسئله را درست نام ببری، انتخاب ابزار ساده می‌شود.

Start with the model, then move to team incidents. Rely on what was actually recorded, not branch names or wishful thinking.

۱پایه / Beginner

دو فایل ردیابی‌شده تغییر کرده‌اند، یکی آماده‌شده است. آیا stash معمولی هر دو را ثبت می‌کند و بعد از موفقیت چه می‌شود؟

Two tracked files changed, one staged. Does a normal stash record both, and what happens after success?

توضیح / Explanation

بله؛ تغییرهای آماده‌شده و آماده‌نشده ثبت می‌شوند و ناحیه‌ها معمولاً به HEAD برمی‌گردند. stash commit روی شاخه نیست.

Yes; staged and unstaged edits are recorded and the areas normally return to HEAD. A stash is not a branch commit.

۲پایه / Beginner

new.md ردیابی‌نشده بود و بعد از stash ناپدید شد. چه می‌کنی؟

new.md was untracked and disappeared after stashing. What do you do?

غیبت مدرک نیست / Absence is not proof

بررسی کن رد با -u ساخته شده یا نه: stash list و stash show -p -u. اگر محتوا آنجا نیست، نسخهٔ ویرایشگر یا سیستم فایل را بجوی؛ بازیابی تضمین‌شده نیست.

Check whether the entry used -u with stash list/show. If the content is absent, check editor/filesystem recovery; restoration is not guaranteed.

۳پایه / Beginner

stash را فقط می‌خواهی بخوانی، نه اعمال کنی. چه می‌زنی؟

You want to inspect, not apply, a stash. What do you run?

بازرسی / Inspection

git stash list و git stash show -p "stash@{n}". این‌ها پوشه را تغییر نمی‌دهند.

Use git stash list and git stash show -p "stash@{n}". They do not modify the worktree.

۴پایه / Beginner

apply تغییرها را برگردانده ولی رد هنوز هست. شکست است؟

apply restored the edits, but the entry remains. Is that failure?

رفتار مورد انتظار / Expected behavior

خیر؛ apply نگه می‌دارد. بررسی کن و اگر دیگر لازم نیست drop کن. pop بعد از موفقیت حذف می‌کند.

No; apply keeps it. Verify, then drop if no longer needed. Pop removes it after success.

۵پایه / Beginner

ردیابی‌نشده باید ذخیره شود، ignored نه. کدام گزینه؟

Include untracked, but exclude ignored files. Which option?

دامنهٔ محدود / Narrow scope

-u. گزینهٔ -a ignoredها را هم می‌گیرد و بیش از نیاز است.

Use -u. -a also includes ignored files and is broader than needed.

۶میانی / Intermediate

stash pop تعارض داد. آیا رد حذف شد؟

Stash pop conflicted. Was the entry removed?

اول بررسی / Inspect first

معمولاً نه. وضعیت و list را بخوان، تعارض را حل و ناحیه‌ آماده‌سازی کن، تست بگیر؛ بعد از اثبات نتیجه drop کن.

Usually not. Inspect status/list, resolve and stage, test, and drop only after verifying.

سه ابزار این فصل را قاطی نکن. از اینجا به بعد هر تمرین را با یک اسم شروع کن: «کار نیمه‌تمام»، «تغییر داخل commit»، یا «نام یک نسخه». همین اسم معمولاً ابزار را مشخص می‌کند.

Do not mix the three tools in this chapter. From here, label each problem first: “unfinished work,” “a change inside a commit,” or “a release name.” That label usually identifies the right tool.

۷میانی / Intermediate

یک patch باید به نسخه‌ انتشار بیاید ولی کل شاخه نه. چه روشی؟

One patch must reach release, but not the whole branch. Which operation?

انتقال انتخابی / Selective integration

cherry-pick؛ اول شناسه‌ شیء، diff و شاخهٔ مقصد را ثابت کن. برای انتقال مسیر تاریخ کامل merge را بررسی کن.

Cherry-pick; first verify OID, diff, and target branch. Use merge when the full lineage is needed.

۸میانی / Intermediate

چرا commit cherry-pickشده معمولاً شناسه‌ شیء دیگری دارد؟

Why does a cherry-picked commit usually have another OID?

والد بخشی از هویت است / Parent is part of identity

commit تازه روی والد مقصد ساخته می‌شود و فراداده هم ممکن است فرق کند. patch مشابه است؛ شیء الزاماً یکی نیست.

The new commit is built on the target parent and metadata may differ. The patch can be similar while the object differs.

۹میانی / Intermediate

دو commit وابسته باید با رابطهٔ والدها وارد شاخه شوند. merge یا cherry-pick؟

Two dependent commits should enter with ancestry. Merge or cherry-pick?

تاریخچه را حفظ کن / Preserve history

معمولاً merge؛ cherry-pickها patchها را بازسازی می‌کنند و مسیر تاریخ مبدا را همان‌طور حفظ نمی‌کنند.

Usually merge; cherry-picks reconstruct patches rather than preserving the source lineage in the same way.

۱۰میانی / Intermediate

بعد از حل و ناحیه‌ آماده‌سازی تعارض، چه‌طور cherry-pick را تمام می‌کنی؟

After resolving and staging, how do you finish the cherry-pick?

Continue یا abort

--continue commit را ثبت می‌کند؛ اگر انتخاب غلط بود --abort. --skip برای رد commit جاری در یک توالی چندتایی است.

--continue records the commit; use --abort if the choice was wrong. --skip skips the current commit in a sequence.

۱۱میانی / Intermediate

تلاش دوم patch خالی شد. آیا --allow-empty راه پیش‌فرض است؟

A second attempt produces an empty patch. Is --allow-empty the default fix?

علت را پیدا کن / Find the cause

نه؛ تغییر شاید از قبل آمده، مقصد غلط است یا commit ذاتاً خالی است. log و diff را بسنج و skip/abort را آگاهانه انتخاب کن.

No; it may already be applied, the target may be wrong, or the source may be intentionally empty. Inspect log/diff and choose skip or abort deliberately.

۱۲میانی / Intermediate

برای برچسب محلی موقت و نسخه‌ انتشار دارای پیام، چه tagهایی می‌سازی؟

Which tags suit a temporary local marker and a release with a message?

نوع از قصد می‌آید / Intent chooses kind

سبک برای نشانهٔ موقت؛ نشانه‌دار برای نسخه‌ انتشار، مثلاً git tag -a v2.4.1 -m "Release" HEAD. مقصد را با show بخوان.

Lightweight for a temporary marker; annotated for a release, e.g. git tag -a v2.4.1 -m "Release" HEAD. Inspect it with show.

تمرین‌های آخر چند ابزار را پشت سر هم می‌آورند. مهم این است که مرز هر مرحله روشن بماند: stash نباید اصلاح فوری را ببلعد، cherry-pick نباید تاریخ شاخهٔ مبدا را منتقل کند و tag باید دقیقاً روی commit آزموده‌شده بنشیند.

The final exercises chain the tools together. Keep each boundary clear: the stash must not swallow the hotfix, cherry-pick must not import the source branch ancestry, and the tag must point at the tested commit.

۱۳میانی / Intermediate

شاخه push شد ولی tag در مخزن راه دور نیست. چه می‌کنی؟

The branch was pushed, but the tag is absent remotely. What do you do?

ref جدا، push جدا / Separate ref, separate push

git push origin v2.4.1، سپس git ls-remote --tags origin. شاخه push به‌تنهایی انتشار tag را ثابت نمی‌کند.

Run git push origin v2.4.1, then git ls-remote --tags origin. A branch push alone does not prove tag publication.

۱۴پرونده / Incident

نام tag از قبل هست و مدیر می‌خواهد دوباره بسازی. قدم اول؟

The tag name already exists and a manager asks you to recreate it. First step?

نام را جابه‌جا نکن / Do not move it casually

git show TAG و git ls-remote --tags origin را بررسی کن. اگر مقصد فرق دارد، هماهنگ شو؛ ممکن است نام عمومی مبنای ساخت باشد.

Inspect git show TAG and the remote tags. If the target differs, coordinate; public names may anchor builds.

۱۵پرونده / Incident

سه tag محلی داری، فقط یکی باید منتشر شود. چرا push --tags پرریسک است؟

You have three local tags, but only one should be published. Why is push --tags risky?

دامنهٔ ناخواسته / Unintended scope

همهٔ tagهای محلی را می‌فرستد، حتی آزمایشی یا خصوصی. نام دقیق را push و مخزن راه دور را بررسی کن.

It sends all local tags, including experimental or private ones. Push the exact name and inspect the remote.

۱۶پرونده / Incident

وسط cherry-pick می‌فهمی دو commit وابستهٔ دیگر لازم‌اند. چه می‌کنی؟

Mid-cherry-pick, you learn two dependent commits are also required. What now?

توقف و طراحی دوباره / Pause and reconsider

وضعیت را بخوان؛ اگر توالی جاری است abort کن، بعد تصمیم بگیر merge مسیر تاریخ بهتری می‌دهد یا چند cherry-pick با ترتیب مشخص لازم‌اند. بی‌بررسی ادامه نده.

Inspect status; if the sequence is active, abort, then decide whether merge preserves better lineage or ordered cherry-picks are needed. Do not continue blindly.

۱۷پرونده / Incident

pop موفق شد ولی تست fail شد و رد هم ناپدید شد. اول چه می‌خوانی؟

Pop succeeded but tests failed and the entry disappeared. What do you inspect first?

فرمان موفق، کار نه / Command success is not task success

وضعیت، diff، ردیابی‌نشدهها و تست را. شاید بخشی هرگز stash نشده یا زمینه patch را عوض کرده. بازیابی را تضمین نکن؛ دفعهٔ بعد apply، وارسی و بعد drop.

Inspect status, diff, untracked paths, and tests. Some work may never have been stashed or context changed the patch. Do not promise recovery; next time apply, verify, then drop.

۱۸پروندهٔ تیمی / Team incident

ساخت با توضیح نسخه‌ انتشار مدیر برای v3.0.0 نمی‌خواند؛ شاخه push شده و tag شاید جا مانده. سه شاهد؟

The build differs from the release manager's description of v3.0.0; the branch was pushed and the tag may be missing. What three facts do you prove?

سه مقصد را جدا کن / Separate three targets

log --decorate برای commit شاخه، show v3.0.0 برای tag محلی، و ls-remote --tags origin برای مخزن راه دور. اگر مقصد مخزن راه دور غلط است، قبل از تغییر هماهنگ شو.

Use log --decorate for the branch commit, show v3.0.0 for the local tag, and ls-remote --tags origin for the remote. Coordinate before changing an incorrect public target.

وقتی می‌دانی چه می‌خواهی، این ابزارها کمک می‌کنندThese tools help when you know what you need

این سه ابزار وقتی به درد می‌خورند که دقیقاً می‌دانی چه چیزی می‌خواهی. فصل بعد برعکس است: فقط می‌دانیم جایی در چند ده commit گذشته یک باگ وارد شده و باید با کمترین آزمون، مرزش را پیدا کنیم.

You can preserve unfinished work, apply a known patch, and name a tested version. But if a bug appeared weeks ago and you do not know which commit introduced it, neither stash nor cherry-pick answers that question. Chapter 12 turns it into a systematic search with git bisect.

مرور کوتاهQuick reference

وقفه، patch انتخابی، نشانهٔ انتشارPause, selected patch, release marker
  • stash push -m برای ردیابی‌شده؛ -u ردیابی‌نشده را می‌گیرد، نه ignored را.
  • stash push -m for tracked edits; -u includes untracked, not ignored, files.
  • list/show -p را قبل از restore بخوان؛ apply نگه می‌دارد، pop بعد از موفقیت حذف می‌کند.
  • Inspect with list/show; apply keeps the entry, successful pop removes it.
  • stash محلی و موقت است؛ drop فقط بعد از بررسی.
  • A stash is local and temporary; drop only after inspection.
  • قبل از cherry-pick مقصد و patch را ثابت کن؛ تعارض را continue یا abort کن.
  • Verify target and patch before cherry-picking; continue or abort a conflict deliberately.
  • نسخه‌ انتشار را معمولاً با tag نشانه‌دار نام‌گذاری و با show بررسی کن.
  • Usually use an annotated tag for a release and verify with show.
  • tag مشخص را push کن؛ --tags همه را می‌فرستد.
  • Push one named tag; --tags sends them all.

stash برای توقف کوتاه، cherry-pick برای آوردن یک تغییر مشخص و tag برای نام‌گذاری یک نقطهٔ تاریخ است. اگر یکی از این سه را برای مسئلهٔ دیگری استفاده می‌کنی، یک بار دیگر سؤال اصلی را بخوان.

For behavior in your Git version, see the official manuals for git stash, git cherry-pick, git tag, and git push. Configuration may affect pushes; inspect the remote result.