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

کار تیمی: PR و بازبینی کد

Team collaboration: pull requests and code review

دو PR می‌توانند دقیقاً یک قابلیت را بسازند، اما یکی در ده دقیقه فهمیده شود و دیگری یک ساعت وقت بگیرد. تفاوت فقط کد نیست؛ نحوهٔ تقسیم commitها، توضیح مسئله و نشانه‌هایی است که برای بازبین می‌گذاری.

Two pull requests for one feature are on the table. The first changes 38 files, is titled “update stuff,” and mixes behavior, formatting, refactoring, and generated files. The second has three focused commits, a clear scope, and says which tests ran. If you can carefully review only one today, which would you choose—and why?

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

یک تغییر را چطور به همکارت نشان می‌دهی؟How do you present a change to a teammate?

در فصل ۱۳ دربارهٔ سیاست شاخه‌ها تصمیم گرفتیم؛ حالا یک شاخه آمادهٔ ادغام است و باید انسانی دیگر آن را بفهمد. دشواری PR اول اینجاست: بازبین باید حدس بزند کدام فایل مهم است، چرا قالب‌بندی عوض شده، تست‌ها کجا هستند و آیا فایل تولیدشده عمدی است یا تصادفی.

Chapter 13 helped us choose a branching policy. Now a branch is ready to integrate, and another person needs to understand it. The cost of the first PR becomes clear: the reviewer must guess which file matters, why formatting changed, where the tests are, and whether a generated file is intentional.

PR کوچک‌تر الزاماً درست‌تر نیست، اما معمولاً پرسش روشن‌تری می‌سازد: «این تغییر مشخص، مشکل مشخص را حل می‌کند؟» اگر refactor مکانیکی را از تغییر رفتار جدا کنی، بازبین می‌تواند اول شکل کد را بفهمد و بعد منطق تازه را بررسی کند. اگر جداسازی خودش معنای تغییر را پنهان می‌کند، آن را به قانون خشک تبدیل نکن؛ دلیل هر بخش را توضیح بده.

A smaller PR is not automatically more correct, but it usually asks a clearer question: “Does this specific change solve this specific problem?” Separating mechanical refactoring from behavior can let a reviewer understand the code shape first and then inspect the new logic. If separation would hide the meaning of the change, do not turn it into a rigid rule; explain why the pieces belong together.

A branch is pushed, proposed in a pull request, reviewed, checked, and then merged branchcommits pushto remote PR / reviewconversation mergeto base branch CI + repository rules may gate merge
نمودار ۱ — commitها از شاخه به مخزن راه دور می‌روند؛ PR در میزبان گفت‌وگو و بررسی را کنار diff جمع می‌کند. merge نتیجه را به شاخهٔ مقصد می‌رساند؛ بررسی و تأیید فقط طبق تنظیمات همان مخزن مانع ادغام می‌شوند.
Diagram 1 — Commits move from a branch to a remote; the host's PR gathers discussion and review around the diff. Merge integrates the result into the target branch; checks and approvals block it only when repository settings require them.

یک مرز مهم: Git شاخه، commit و مخزن راه دور را می‌شناسد؛ PR یا MR چیزی نیست که به‌عنوان شیء داخل .git ذخیره شده باشد. میزبان گفتگو، بازبینی، بررسیهای CI، تأییدها و دکمه‌های merge را به آن تغییرها وصل می‌کند. Git می‌تواند شاخهها را جابه‌جا و ادغام کند حتی اگر هیچ PRای نداشته باشی؛ اما تاریخچهٔ گفت‌وگوی PR را Git محلی نگه نمی‌دارد.

An important boundary: Git knows branches, commits, and remotes; a PR or MR is not an object stored inside .git. The hosting platform attaches discussion, reviews, CI checks, approvals, and merge controls to those changes. Git can move and merge branches without any PR, but it does not store the PR conversation in your local repository.

commit خوب، بررسی را به قدم‌های قابل‌فهم تقسیم می‌کندGood commits break review into understandable steps

بازبین diff را می‌بیند، اما commitهای شاخه می‌توانند مسیر رسیدن به diff را هم روشن کنند. commit اتمی یک تغییر کوچک و منسجم را ثبت می‌کند؛ یعنی بعداً می‌توانی همان بخش را بفهمی یا جداگانه برگردانی. اتمی یعنی یک دلیل روشن برای تغییر، نه الزاماً یک خط کد.

A reviewer sees the diff, but the branch's commits can also explain how it got there. An atomic commit records one small, coherent change, so later you can understand or revert that part separately. Atomic means one clear reason for the change, not necessarily one line of code.

پیام/ترتیبMessage / sequenceبازبین چه می‌فهمد؟What can a reviewer learn?چه چیزی را بهتر است جدا کنی؟What may deserve separation?
update stuffتقریباً هیچ؛ باید diff را بدون سرنخ بخواند.Almost nothing; the reviewer must infer the purpose from the diff.عنوانی که نه تغییر را می‌گوید و نه دلیل را باز می‌کند.A title that names neither the change nor its intent.
refactor: extract name normalization
fix: use fallback for blank names
اول ساختار عوض شده، بعد رفتار قابل‌مشاهده اصلاح شده.Structure changed first; observable behavior was fixed next.تغییر مکانیکی را از منطق رفتاری جدا کن، اگر هر دو commit به‌تنهایی معتبر و قابل‌فهم می‌مانند.Separate mechanical edits from behavior when each commit remains understandable and valid.
test: cover blank display namesمی‌بیند چه رفتاری باید حفظ شود.Shows which behavior must remain correct.آزمون را جایی بگذار که خواننده بتواند آن را با پیاده‌سازی پیوند دهد.Place tests where the reader can connect them to the implementation.

پیام commit لازم نیست از یک الگوی جهانی پیروی کند. یک summary کوتاه بگوید چه تغییر معناداری رخ داده؛ اگر دلیل در diff معلوم نیست، بدنه توضیح دهد چرا تصمیم گرفته شد، چه گزینه‌ای کنار گذاشته شد و چه محدودیتی باقی است. Conventional Commits مثل feat: و fix: یک قرارداد اختیاری برای تیم یا ابزارهاست، نه قانونی که Git enforce کند.

Commit messages do not need a universal format. A short summary should name the meaningful change; if the reason is not obvious from the diff, the body can explain why the decision was made, which alternative was rejected, and what limitation remains. Conventional Commits labels such as feat: and fix: are an optional convention, not a rule enforced by Git.

اگر شاخه چند commit آزمایشی دارد، می‌توانی قبل از بازبینی نهایی آن‌ها را با fixup و interactive rebase مرتب کنی؛ فصل ۷ این ابزار را باز کرد. اما اگر همکار شاخه را گرفته یا سیاست تیم تاریخچهٔ بازبینی را حفظ می‌کند، بازنویسی commitهای منتشرشده شناسه‌ها و نظرهای inline را جابه‌جا می‌کند. قبل از squash یا rebase بپرس چه چیزی باید در تاریخچه بماند.

If a branch contains experimental commits, you may organize them with fixup and interactive rebase before final review; Chapter 7 covered that tool. But if a teammate already has the branch or team policy preserves review history, rewriting published commits changes IDs and can displace inline comments. Before squashing or rebasing, ask what the history should preserve.

توضیح PR، سؤال بازبین را قبل از حدس‌زدن جواب می‌دهدA PR description answers the reviewer's first questions

عنوان خوب شروع است، اما بازبین هنوز باید بداند چرا این تغییر لازم شد. توضیح PR نقشهٔ خواندن diff است، نه جای تکرار همهٔ commitها. اگر از او می‌خواهی دربارهٔ رفتار، خطر انتشار یا تصمیم معماری نظر بدهد، همان‌جا مشخصش کن.

A good title is a start, but the reviewer still needs to know why the change exists. A PR description is a map for reading the diff, not a repetition of every commit. If you want feedback on behavior, rollout risk, or an architectural decision, say so directly.

بخش توضیحDescription partپرسشی که جواب می‌دهدQuestion it answersنمونهExample
مشکلProblemکاربر یا تیم چه چیزی را تجربه می‌کند؟What is the user or team experiencing?نامی که فقط فاصله دارد خالی به‌نظر می‌رسد.A name containing only spaces looks blank.
راه‌حل و محدودهApproach and scopeچه چیزی عوض می‌شود و چه چیزی عمداً عوض نمی‌شود؟What changes, and what is intentionally unchanged?ورودی متنی را trim می‌کنیم؛ ترجمهٔ Guest بیرون از این تغییر است.Trim text input; translating “Guest” is outside this change.
آزمونTestingچه چیزی واقعاً اجرا شد و چه چیزی هنوز بررسی نشده؟What actually ran, and what remains unchecked?python3 -m unittest
خطر و انتشارRisk and rolloutآیا رفتار یا انتشار برای کاربر خطر خاصی دارد؟Does behavior or rollout carry a particular user risk?رفتار ورودی خالی عوض می‌شود؛ نام‌های معمولی دست‌نخورده‌اند.The fallback for blank input changes; ordinary names are unchanged.

Issue را فقط اگر تیم از آن برای پیوند کار استفاده می‌کند وصل کن. تصویر یا log وقتی مفید است که رفتار دیداری یا خروجی را روشن کند؛ دادهٔ شخصی، token، رمز یا log حساس را در PR نگذار. برای migration یا انتشار پرخطر، یک بند کوتاه دربارهٔ برگشت یا پایش بعد از انتشار اضافه کن.

Link an issue if the team uses it to connect work. Add a screenshot or log only when it clarifies visual behavior or output; never include personal data, tokens, passwords, or sensitive logs. For risky migrations or rollouts, add a short note about rollback or post-release monitoring.

بازبینی، پیدا کردن عیب است؛ مسابقهٔ سلیقه نیستReview is about finding risk, not winning a style contest

بازبین از عنوان و توضیح شروع می‌کند، بعد diff را می‌خواند و می‌پرسد: «آیا این کد مسئلهٔ تعریف‌شده را درست حل می‌کند؟» اگر نیت معلوم نباشد، بازبینی خط‌به‌خط هم ممکن است به نکته‌های کم‌اهمیت بچسبد و خطر اصلی را جا بیندازد.

A reviewer starts with the title and description, then reads the diff and asks: “Does this code correctly solve the stated problem?” Without clear intent, even a line-by-line review can focus on minor details and miss the actual risk.

Author context and reviewer questions converge on a revised, verified change authorintent + scope + tests reviewerquestions + risks revised diffresponse + proof shared context keeps review focused
نمودار ۲ — نویسنده نیت و آزمون را می‌دهد؛ بازبین پرسش و ریسک را برمی‌گرداند؛ نویسنده diff را با پاسخ یا اصلاح تازه می‌کند. PR محل این رفت‌وبرگشت است، نه امتیاز یک‌طرفه به کد.
Diagram 2 — The author supplies intent and tests; the reviewer returns questions and risks; the author updates the diff with an explanation or fix. A PR hosts this exchange, not a one-way score for the code.
نقشRoleپرسش خوبUseful questionنمونهٔ بازخوردExample feedback
نویسندهAuthorآیا محدوده، تصمیم و مدرک را طوری داده‌ام که بازبین مجبور به حدس نباشد؟Have I provided enough scope, reasoning, and evidence to avoid guesswork?«این PR رفتار blank را عوض می‌کند؛ حالت None را نمی‌پذیرد چون ورودی تابع str است.»“This PR changes blank input; it does not accept None because the function input is a string.”
بازبینReviewerآیا منظور درست، مرزهای ورودی پوشش‌داده‌شده و تغییر قابل‌نگهداری است؟Is the intent correct, are input boundaries covered, and is the change maintainable?«آیا رشتهٔ فقط‌فاصله هم باید Guest شود؟ تستی برای این قرارداد می‌بینم؟»“Should a whitespace-only string also become Guest? Is there a test for that contract?”
هر دوBothآیا دربارهٔ رفتار و خطر حرف می‌زنیم یا فقط سلیقهٔ قالب‌بندی؟Are we discussing behavior and risk, or only formatting preference?«آیا formatter پروژه این فاصله را تعیین می‌کند؟» بهتر از «من این سبک را دوست ندارم» است.“Does the project formatter define this spacing?” is better than “I dislike this style.”

بازبینی را از منظور، correctness، آزمون، نگه‌داری و در جای لازم امنیت شروع کن. سؤال، درخواست تغییر و پیشنهاد سلیقه‌ای را از هم جدا کن. در GitHub می‌توانی نظر کلی یا inline بگذاری، پیشنهاد تغییر بسازی و در پایان Comment، Approve یا Request changes ثبت کنی. اینکه Request changes merge را مسدود کند به ruleهای مخزن بستگی دارد.

Start review with intent, correctness, tests, maintainability, and security where relevant. Distinguish a question, a required change, and a stylistic suggestion. On GitHub, you can leave general or inline comments, suggest an edit, and submit Comment, Approve, or Request changes. Whether Request changes blocks merging depends on repository rules.

درخواست تغییر را بی‌توضیح رها نکن: بگو چه رفتاری نگران‌کننده است و چه مدرکی آن را برطرف می‌کند. نویسنده لازم نیست هر پیشنهاد سلیقه‌ای را بپذیرد؛ کافی است منظور را بفهمد، دلیل تصمیمش را محترمانه بنویسد و اگر لازم شد آن را با آزمون یا قرارداد پروژه مقایسه کند. بازبینی خوب می‌تواند با توافق بر «فعلاً همین، بعداً issue جدا» تمام شود.

Do not leave a change request unexplained: say what behavior worries you and what evidence would resolve it. An author need not accept every stylistic suggestion; they should understand it, explain their decision respectfully, and compare it with tests or project conventions where useful. A good review can end with agreement to handle a follow-up in a separate issue.

بعد از بازخورد، پاسخ را به commit و توضیح تبدیل کنTurn review feedback into a commit and an explanation

دو نظر روی PR رسید: «برای رشتهٔ فقط‌فاصله تست داریم؟» و «اگر ورودی None باشد قرارداد تابع چیست؟» قبل از ویرایش، منظور سؤال دوم را روشن کن. آیا رفتار تازه لازم است یا بازبین می‌خواهد قرارداد موجود را واضح ببیند؟ هر نظر را با تغییر کد، آزمون یا پاسخ مستدل ببند.

Two comments arrive: “Do we test whitespace-only input?” and “What is the function contract if the input is None?” Before editing, clarify the second comment's intent. Is new behavior required, or does the reviewer want the existing contract made explicit? Resolve each comment with a code change, a test, or a reasoned answer.

برای نظر اول، تستی اضافه کن که " " را بررسی کند و مطمئن شو خروجی Guest است. برای دومی، اگر API فقط str می‌پذیرد، نوع hint و توضیح را روشن کن؛ اگر None از مسیر واقعی می‌رسد، آن را به قرارداد اضافه کن و آزمونش را بنویس. یکی را با «باید کار کند» جواب نده؛ قرارداد باید از کد و تست خوانده شود.

For the first comment, add a test for " " and verify that the result is Guest. For the second, clarify the type hint and docs if the API accepts only str; if None can arrive in the real path, add it to the contract and test it. Do not answer with “it should work”; make the contract visible in code and tests.

اگر شاخه فقط دست خودت است، یک follow-up commit معمولاً امن‌ترین پاسخ است: تاریخچهٔ بازبینی و مقایسهٔ قبل/بعد روشن می‌ماند. اگر سیاست تیم می‌گوید قبل از merge commitهای fixup را squash کن، هماهنگ شو. بعد از push همکار ممکن است شاخه را داشته باشد یا comment را روی commit مشخص گذاشته باشد؛ rebase شناسه‌ها را عوض می‌کند و نظرهای قدیمی را نیازمند بازبینی دوباره می‌سازد.

If the branch is yours alone, a follow-up commit is often the safest response: review history and before/after remain visible. If team policy says to squash fixups before merge, coordinate that. After a push, a teammate may have the branch or comments may refer to specific commits; rebasing changes IDs and can require old comments to be revisited.

--force-with-lease حصار است، نه چراغ سبز--force-with-lease is a guard, not a green light

اگر بازنویسی شاخه منتشرشده واقعاً لازم و طبق سیاست مجاز است، --force-with-lease می‌تواند push را رد کند وقتی مخزن راه دور از اشاره‌گر موردانتظار تو جلو رفته باشد. اما اگر وضعیت همکار را fetch کرده‌ای و بعد عمداً تاریخچه‌ای می‌فرستی که آن commit را کنار گذاشته، lease ممکن است همان وضعیت تازه را معتبر بداند و overwrite را انجام دهد. اول اشاره‌گرها را ببین، با همکار هماهنگ کن و در صورت امکان commit تازه push کن.

If rewriting a published branch is genuinely needed and allowed by policy, --force-with-lease can reject a push when the remote has moved beyond your expected ref. But if you fetched a teammate's latest state and then intentionally push history that omits their commit, the lease may consider that new state expected and allow the overwrite. Inspect refs, coordinate, and prefer a new commit when possible.

سه روش merge، سه شکل تاریخچهThree merge methods, three history shapes

PR تأیید شده و بررسیها سبزند؛ هنوز باید بپرسیم کدام تاریخچه را می‌خواهیم. هیچ روش mergeای «بهترین» نیست: یکی رابطهٔ شاخه را ثبت می‌کند، یکی تغییرها را یک‌جا جمع می‌کند، دیگری commitها را جدا نگه می‌دارد اما روی خط پایه بازنویسی می‌کند.

The PR is approved and checks are green; we still need to ask what history we want. No merge method is universally best: one records the branch relationship, one combines its changes, and another keeps commits separate but replays them onto the base line.

Merge commit, squash merge, and rebase merge produce different commit graphs same reviewed change · different history on the target merge commitbranch commits + merge node squashone new combined commit rebase / linearreplayed commits · new IDs choose by traceability, commit quality, and team conventionhosting platforms may constrain or implement options differently
نمودار ۳ — هر سه تغییر را به مقصد می‌رسانند اما ردّ تاریخچه فرق می‌کند. merge commit دو خط و نقطهٔ ادغام را نگه می‌دارد؛ squash یک commit تازه می‌سازد؛ rebase/linear commitها را روی مقصد بازپخش می‌کند و شناسهٔ تازه می‌دهد.
Diagram 3 — All three integrate the change, but preserve different traces. A merge commit keeps both lines and the integration point; squash creates one new commit; rebase/linear replays commits onto the target with new IDs.
\n+
روشMethodچه چیزی به مقصد می‌رسد؟What reaches the target?مناسب وقتی…Useful when…هزینه یا نکتهCost or caveat
merge commitMerge commitcommitهای شاخه به‌علاوهٔ commit ادغام با دو والدBranch commits plus a two-parent merge commitمی‌خواهی تاریخچهٔ کامل شاخه و نقطهٔ ادغام بماند.You want the full branch history and integration point preserved.گراف شاخه‌دارتر است؛ commitهای کم‌کیفیت هم می‌مانند.The graph is less linear; low-quality commits remain visible.
squash mergeSquash mergeیک commit جدید با حاصل تغییرهای PROne new commit containing the PR's combined changesیک PR یک تغییر منطقی است و commitهای میانی بیشتر fixup بوده‌اند.One PR is one logical change and intermediate commits were mostly fixups.commitهای میانی روی خط مقصد جدا نیستند؛ ادامهٔ همان شاخه بعد از squash می‌تواند diff تکراری بسازد.Intermediate commits are not separate on the target; continuing the same branch after squash can produce confusing repeat diffs.
rebase and merge / خطیRebase and merge / linearcommitهای شاخه به‌شکل commitهای بازپخش‌شده، بدون merge commitBranch commits replayed onto the target without a merge commitتاریخچهٔ خطی می‌خواهی و هر commit جداگانه تمیز و معنادار است.You want linear history and each commit is already clean and meaningful.شناسهٔ commitها عوض می‌شود؛ رفتار دقیق میزبان ممکن است با git rebase محلی فرق کند.Commit IDs change; host-specific details may differ from local git rebase.

در GitHub، روش‌های merge را مدیر مخزن می‌تواند روشن یا خاموش کند. طبق مستند فعلی، squash یک commit روی مقصد می‌سازد؛ Rebase and merge commitهای شاخه را جداگانه بدون merge commit اضافه می‌کند و SHA تازه می‌سازد. این گزینهٔ میزبان را عیناً با اجرای محلی git rebase یکی نگیر. اگر merge queue فعال باشد، خود queue هم می‌تواند روش ادغام را کنترل کند.

On GitHub, repository administrators can enable or disable merge methods. Its current documentation says squash creates one commit on the target, while Rebase and merge adds branch commits individually without a merge commit and creates new SHAs. Do not assume this host option is identical to running local git rebase. When a merge queue is active, the queue may also control the merge method.

CI و حفاظت شاخه، دروازه‌ای با شرط‌های مشخص‌اندCI and branch protection form a gate with explicit conditions

بازبین می‌گوید کد قابل‌فهم است، اما هنوز ممکن است تست، lint یا ساخت شکست بخورد. CI نتیجهٔ بررسیهای خودکار را کنار PR می‌آورد؛ حفاظت شاخه می‌تواند بعضی نتیجه‌ها و تعداد تأییدهای لازم را شرط merge کند. سبز بودن بررسی فقط همان بررسی تعریف‌شده را ثابت می‌کند.

A reviewer may find the code understandable while a test, lint, or build still fails. CI attaches automated check results to the PR; branch protection can make selected results and approvals merge conditions. A green check proves only what that configured check actually tests.

A pull request reaches the protected branch only when required checks and approvals pass pull requestproposed diff required CI checkstest · build · lint required reviewapproval · conversations protected basemerge allowed a missing / failing required condition keeps the gate closed
نمودار ۴ — PR باید از بررسی و بازبینیای بگذرد که مخزن واقعاً لازم کرده است. پیکان‌ها جریان بررسی به سوی شاخهٔ محافظت‌شده را نشان می‌دهند؛ اگر شرطی تنظیم نشده باشد، نمودار به‌تنهایی آن را ایجاد نمی‌کند.
Diagram 4 — A PR must pass the checks and reviews the repository actually requires. Arrows show review flow toward the protected branch; the diagram cannot create a condition that was never configured.

در GitHub، نتیجهٔ بازبینی و بررسیها در PR دیده می‌شود و حفاظت شاخه می‌تواند آن‌ها را الزام کند. تنظیم‌ها ممکن است به سطح دسترسی و قواعد همان مخزن وابسته باشند. یک PR سبز ثابت نمی‌کند منظور درست فهمیده شده، تست‌ها کافی‌اند یا انتشار موفق خواهد شد؛ بازبین و نویسنده باید این مرز را حفظ کنند.

On GitHub, review decisions and check results appear in the PR, and branch protection can require them. Settings may depend on repository permissions and rules. A green PR does not prove intent was understood, tests are sufficient, or deployment will succeed; authors and reviewers must keep that boundary clear.

وقتی PR گیر می‌کند، دنبال شاهد بگرد نه دکمهٔ سریعWhen a PR stalls, look for evidence—not a quick button

نشانهSymptomاول چه چیزی را ببینی؟What to inspect firstاقدام بعدیNext action
PR قدیمی؛ base جلو رفتهStale PR; base has movedشاخه‌های مقایسه‌شده، تعارض‌ها، آخرین بررسی و فایل‌های تغییرکرده را ببین.Inspect base/head, conflicts, latest checks, and changed files.base تازه را طبق سیاست با merge یا rebase هماهنگ کن؛ تست و diff نهایی را دوباره بررسی کن.Update from the new base by merge or rebase per policy; rerun checks and inspect the final diff.
PR بزرگ و درهمLarge, mixed PRgit diff --stat و فهرست فایل‌ها را بخوان؛ فایل تولیدشده و قالب‌بندی را جدا تشخیص بده.Read git diff --stat and the file list; identify generated and formatting-only changes.تغییر مستقل را جدا کن یا دلیلش را توضیح بده؛ secret را هیچ‌وقت برای بازبینی منتشر نکن.Split independent changes or explain why not; never expose a secret for review.
push رد شد؛ مخزن راه دور جلوتر استPush rejected; remote advancedبا fetch و git log --graph --oneline --decorate --all commit تازه را پیدا کن.Fetch and inspect new commits with git log --graph --oneline --decorate --all.اگر commit همکار هست، آن را حفظ و هماهنگ شو؛ --force نزن.Preserve the collaborator's commit and coordinate; do not use --force.
CI سبز، اما نیت مبهمCI is green, but intent is unclearتوضیح PR، نیاز محصول و diff را کنار هم بگذار.Compare the PR description, product requirement, and diff.سؤال روشن بپرس یا محدوده و آزمون را بخواه؛ سبزی CI جای فهم مسئله نیست.Ask a focused question or request clearer scope and testing; green CI does not explain intent.
تغییر ناخواستهٔ فایل تولیدی یا secretUnexpected generated file or secretقبل از تأیید منشأ فایل را امن بررسی کن؛ مقدار secret را در comment کپی نکن.Safely inspect the file's origin before approval; do not copy a secret into a comment.فایل را طبق سیاست بساز یا حذف کن. اگر secret لو رفته، حذف از diff کافی نیست: اعتبارنامه را عوض کن.Regenerate or remove the file per policy. If a secret leaked, deleting it from the diff is not enough: rotate the credential.

وقتی یک درخواست ادغام گیر می‌کند، سریع دنبال دکمهٔ merge یا push اجباری نرو. اول معلوم کن مشکل از چیست: شاخه عقب افتاده؟ تست شکست خورده؟ بازبین سؤال بی‌جواب دارد؟ یا تغییرها آن‌قدر قاطی‌اند که اصلاً نمی‌شود با اطمینان بررسی‌شان کرد؟

On GitHub, a new review may still be pending until submitted. If new commits are pushed to an approved PR and the repository dismisses stale approvals, the previous approval may become stale. Before requesting review again, inspect the review state and commit it covered; confirm exact behavior from repository settings and current host documentation.

پروژهٔ کوچک: یک PR آمادهٔ بازبینی کنMini-project: prepare a reviewable PR

در این پروژه خودت نقش نویسنده و بازبین را لمس می‌کنی. چند commit کوچک می‌سازی، توضیح درخواست ادغام را می‌نویسی، دو بازخورد می‌گیری و بعد تغییر را طوری به‌روز می‌کنی که هم گراف درست بماند و هم بازبین مجبور نباشد حدس بزند چه اتفاقی افتاده است.

We will build a small feature from two people's perspectives. If you have GitHub or GitLab access, use a disposable repository. Otherwise, create a bare remote and two clones, and simulate the PR and two comments in Markdown. This is not a real PR object or API; it lets you practice the diff, review exchange, and merge before using a host.

سناریو: تابع display_name نام را trim می‌کند و برای رشتهٔ خالی Guest برمی‌گرداند. سه commit جدا و قابل‌فهم بساز: پیاده‌سازی، تست‌ها و توضیح رفتار. قبل از push، خودت diff را مرور کن، test را اجرا کن و هر فایل خارج از محدوده را توضیح بده.

Scenario: a display_name function trims a name and returns Guest for a blank string. Create three separate, understandable commits: implementation, tests, and behavior documentation. Before pushing, self-review the diff, run the tests, and account for every file outside the intended scope.

در Git Bash، macOS یا Linux، این محیط ایزوله را بساز. پوشهٔ review-lab تازه است و فقط مخزن راه دور آزمایشی را در خودش دارد:

In Git Bash, macOS, or Linux, create this isolated environment. The new review-lab directory contains only the disposable test remote:

create a disposable remote and author clone
mkdir review-lab && cd review-lab
git init --bare --initial-branch=main team.git
git clone team.git author
cd author
git config user.name "Roya Author"
git config user.email roya@example.test

یک README.md ساده بساز، commit و push کن تا مبنای مشترک داشته باشیم. بعد clone بازبین را کنار clone نویسنده بساز؛ این دو پوشه working copy مستقل‌اند و شاخه نویسنده تا قبل از push به بازبین نمی‌رسد.

Create a simple README.md, commit and push it to establish a shared base. Then clone the reviewer copy beside the author's; these are independent working copies, and the author's branch will not reach the reviewer before it is pushed.

establish the shared base and clone the reviewer
printf '# Display-name review lab\n' > README.md
git add README.md
git commit -m "docs: start display-name review lab"
git push -u origin main
cd ..
git clone team.git reviewer
cd author
git switch -c feature/trim-display-name

فایل app.py را با این رفتار کوچک بساز. فعلاً قرارداد ورودی str است؛ اگر محصول باید None را هم بپذیرد، آن نیاز را جدا به مسئله اضافه کن، نه اینکه بی‌صدا فرضش بگیری:

Create app.py with this small behavior. The input contract is str for now; if the product must accept None, add that requirement explicitly rather than silently assuming it:

app.py · implementation
def display_name(value: str) -> str:
    cleaned = value.strip()
    return cleaned or "Guest"

برای تست از کتابخانهٔ استاندارد Python استفاده کن تا وابستگی تازه‌ای لازم نباشد. هر commit یک علت روشن دارد:

Use Python's standard library for tests so no new dependency is needed. Each commit should have one clear reason:

test_app.py · behavior contract
import unittest
from app import display_name

class DisplayNameTests(unittest.TestCase):
    def test_trims_surrounding_spaces(self):
        self.assertEqual(display_name("  Mina  "), "Mina")

    def test_preserves_regular_name(self):
        self.assertEqual(display_name("Roya"), "Roya")

if __name__ == "__main__":
    unittest.main()

در README رفتار blank را هم توضیح بده. سپس سه commit بساز و هر بار فقط فایل همان مرحله را ناحیه‌ آماده‌سازی کن. دستورها را یکی‌یکی اجرا کن و قبل از commit سوم وضعیت و diff را بخوان:

Document blank-input behavior in the README. Then create three commits, staging only the file for each step. Run the commands one at a time and inspect status and diff before the third commit:

three focused commits and a self-review
git add app.py
git commit -m "feat: trim display names and add blank fallback"
git add test_app.py
git commit -m "test: cover display-name behavior"
git add README.md
git commit -m "docs: explain display-name fallback"
python3 -m unittest
git diff --check main...HEAD
git diff --stat main...HEAD
git log --oneline --reverse main..HEAD

خروجی تست باید دو تست موفق را نشان دهد؛ git diff --check در موفقیت چیزی چاپ نمی‌کند؛ و log باید سه commit شاخه را نشان دهد. این شاهدها می‌گویند تست‌های موجود پاس شدند، whitespace مشکل‌دار در diff نیست و تاریخچه سه قدم دارد؛ ثابت نمی‌کنند PR در میزبان باز شده یا همهٔ نیازهای محصول پوشش دارند.

The test output should show two passing tests; git diff --check prints nothing on success; and the log should show three branch commits. This evidence says the existing tests passed, the diff has no whitespace errors, and the history has three steps. It does not prove a hosted PR exists or that every product requirement is covered.

شاخه را push کن تا بازبین بتواند آن را ببیند. اگر حساب میزبان داری، PR را با عنوان روشن و توضیح «مشکل، راه‌حل، محدودهٔ خارج از تغییر، تست و خطر» بساز و دو نظر پایین را ثبت کن. در مسیر محلی، فایل review.md را بیرون cloneها بساز تا وانمود نکنیم PR یک فایل Git است.

Push the branch so the reviewer can see it. If you use a host, open a PR with a clear title and a description covering problem, approach, out-of-scope behavior, tests, and risk; add the two comments below. For the local path, create review.md outside the clones so we do not pretend a PR is a Git file.

publish and inspect from a second clone
git push -u origin feature/trim-display-name
cd ..
git -C reviewer fetch origin
git -C reviewer diff --stat origin/main...origin/feature/trim-display-name
git -C reviewer diff origin/main...origin/feature/trim-display-name

بازبین دو نظر بدهد: «برای رشتهٔ فقط‌فاصله آزمون مستقلی داریم؟» و «ورودی None جزو قرارداد هست یا باید خطای نوع بگیریم؟» نظر اول باید به تغییر قابل‌آزمایش برسد؛ نظر دوم شاید با روشن‌کردن قرارداد جواب بگیرد و الزاماً تغییر رفتار نمی‌خواهد. نویسنده پاسخ را بیرون repo در review.md ثبت کند.

Have the reviewer leave two comments: “Do we have a dedicated test for whitespace-only input?” and “Is None part of the contract, or should this be a type error?” The first should lead to a testable change; the second may be resolved by clarifying the contract without changing behavior. Record the response outside the repository in review.md.

نظر اول را با تستی تازه پاسخ بده؛ پیش از تغییر، نتیجهٔ تست را ببین و بعد همان دستور را دوباره اجرا کن. برای نظر دوم، اگر قرارداد str است توضیح بده؛ اگر None از مسیر واقعی می‌رسد، قرارداد و آزمونش را تغییر بده. commit جدید را عادی push کن؛ اینجا شاخه خودت است و تاریخچه را بازنویسی نکرده‌ای.

Answer the first comment with a new test; observe the current test result before editing, then rerun the same command. For the second, explain the str contract; if None arrives in the real path, change and test the contract. Push a normal follow-up commit; this is your branch and you have not rewritten history.

follow-up commit; reviewer fetches the updated branch
cd author
# add a whitespace-only test to test_app.py, then:
python3 -m unittest
git add test_app.py
git commit -m "test: cover whitespace-only display names"
git push
git -C reviewer fetch origin
git -C reviewer log --oneline origin/main..origin/feature/trim-display-name
git -C reviewer diff origin/main...origin/feature/trim-display-name

بعد از دیدن بررسی سبز و بازبینی diff تازه، merge را طبق سیاست انتخاب کن. در مسیر محلی، این فقط merge شاخه در bare مخزن راه دور است؛ protection و تأیید واقعی میزبان وجود ندارند. برای merge commit، نویسنده در clone خودش main را به‌روز می‌کند، ادغام می‌کند و push می‌کند:

After reviewing the new diff and seeing checks pass, merge under team policy. In the local path this is only a branch merge against a bare remote; real host protection and approval rules are absent. For a merge commit, the author updates main in their clone, integrates, and pushes:

local simulation · disposable repository only
git switch main
git pull --ff-only origin main
git merge --no-ff feature/trim-display-name -m "merge: review display-name behavior"
python3 -m unittest
git log --graph --oneline --decorate --all
git push origin main
git -C ../reviewer fetch origin
git -C ../reviewer log --graph --oneline --decorate origin/main
پاک‌سازی فقط بعد از جمع‌آوری مدرکClean up only after collecting evidence

پیش از حذف review-lab، log، diff نهایی، خروجی تست، توضیح PR و دو پاسخ بازبینی را ثبت کن. در میزبان واقعی شاخه را فقط بعد از merge موفق و اطمینان از نبود کار همکار پاک کن. پاک‌سازی را از پوشهٔ والد آزمایش اجرا کن؛ مخزن اصلی را هدف نگیر.

Before removing review-lab, save the final log, diff, test output, PR description, and both review responses. On a real host, delete the branch only after a successful merge and after confirming no teammate's work remains. Clean up from the lab's parent directory; never target the real repository.

تمرین‌ها: PR را از دید هر دو نفر ببینExercises: see the PR from both sides

تمرین‌ها را از هر دو طرف میز ببین. یک بار نویسنده‌ای که می‌خواهد تغییرش فهمیده شود و یک بار بازبینی که باید با زمان محدود مطمئن شود تغییر درست و قابل نگهداری است. خیلی از جواب‌های خوب این فصل دربارهٔ کم‌کردن ابهام‌اند، نه حفظ یک قالب ثابت.

For each case, give a decision and its reason; “this is good” is not enough. State what should change, what evidence would establish the result, and which risk remains.

۱. دو PR را مقایسه کن1. Compare two PRs

PR اول ۳۸ فایل و عنوان «update stuff» دارد؛ PR دوم سه commit با عنوان روشن و تست دارد. کدام را اول می‌خوانی؟ یک نشانه بگو که ممکن است انتخابت را عوض کند.

PR A has 38 files and the title “update stuff”; PR B has three focused commits and tests. Which do you review first? Name one signal that might change your choice.

راهنماHint

اندازه فقط تعداد فایل نیست؛ خطر فوری، محدوده و توضیح را هم ببین.

Size is not only file count; consider urgency, scope, and context too.

معمولاً PR دوم را می‌توان دقیق‌تر شروع کرد، چون هدف و مرز تغییر روشن‌تر است. اما اگر PR بزرگ رفع یک رخداد زنده باشد، اولویت عوض می‌شود؛ باز هم فایل‌های مکانیکی/generated باید مشخص یا کار به بخش‌های بررسی‌پذیر تقسیم شود. عدد ۳۸ به‌تنهایی حکم رد نیست.

PR B is usually easier to review carefully because its purpose and boundaries are clearer. An urgent incident fix may change priority; even then, mechanical/generated files should be identified or work split into reviewable pieces. The number 38 alone is not a rejection rule.

۲. پیام commit مبهم2. An unclear commit message

git log --oneline این را نشان می‌دهد: a13cd21 update stuff. چه چیزی از این پیام نمی‌فهمی و چطور بهترش می‌کنی؟ یک عنوان جایگزین و یک دلیل بیاور.

git log --oneline shows a13cd21 update stuff. What can you not learn from this message, and how would you improve it? Give a replacement subject and explain why.

راهنماHint

عنوان باید تغییر را مشخص کند؛ دلیل پیچیده را می‌توان در بدنه آورد.

The subject should identify the change; a more complex rationale can go in the body.

این پیام نه موضوع تغییر را می‌گوید نه دامنه‌اش را. fix: treat whitespace-only names as blank روشن‌تر است. اگر دلیل تصمیم معلوم نیست، بدنه توضیح دهد چه مسئله‌ای رخ می‌داد؛ لازم نیست همهٔ تیم‌ها prefix خاصی استفاده کنند.

The message says neither what changed nor its scope. fix: treat whitespace-only names as blank is clearer. If the rationale is not obvious, the body can explain the problem; not every team needs the same prefix convention.

۳. آیا Conventional Commits اجباری است؟3. Are Conventional Commits mandatory?

تیمی پیام‌هایی مثل feat: و fix: را می‌پسندد. همکارت می‌گوید Git commit بدون این prefix را رد می‌کند. تشخیص درست را با یک دلیل بگو.

A team likes messages such as feat: and fix:. A teammate claims Git rejects commits without those prefixes. Correct the claim and give a reason.

راهنماHint

قابلیت خود Git را از قراردادی که ابزار جدا enforce می‌کند جدا کن.

Separate Git's behavior from a convention enforced by a separate tool.

این convention است، نه الزام داخلی Git. تیم می‌تواند آن را در راهنما یا hook/CI بررسی کند، اما enforcement از تنظیم جدا می‌آید. اگر ابزار انتشار به قالب وابسته است، دلیل خوبی برای توافق تیمی است؛ وگرنه قالب آزاد هم ممکن است مناسب باشد.

It is a convention, not a built-in Git requirement. A team may check it with guidance or a hook/CI, but enforcement comes from separate configuration. If release tooling depends on the format, that is a good reason for an agreement; otherwise a looser format may be fine.

۴. قالب‌بندی و رفتار در یک diff4. Formatting and behavior in one diff

یک PR کل پروژه را format کرده و یک bug را هم رفع می‌کند. چه مشکلی برای بازبینی می‌بینی و چه دو راهی داری؟

A PR reformats the whole project and fixes a bug. What review problem do you see, and what are two options?

راهنماHint

بازبین باید تغییر مکانیکی را از تصمیم رفتاری تشخیص دهد.

The reviewer needs to distinguish mechanical edits from behavioral decisions.

قالب‌بندی ممکن است بخش رفتاری کوچک را در انبوه diff پنهان کند. اگر مستقل‌اند، دو PR یا دو commit معتبر بساز؛ اگر ابزار آن‌ها را یک‌جا تولید می‌کند، تغییر مکانیکی را مشخص و تست رفتار را جدا نشان بده. جداسازی کورکورانه اگر فهم را سخت کند کمک نیست.

Formatting may hide the small behavior change in a large diff. If independent, split into PRs or valid commits; if tooling produces them together, label mechanical edits and show behavior tests separately. Blind separation is not helpful if it makes the change harder to understand.

۵. توضیح PR چه کم دارد؟5. What is missing from this PR description?

توضیح فقط می‌گوید: «این قابلیت اضافه شد.» سه پرسشی را فهرست کن که بازبین هنوز باید بپرسد و یک بند بهتر پیشنهاد بده.

The description says only, “Added this feature.” List three questions the reviewer still has and propose a better paragraph.

راهنماHint

از مشکل، محدوده و تست شروع کن.

Start with the problem, scope, and tests.

بازبین نمی‌داند چه مشکلی حل شد، کدام رفتار خارج از محدوده است و چه تستی اجرا شده. مثلاً: «رشتهٔ فقط‌فاصله اکنون Guest می‌شود. نام عادی فقط trim می‌شود؛ ترجمهٔ fallback بیرون از این PR است. unittest اجرا شد؛ رفتار None در قرارداد نیست.» جملهٔ آخر را فقط اگر واقعاً درست است بنویس.

The reviewer does not know what problem was solved, what is out of scope, or which tests ran. For example: “Whitespace-only input now becomes Guest. Regular names are only trimmed; translating the fallback is out of scope. Unit tests ran; None is not in the contract.” State the last sentence only if it is true.

۶. تغییر فایل تولیدشده6. A generated file changed

در PR یک فایل generated بزرگ می‌بینی که نویسنده درباره‌اش چیزی نگفته. آیا فوراً ردش می‌کنی؟ قبل از تصمیم چه مدرکی می‌خواهی؟

A large generated file appears in a PR with no explanation. Do you reject it immediately? What evidence do you want before deciding?

راهنماHint

منشأ فایل و قرارداد مخزن دربارهٔ commit کردن خروجی را پیدا کن.

Find the file's origin and the repository's policy for committing generated output.

اول بپرس این فایل از کدام ورودی/ابزار تولید شده و آیا باید version control شود. diff را امن و با ابزار مناسب بخوان، تولید را بازتولید و خروجی را مقایسه کن. اگر secret یا دادهٔ حساس است، مقدار را در comment بازنشر نکن و دسترسی/تعویض اعتبارنامه را بررسی کن.

First ask which input/tool generated it and whether repository policy tracks it. Inspect the diff safely, reproduce generation, and compare output. If it contains a secret or sensitive data, do not repeat it in a comment; review access and credential rotation.

از اینجا به بعد فقط کیفیت کد مهم نیست؛ کیفیت ارائهٔ تغییر هم مهم است. بازبین نباید برای فهمیدن مسئله بین ۳۰ فایل و پنج commit نامرتبط حدس بزند.

From here, code quality is not the only concern; how the change is presented matters too. A reviewer should not have to guess the intent across thirty files and five unrelated commits.

۷. بازبینی یا سلیقه؟7. Review or preference?

بازبین می‌نویسد «من این نام را دوست ندارم»، اما قرارداد تیم دربارهٔ نام‌گذاری روشن نیست. نویسنده چه پاسخی بدهد تا بحث مفید شود؟

A reviewer writes, “I don't like this name,” but the team has no naming convention. How can the author respond constructively?

راهنماHint

اثر نام روی فهم، رفتار یا سازگاری پروژه را بپرس.

Ask how the name affects understanding, behavior, or project consistency.

با احترام بپرس: «کدام برداشت اشتباه را ممکن می‌کند؟ نمونه‌ای در پروژه داریم؟» اگر به فهم یا قرارداد موجود مربوط است، اصلاح کن؛ اگر فقط سلیقه است، قاعدهٔ آینده را جدا توافق کنید یا همین‌جا ببندید. هدف بردن بحث نیست.

Ask respectfully: “What misunderstanding could this name cause? Is there a similar convention in the project?” If it affects understanding or an existing convention, change it; if it is preference, agree on a future rule separately or close the discussion. The goal is not to win.

۸. وضعیت Request changes8. The Request changes state

یک بازبین در GitHub گزینهٔ Request changes را می‌زند. آیا merge در همهٔ مخزن‌ها قطعاً ناممکن می‌شود؟ پاسخ را مشروط و دقیق بگو.

A GitHub reviewer selects Request changes. Is merging definitely impossible in every repository? Give a precise, conditional answer.

راهنماHint

تصمیم بازبینی را از تنظیم حفاظت شاخه جدا کن.

Separate the review decision from branch-protection settings.

نه؛ خود وضعیت به‌تنهایی همه‌جا blocker نیست. اگر حفاظت شاخه یا ruleset تأیید لازم را enforce کند، بازبینی می‌تواند merge را ببندد؛ وگرنه اختیارهای مخزن ممکن است اجازه دهند. تنظیم واقعی را ببین، نه فقط label را.

No; the state alone is not universally a blocker. If branch protection or a ruleset enforces approval requirements, the review can block merging; otherwise repository permissions may allow it. Inspect actual settings, not just the label.

۹. CI سبز اما منظور گم9. Green CI, unclear intent

تمام بررسیها سبزند، ولی توضیح PR معلوم نمی‌کند آیا رفتار برای کاربر عوض می‌شود. آیا می‌توانی approve کنی؟ چه سؤال و مدرکی لازم است؟

All checks are green, but the PR description does not say whether user behavior changes. Can you approve it? What question and evidence do you need?

راهنماHint

بررسیها بخش قابل‌آزمون را پوشش می‌دهند، نه لزوماً دلیل محصول را.

Checks cover what they test, not necessarily the product rationale.

اگر منظور برای ارزیابی اثر لازم است، فعلاً approve نکن؛ از نویسنده رفتار قبلی/جدید و محدوده را بخواه و مسیر مرتبط را در diff یا تست ببین. CI سبز ابهام مسئله را حل نمی‌کند.

If intent is needed to judge impact, do not approve yet; ask the author to clarify old/new behavior and scope, then inspect related code or tests. Green CI does not resolve an unclear problem statement.

۱۰. PR قدیمی شده10. The PR has gone stale

main دو روز پیش جلو رفته و CI مربوط به commit قدیمی سبز است. قبل از merge چه می‌کنی و چه چیزی را دوباره بررسی می‌کنی؟

Main advanced two days ago and CI is green for an older commit. What do you do before merging, and what do you recheck?

راهنماHint

نتیجهٔ قدیمی برای ترکیب تازه الزاماً معتبر نیست.

An old result does not necessarily apply to the new combination.

طبق سیاست شاخه را با base تازه هماهنگ کن، تعارض را حل و بررسیها را روی ترکیب نهایی دوباره اجرا کن. بازبینی را هم روی diff تازه بخواه؛ merge یا rebase ممکن است محتوای بررسی‌شده را عوض کند. سبز بودن SHA قبلی مدرک SHA جدید نیست.

Under team policy, update the branch from the new base, resolve conflicts, and rerun checks on the final combination. Request review of the new diff too; merge or rebase may change what was reviewed. A green result for the old SHA is not evidence for the new one.

۱۱. همکار commit تازه‌ای دارد11. A collaborator pushed a commit

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

Your push is rejected because the remote is ahead. You share the branch with a teammate. What unsafe action should you avoid, and what should you inspect?

راهنماHint

قبل از force، commitهایی را پیدا کن که در clone تو نیستند.

Before considering force, find commits missing from your clone.

force نزن. fetch کن و گراف یا git log HEAD..origin/feature/name را ببین تا commit همکار را پیدا کنی. آن را طبق سیاست merge/rebase و حفظ کن، تست و push عادی انجام بده. force-with-lease ریسک را کم می‌کند، اما مجوز حذف کار همکار نیست.

Do not force-push. Fetch and inspect the graph or git log HEAD..origin/feature/name to find the teammate's commit. Preserve it with merge/rebase under policy, test, and push normally. Force-with-lease reduces risk but is not permission to remove a teammate's work.

۱۲. نظرهای inline بعد از rebase12. Inline comments after a rebase

نویسنده شاخه منتشرشده را rebase و push اجباری کرده؛ چند نظر inline جابه‌جا یا outdated شده‌اند. چه رخ داد و چطور از تکرار سردرگمی کم می‌کنی؟

The author rebased a published branch and force-pushed; some inline comments moved or became outdated. What happened, and how can the team reduce confusion?

راهنماHint

comment ممکن است به commit یا خط diff قدیمی وصل باشد.

A comment may refer to an older commit or diff line.

rebase commitهای تازه با شناسه‌های جدید ساخته و تاریخچهٔ شاخه را عوض کرده؛ میزبان ممکن است نظر را outdated نشان دهد. قبل از rewrite هماهنگ کن، برای پاسخ push عادی را ترجیح بده و اگر rewrite لازم شد بگو چه commitهایی عوض شدند و بازبینی تازه بخواه.

Rebase created commits with new IDs and changed branch history; the host may mark comments outdated. Coordinate before rewriting, prefer normal pushes for responses, and if rewriting is necessary, explain which commits changed and request a fresh review.

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

The final exercises move you between author and reviewer roles. Each time, ask what information is missing for a decision and how a better commit, explanation, or test can reduce that uncertainty.

۱۳. merge commit یا squash؟13. Merge commit or squash?

PR یک تغییر منطقی است اما شاخه شش commit آزمایشی و fixup دارد. چه روشی پیشنهاد می‌دهی و چه اطلاعاتی ممکن است از دست برود؟

A PR is one logical change, but its branch has six experimental and fixup commits. Which method would you recommend, and what information might be lost?

راهنماHint

بپرس commitهای میانی ارزش تاریخی مستقل دارند یا نه.

Ask whether intermediate commits have independent historical value.

اگر سیاست اجازه می‌دهد و PR یک واحد منطقی است، squash می‌تواند یک commit تمیز روی مقصد بسازد. جزئیات ترتیب و پیام commitهای میانی جدا نمی‌ماند. اگر آن قدم‌ها برای bisect یا فهم مسیر مهم‌اند، آن‌ها را مرتب کن و merge commit یا rebase/linear را بسنج.

If policy allows and the PR is one logical unit, squash can create one clean target commit. The separate order and messages of intermediate commits will not remain on the target line. If those steps matter for bisect or understanding, organize them and consider merge commit or rebase/linear.

۱۴. هر commit را نگه داریم؟14. Should every commit be preserved?

یک PR چهار commit معنی‌دار دارد و تیم می‌خواهد هر مرحله در تاریخچه دیده شود. بین merge commit، squash و rebase/linear چه انتخابی معقول است؟ یک هزینه را هم بگو.

A PR has four meaningful commits and the team wants each step visible in history. Which of merge commit, squash, or rebase/linear is plausible? Name a cost too.

راهنماHint

شکل گراف و نیاز به دیدن نقطهٔ ادغام دو پرسش جدا هستند.

Graph shape and the need to preserve an integration point are separate questions.

rebase/linear آن‌ها را جدا روی مقصد نگه می‌دارد اما SHA تازه می‌دهد. merge commit هم قدم‌ها را نگه می‌دارد و رابطهٔ والدها ادغام را نشان می‌دهد، ولی گراف شاخه‌دار است. squash با حفظ چهار قدم سازگار نیست، مگر جزئیات جای دیگری بماند.

Rebase/linear keeps them separately on the target but creates new SHAs. A merge commit also preserves the steps and shows integration ancestry, but the graph is non-linear. Squash conflicts with preserving four steps unless details are kept elsewhere.

۱۵. CI و بازبینی چه می‌کنند؟15. What do CI and review each do?

یک PR دو تأیید گرفته اما required test قرمز است. PR دیگری بررسی سبز دارد ولی توضیحش مبهم است. برای هر کدام مانع merge چیست و چرا؟

One PR has two approvals but a required test is red. Another has green checks but an unclear description. What blocks merging in each case, and why?

راهنماHint

شرط خودکار مخزن و فهم انسانی دو سیگنال متفاوت‌اند.

Automated repository conditions and human understanding are different signals.

در اولی، required بررسی قرمز باید طبق rule ادغام را ببندد؛ تأیید جای تست نیست. در دومی، ابزار شاید merge را نبندد، اما بازبین نباید بدون فهم منظور تأیید کند. قوانین ماشینی شرط لازم می‌گذارند، نه اینکه تمام قضاوت انسانی را انجام دهند.

For the first, the failing required check should block merge under the rule; approval does not replace tests. For the second, tooling may not block merge, but a reviewer should not approve without understanding intent. Machine rules enforce necessary conditions, not all human judgment.

۱۶. secret در diff16. A secret appears in the diff

در فایل generated یک API token دیدی که شاید واقعی باشد. قبل از approve یا درخواست اصلاح، دست‌کم سه قدم بگو.

You found a possibly real API token in a generated file. Give at least three steps before approving or requesting a fix.

راهنماHint

حذف خط کافی نیست اگر اعتبارنامه قبلاً push شده باشد.

Removing the line is not enough if the credential was already pushed.

تأیید را نگه دار و مقدار را در comment کپی نکن. از مسیر امن با مسئول مخزن تماس بگیر تا اعتبارنامه فوراً revoke/rotate شود؛ بعد منشأ فایل و secret scanning را بررسی کن. حذف از diff آن را از commit یا clone قبلی پاک نمی‌کند؛ پاک‌سازی تاریخچه برنامه و هماهنگی می‌خواهد.

Withhold approval and do not copy the value into a comment. Contact the repository owner safely so the credential can be revoked/rotated; then inspect file generation and secret scanning. Removing it from the diff does not erase prior commits or clones; history cleanup requires a plan and coordination.

۱۷. comment سؤال است یا blocker؟17. Is the comment a question or a blocker?

بازبین روی یک خط سؤال گذاشته ولی Request changes نزده: «این شاخه از کجا می‌داند locale چیست؟» نویسنده چه چیزی را بررسی و برای بستن نظر چه پاسخی آماده کند؟

A reviewer left a line comment but did not select Request changes: “How does this branch know the locale?” What should the author inspect, and what response would resolve the thread?

راهنماHint

نوع دکمه همهٔ نیت را نمی‌گوید؛ سؤال را از نظر رفتار دنبال کن.

The review button does not reveal all intent; investigate the behavioral question.

مسیر داده و فرض locale را در کد و تست پیدا کن. اگر از تنظیم موجود می‌آید، محلش را نشان بده و تست را ارجاع یا اضافه کن؛ اگر نه، رفتار را اصلاح یا محدوده را روشن کن. بعد از push، بازبین diff تازه را می‌بیند و وقتی پاسخ قابل‌بررسی شد thread را می‌بندد.

Trace the locale assumption through code and tests. If it comes from existing configuration, point to it and reference or add a test; otherwise fix behavior or clarify scope. After the push, the reviewer inspects the new diff and resolves the thread once the answer is verifiable.

۱۸. تاریخچهٔ PR را طراحی کن18. Design the PR history

سه commit شاخه عبارت‌اند از refactor، fix و test و هر کدام معنی‌دارند. تیم تاریخچهٔ ساده می‌خواهد اما علت تغییر هم باید بماند. دو روش merge را مقایسه کن و یک پرسش باقی‌مانده را بگو.

A branch has three meaningful refactor, fix, and test commits. The team wants simple history but also wants the rationale preserved. Compare two merge methods and name one question that remains.

راهنماHint

سادگی گراف و حفظ commitهای میانی ممکن است با هم trade off داشته باشند.

A simple graph and preservation of intermediate commits may trade off.

squash گراف مقصد را ساده می‌کند ولی سه قدم را یکی می‌کند؛ rebase/linear سه قدم را نگه می‌دارد و SHA تازه می‌دهد؛ merge commit قدم‌ها و رابطهٔ شاخه را ثبت می‌کند اما گراف شاخه‌دارتر است. باید پرسید آیا commitها مستقل و معتبرند و سیاست میزبان کدام روش را مجاز می‌کند.

Squash simplifies the target graph but combines the three steps; rebase/linear keeps them with new SHAs; a merge commit records the steps and branch relationship but creates a less-linear graph. Ask whether commits are independently valid and which methods host policy allows.

تغییر بررسی‌پذیر آماده است؛ مخزن چه ابزارهای بیشتری می‌خواهد؟The change is reviewable; what more does the repository need?

حالا تغییرها نه فقط از نظر Git، بلکه برای آدم‌ها هم قابل بررسی شده‌اند. فصل بعد سراغ ابزارهایی می‌رود که برای شکل‌های خاص‌تر مخزن لازم می‌شوند؛ ابزارهایی که باید فقط وقتی مسئله‌شان را داری سراغشان بروی.

You can now distinguish a branch, PR, review, check, and merge. Some repositories outgrow one folder and one simple remote: concurrent working trees, dependencies on another repository, partial checkouts, or large files. The next chapter explores specialized Git tools for those cases without losing the underlying model.

مرور سریع این فصلQuick reference

پیش از بازبینیBefore reviewحین بازبینیDuring reviewقبل از mergeBefore merge
diff و محدوده را خودت بخوان؛ commit و توضیح PR دلیل تغییر را بگویند.Self-review the diff and scope; commits and the PR description should explain intent.از correctness و خطر شروع کن؛ سؤال را از درخواست تغییر و سلیقه جدا کن.Start with correctness and risk; distinguish questions, required changes, and preference.بررسی و تأیید لازم را روی commit نهایی ببین؛ روش merge را با قرارداد تاریخچه هماهنگ کن.Check required checks and approvals on the final commit; match merge method to history policy.

قاعدهٔ سادهٔ بازبینیA simple review rule

نویسنده باید سؤال «چرا این تغییر؟» را جواب دهد؛ بازبین باید سؤال «چه چیزی ممکن است بشکند؟» را جدی بگیرد. CI یا تعداد تأیید به‌تنهایی فهم منظور و خطر را تضمین نمی‌کند. اگر تاریخچه را بازنویسی می‌کنی، اول مطمئن شو شاخه و نظرهای همکار را از بین نمی‌بری.

The author should answer “Why this change?”; the reviewer should take “What could break?” seriously. CI or approval count alone does not guarantee understanding of intent or risk. If you rewrite history, first make sure you are not discarding a teammate's branch work or review context.

رفتارهای GitHub در این فصل بر پایهٔ مستندات فعلی GitHub هستند؛ گزینه‌های موجود و الزام‌های merge را برای همان مخزن بررسی کن. آماده‌کردن تغییر برای بازبینی · نوع بازبینیها · روش‌های merge · حفاظت شاخه.

GitHub behavior here follows its current documentation; check available options and merge requirements for your repository. Making changes easier to review · Review types · Merge methods · Branch protection.