Git 2026

فصل ۱۱ · Source Control پیشرفته

Source Control فوق‌پیشرفته — Graph تا PR

Graph، شاخه، Sync، تعارض، rebase و PR همه از همان Ctrl+Shift+G می‌آیند. مثل فصل ۱۰: هر کار یعنی چند کلیک مشخص، چه باید ببینی، و اگر مال تو فرق داشت یعنی چه.

🎯 اهداف یادگیری

  • Graph را با کلیک باز کنی و از راست‌کلیک روی کامیت نترسی
  • Fetch / Pull / Push / Sync را از روی منو جدا بزنی و بدانی چرا دکمهٔ تو با کتاب یکی نیست
  • تعارض و rebase را تا آخرین کلیک (Continue یا Abort) تمام کنی
  • اگر Graph، Incoming یا افزونهٔ PR نبود، علت را بدانی

📈 Graph — باز کردن و راست‌کلیک

کلیک‌ها برای باز شدن:

  1. Ctrl+Shift+G.
  2. ته ستون Source Control روی Graph یک کلیک (اگر > دیدی، همان را باز کن).
  3. اگر Graph نبود: Ctrl+Shift+P → Git: View History → Enter.
Source Control Graph نزدیک

شکل ۱۱ — برش نزدیک. رنگ‌ها و هش‌ها مثال‌اند؛ تو کامیت‌های مخزن خودت را می‌بینی.

باید ببینی: خط‌های رنگی، هش کوتاه، پیام کامیت، گاهی برچسب main / HEAD.

اگر مال تو این‌طور نیست:

چه دیدی علت چه کار کن
اصلاً Graph در ستون نیست VS Code قدیمی‌تر از حدود ۱.۹۷ VS Code را به‌روز کن؛ یا افزونهٔ Git Graph / GitLens
Graph باز شد ولی یک نقطه است مخزن فقط یک کامیت دارد طبیعی است
Incoming خالی است با اینکه همکار push کرده Fetch نشده منوی ··· → Fetch (پایین)
راست‌کلیک منوی کوتاه دارد روی پیام کلیک کرده‌ای نه روی گره، یا افزونه منو را عوض کرده روی دایرهٔ کامیت راست‌کلیک کن

راست‌کلیک روی یک دایره / ردیف کامیت، بعد یک کلیک روی فرمان:

فرمان بعد از کلیک چه می‌شود اگر ترسیدی
Checkout HEAD می‌رود روی آن کامیت اگر شاخه نبود، نوار زرد detached می‌آید → فوری Create Branch
Create Branch جعبهٔ نام می‌پرسد Enter بزن؛ معادل git switch -c
Cherry Pick یک کامیت جدید روی شاخهٔ فعلی تعارض آمد = فصل تعارض همین صفحه
Revert یک کامیت خنثی‌کننده می‌سازد برای main مشترک همین را بزن نه Reset
Reset Current Branch to Here می‌پرسد Soft/Hard Hard را روی شاخهٔ مشترک نزن
Compare with HEAD diff باز می‌شود بی‌خطر

🌿 عوض کردن و ساختن شاخه — از نوار وضعیت

کلیک ۱: پایین-چپ پنجره، روی نام شاخه (مثلاً main).
باید ببینی: فهرست بالا وسط ادیتور (Quick Pick).

انتخاب شاخه در نوار وضعیت VS Code

شکل ۱۱ب — اگر این فهرست نیامد، روی نام شاخه کلیک نشده یا Git پیدا نشده.

کلیک ۲ — تعویض: روی نام شاخهٔ دیگر.
باید ببینی: نوار وضعیت همان نام را می‌گیرد؛ فایل‌های ادیتور عوض می‌شوند.

اگر خطا Your local changes would be overwritten: تغییرات ذخیره‌شده داری. اول Commit یا Stash (منوی ··· → Stash)، بعد دوباره نام شاخه را کلیک کن.

کلیک ۲ — ساختن: روی + Create new branch from... → یک کلیک روی پایه‌ای که می‌خواهی (main) → نام را تایپ کن مثلاً feat/auth → Enter.

ساخت شاخه از Command Palette

شکل ۱۱پ — همین کار از Palette با Git: Create Branch from... هم می‌شود.

کلیک Publish Branch: در همان فهرست یا روی دکمهٔ ابری نوار وضعیت. اولین push است (-u).

اگر Publish می‌خواهد وارد GitHub شوی: Accounts پایین Activity Bar → Sign in. بدون origin، دکمهٔ اصلی پنل به‌جای Sync می‌ماند Publish.

اگر شاخهٔ جدید در فهرست نیست: هنوز Enter ساختن را نزدی، یا refresh لازم است: ··· → Refresh.

📡 منوی ··· — هر فرمان یک کلیک، Sync آخرین انتخاب

کلیک: بالا-راست ستون Source Control روی ··· (شمارهٔ ۲ آناتومی فصل ۱۰).

منوی Fetch Pull Stash در Source Control

شکل ۱۱ت — ترتیب پیشنهادی: اول Fetch، نگاه به ↓↑، بعد Pull یا Push. Sync میان‌بر هر دوست.

کلیک روی باید بعدش ببینی مال تو فرق دارد اگر
Fetch عدد ↓ در نوار وضعیت زیاد شود، Graph Incoming پر شود؛ فایل‌ها عوض نمی‌شوند اینترنت/SSH نیست؛ یا origin نداری
Pull فایل‌ها ممکن است عوض شوند؛ ↓ صفر شود تعارض → بخش بعد. اگر rebaseWhenSync روشن باشد ممکن است rebase شروع شود
Pull (Rebase) اگر تعارض باشد نوار زرد Rebase روی main مشترک نزن
Push ↑ صفر شود rejected = کسی push کرده؛ Fetch کن نه Force
Sync ترکیب pull/push اگر confirmSync روشن باشد یک Yes اضافه می‌پرسد — این «خراب بودن» نیست
Stash (Include Untracked) Changes خالی می‌شود بدون Include، فایل‌های U می‌مانند و switch شکست می‌خورد
Undo Last Commit فایل‌ها برمی‌گردند به Staged اگر push کرده باشی، بعداً Push rejected می‌شود
Discard All Changes همهٔ فایل‌های M از لیست می‌روند پنجرهٔ Are you sure؟ — Yes یعنی از دست رفتن کار ذخیره‌نشده

نوار وضعیت ↑1 ↓2 یعنی ۱ کامیت برای push و ۲ برای pull. عدد تو با کتاب یکی نمی‌شود و نباید بشود.

💥 تعارض — از حرف C تا Commit (merge)

تعارض فقط بعد از Merge / Pull / Cherry-pick / Rebase می‌آید. اگر هیچ‌کدام را نزدی و C دیدی، احتمالاً merge ناتمام قبلی مانده: Palette → Git: Abort Merge.

باید ببینی: در Source Control عنوان Merge Changes و فایل با حرف C. دکمهٔ اصلی ممکن است بشود Accept Merge / Commit (merge).

تعارض در Source Control و ادیتور

شکل ۱۱ث — نوار آبی چهار فرمان فقط روی فایل C بازشده از Source Control است.

کلیک‌ها:

  1. یک کلیک روی فایل C.
  2. بالای بلوک قرمز/سبز، یک کلیک روی یکی از:
    • Accept Current Change = نسخهٔ شاخه‌ای که روی آن بودی (HEAD / Ours)
    • Accept Incoming Change = نسخه‌ای که داشتی وارد می‌کردی (Theirs)
    • Accept Both Changes = هر دو پشت‌سرهم؛ بعد خودت ویرایش کن
    • Compare Changes = دو ستون
  3. Ctrl+S.
  4. یک کلیک روی + همان فایل (Stage). حرف C باید برود.
  5. یک کلیک روی Commit (merge) یا Ctrl+Enter با پیام پیش‌فرض merge.

اگر نوار Accept نبود: Palette → Merge Conflict: Open Merge Editor — سه ستون Incoming / Current / Result. Result را درست کن → Accept Merge.

اگر هنوز C می‌ماند: Save و Stage را نزدی. یا چند تعارض در همان فایل است — همه را Accept کن.

پشیمانی قبل از مرحلهٔ ۵: Palette → Git: Abort Merge. بعد از Commit دیگر abort نیست؛ باید revert.

🔁 Rebase ناتمام — نوار زرد را تا انتها دنبال کن

بعد از Pull (Rebase) یا Git: Rebase Branch... اگر تعارض باشد:

باید ببینی: در پنل «Rebase in progress»، در بالا ادیتور نوار زرد، دکمه‌های Continue / Abort.

Rebase in progress در Source Control

شکل ۱۱ج — تا این نوار هست، دکمهٔ معمولی Commit را نزن. VS Code عمداً کامیت عادی را قفل یا گمراه‌کننده می‌کند.

کلیک‌ها:

  1. فایل C را مثل تعارض حل کن → Save → + (Stage).
  2. یک کلیک Continue (= git rebase --continue).
  3. اگر تعارض بعدی آمد، ۱ و ۲ را تکرار کن تا نوار زرد برود.

اگر Continue خاکستری است: هنوز همهٔ فایل‌های C را Stage نکرده‌ای، یا Message rebase خالی است — جعبهٔ Message را خالی نگذار.

پشیمانی: یک کلیک Abort. همه چیز برمی‌گردد به قبل از rebase.

اگر وسط rebase VS Code را بستی و باز کردی: نوار زرد باید برگردد. اگر نماند، Palette → Git: Continue Rebase یا Abort Rebase.

📚 چند مخزن در یک پنجره

کلیک‌ها: File → Add Folder to Workspace → پوشهٔ دوم که خودش .git دارد.

باید ببینی: در Source Control چند عنوان Repository. یک کلیک روی عنوان، آن مخزن را جمع/باز می‌کند.

چند مخزن در Source Control

شکل ۱۱چ — اگر فقط یکی می‌بینی، پوشهٔ دوم Git ندارد یا هنوز Add Folder نکرده‌ای.

اگر Commit روی مخزن غلط نشست: عنوان همان Repository را باز کن، بعد Message را بزن. VS Code روی مخزن «فعال» کامیت می‌کند.

worktree: در ترمینال git worktree add -b hotfix/500 ../hotfix main بعد File → Add Folder روی ../hotfix. یک شاخه در دو worktree هم‌زمان باز نمی‌شود — پیام خطا را با Stash یا عوض کردن شاخه حل کن.

📬 Pull Request — افزونه، نه خود Git توکار

Source Control توکار PR نمی‌سازد. باید افزونهٔ GitHub Pull Requests نصب باشد.

کلیک نصب: Activity Bar آیکون Extensions (یا Ctrl+Shift+X) → جست‌وجو GitHub Pull Requests → Install → Accounts پایین Activity Bar → Sign in to GitHub → مرورگر Allow.

اگر آیکون GitHub در Activity Bar نیامد: افزونه نصب نشده یا غیرفعال است. View → Appearance → Activity Bar را چک کن.

بررسی Pull Request داخل VS Code

شکل ۱۲ — این نما مال افزونه است نه ستون Git. اگر ندیدی، Sign in نشده.

ساخت PR از شاخهٔ فعلی:

  1. اول Push / Publish Branch از Source Control (وگرنه GitHub شاخه را ندارد).
  2. Ctrl+Shift+P → GitHub Pull Requests: Create Pull Request.
  3. عنوان و پایه (main) را تأیید کن → Create.

اگر Create خطا می‌دهد no upstream: Publish Branch را جا انداختی.

ریویو: آیکون GitHub → یک کلیک روی PR → Checkout → در Files Changed روی خط کلیک → کامنت → Approve.

اگر Checkout PR فایل‌های تو را overwrite می‌کند: اول Commit یا Stash از ستون Source Control.

⚙️ اگر رفتار پنل «عجیب» است، اول این تنظیمات را چک کن

Ctrl+, → جست‌وجوی هر کلید:

.vscode/settings.json — رفتار SCM
{
  "git.enabled": true,
  "git.autofetch": true,
  "git.confirmSync": true,
  "git.enableSmartCommit": false,
  "git.enableCommitSigning": true,
  "git.untrackedChanges": "separate",
  "git.branchProtection": ["main", "master"],
  "git.branchProtectionPrompt": "alwaysCommitToNewBranch",
  "git.rebaseWhenSync": false,
  "git.autoStash": true,
  "scm.defaultViewMode": "tree",
  "scm.repositories.visible": 8,
  "diffEditor.ignoreTrimWhitespace": false,
  "diffEditor.hideUnchangedRegions.enabled": true
}
دیدی احتمالاً این تنظیم
Commit بدون + همه را برد enableSmartCommit روشن — Off کن
روی main کامیت زدی، VS Code شاخهٔ جدید ساخت branchProtection — عمدی است
Sync ناگهان rebase شروع کرد rebaseWhenSync روشن
قبل از Pull فایل‌ها ناپدید شدند و بعد برگشتند autoStash — stash موقت، ترس ندارد
Untracked ته لیست قاطی است untrackedChanges را separate کن
هر Sync یک دیالوگ Yes/No confirmSync — سلیقه است

⌨️ Palette — وقتی کلیک را پیدا نمی‌کنی

Ctrl+Shift+P، تایپ Git:، Enter روی فرمان. اگر فرمان در فهرست نیست: یا پوشه مخزن ندارد، یا Git پیدا نشده (Git: Show Git Output).

Stage All Changes · Commit · Undo Last Commit · Push · Pull · Pull (Rebase) · Fetch · Sync · Create Branch from... · Checkout to... · Merge Branch... · Rebase Branch... · Publish Branch · Stash · Continue Rebase · Abort Rebase · Abort Merge · View History · Show Git Output

سؤالات مصاحبه (با پاسخ)

Mid — چرا Sync من merge ساخت و مال همکار rebase؟ تنظیم git.rebaseWhenSync فرق دارد. از روی دکمه حدس نزن؛ منوی ··· را بخوان.

Senior — Checkout PR چه کلیک‌هایی زیرش است؟ Sign in، fetch همان ref، switch به آن شاخه. اگر Changes خالی نبود، VS Code اول Stash/Commit می‌خواهد.

✅ چک‌لیست فهم

  • Graph را باز کرده‌ای و اگر نبود علت را بلدی
  • از روی ··· یک Fetch جدا زده‌ای نه فقط Sync
  • یک فایل C را تا Commit (merge) یا Abort برده‌ای
  • نوار زرد rebase را Continue یا Abort کرده‌ای نه Commit عادی
  • اگر PR نبود، فرق افزونه با Source Control توکار را می‌دانی

فصل بعد: diff، blame، log و bisect — دیدن تغییر با چشم مسلح.

فصل ۱۱ از ۳۶ · مرجع جامع و حرفه‌ای Git و GitHub · ویرایش 1.0.0