~/icsd.ir — bash
SYSTEM_ONLINE

کار با Remote و GitHub

حالا که Git محلی را یاد گرفتیم، وقت آن است که به دنیای متصل برویم. در این فصل یاد می‌گیریم چطور با GitHub کار کنیم: ساخت ریپازیتوری، اتصال SSH، push، pull، fetch و مفاهیم remote.

حالا که Git محلی را یاد گرفتیم، وقت آن است که به دنیای متصل برویم. در این فصل یاد می‌گیریم چطور با GitHub کار کنیم: ساخت ریپازیتوری، اتصال SSH، push، pull، fetch و مفاهیم remote.

Remote چیست؟

Remote نسخه‌ای از ریپازیتوری شماست که جای دیگری نگهداری می‌شود – معمولاً روی GitHub، GitLab یا یک سرور.

┌─────────────────┐         ┌──────────────────┐
│  Local Repo     │ ←────→  │  Remote Repo     │
│  (your computer)│         │  (GitHub server) │
└─────────────────┘         └──────────────────┘
        ↑
    git push / pull / fetch

یک پروژه می‌تواند چند remote داشته باشد. معمول‌ترین نام: origin

ساخت ریپازیتوری در GitHub

روش ۱: ابتدا در GitHub، سپس clone

  1. به github.com بروید
  2. روی + در بالا سمت چپ → New repository
  3. Repository name: todo-app
  4. توضیحات (اختیاری)
  5. Public یا Private
  6. تیک Add a README file را بزنید
  7. Add .gitignore (Python، Node، …)
  8. Choose a license (MIT متداول)
  9. Create repository
# Clone روی سیستم خود
git clone https://github.com/USERNAME/todo-app.git
cd todo-app

# remote خودکار به نام origin اضافه می‌شود
git remote -v
# origin  https://github.com/USERNAME/todo-app.git (fetch)
# origin  https://github.com/USERNAME/todo-app.git (push)

روش ۲: اول local، بعد به GitHub

# شروع از پروژه local
mkdir my-project
cd my-project
git init
echo "# My Project" > README.md
git add .
git commit -m "Initial commit"

# در GitHub repo بسازید (بدون README و .gitignore - چون از قبل دارید)

# اضافه کردن remote
git remote add origin https://github.com/USERNAME/my-project.git

# تعیین branch اصلی
git branch -M main

# اولین push
git push -u origin main

احراز هویت با SSH Key

HTTPS هر بار password می‌خواهد. SSH key راحت‌تر و امن‌تر است:

۱. ساخت SSH key

# Linux/Mac/Git Bash در ویندوز
ssh-keygen -t ed25519 -C "you@example.com"

# اگر سیستم قدیمی است که ed25519 را پشتیبانی نمی‌کند:
ssh-keygen -t rsa -b 4096 -C "you@example.com"

# Enter file: (Enter بزنید برای پیش‌فرض ~/.ssh/id_ed25519)
# Enter passphrase: (می‌توانید خالی بگذارید یا رمز اضافی بدهید)

۲. افزودن کلید به ssh-agent

# شروع agent
eval "$(ssh-agent -s)"

# افزودن کلید
ssh-add ~/.ssh/id_ed25519

۳. کپی کلید عمومی

# Linux
cat ~/.ssh/id_ed25519.pub
# سپس copy کنید

# Mac
pbcopy < ~/.ssh/id_ed25519.pub

# Windows (Git Bash)
clip < ~/.ssh/id_ed25519.pub

۴. افزودن به GitHub

  1. GitHub → Settings → SSH and GPG keys
  2. New SSH key
  3. Title: نام دستگاه (مثلاً “Work Laptop”)
  4. Key: کلید عمومی را paste کنید
  5. Add SSH key

۵. تست اتصال

ssh -T git@github.com
# Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.

تغییر URL از HTTPS به SSH

# بررسی URL فعلی
git remote -v
# origin  https://github.com/USERNAME/repo.git

# تغییر به SSH
git remote set-url origin git@github.com:USERNAME/repo.git

# تأیید
git remote -v
# origin  git@github.com:USERNAME/repo.git

git clone – دانلود یک repository

# Clone از HTTPS
git clone https://github.com/django/django.git

# Clone از SSH
git clone git@github.com:django/django.git

# Clone با نام پوشه دیگر
git clone https://github.com/django/django.git my-django

# Clone فقط یک branch خاص
git clone --branch develop https://github.com/USER/repo.git

# Shallow clone (فقط commit‌های اخیر - برای پروژه‌های بزرگ)
git clone --depth 1 https://github.com/torvalds/linux.git

# Clone یک ریپو با همه submodule‌هایش
git clone --recurse-submodules https://github.com/USER/repo.git

دستورات Remote

# لیست remote‌ها
git remote
# origin

# با URL
git remote -v
# origin  git@github.com:USER/repo.git (fetch)
# origin  git@github.com:USER/repo.git (push)

# اطلاعات کامل یک remote
git remote show origin

# افزودن remote جدید
git remote add upstream https://github.com/ORIGINAL/repo.git

# تغییر URL
git remote set-url origin git@github.com:USER/new-repo.git

# تغییر نام
git remote rename origin github

# حذف remote
git remote remove upstream

git push – فرستادن به Remote

# push branch فعلی به remote
git push

# اگر branch محلی tracking نشده با remote (اولین push)
git push -u origin main
# -u یعنی: این branch را با origin/main link کن، تا دفعات بعدی فقط git push بزنیم

# push همه branch‌ها
git push --all

# push همه tag‌ها
git push --tags

# push با یک branch به branch دیگر در remote
git push origin local-branch:remote-branch-name

# حذف branch روی remote
git push origin --delete feature-old

# force push (خطرناک!)
git push --force
git push --force-with-lease           # کمی امن‌تر
هشدار: git push --force تاریخچه remote را بازنویسی می‌کند و کار همکاران را خراب می‌کند. فقط روی branch‌های شخصی استفاده کنید. --force-with-lease امن‌تر است چون اول چک می‌کند کسی push نکرده باشد.

git fetch vs git pull

این دو متفاوت‌اند. تفاوت را بدانید!

git fetch

تغییرات remote را فقط دانلود می‌کند، اما در branch محلی شما merge نمی‌کند:

git fetch origin
# تغییرات remote در origin/main می‌نشینند
# اما main محلی دست‌نخورده می‌ماند

# حالا می‌توانید چک کنید چه تغییری آمده
git log main..origin/main         # commit‌های جدید در remote
git diff main origin/main         # تغییرات
git log --oneline --graph --all   # نمایش گرافیکی

# اگر راضی بودید، merge کنید
git merge origin/main

git pull

git pull = git fetch + git merge (یا rebase) – یعنی دانلود + ادغام در یک قدم:

git pull origin main
# = git fetch origin && git merge origin/main

# با rebase به‌جای merge
git pull --rebase origin main

# تنظیم default
git config --global pull.rebase true        # همیشه rebase
git config --global pull.rebase false       # همیشه merge (default)
git config --global pull.ff only            # فقط fast-forward
توصیه: در پروژه‌های تیمی، git fetch را بیشتر استفاده کنید تا قبل از ادغام، تغییرات را ببینید. git pull سریع است اما گاهی غافلگیرتان می‌کند.

Tracking Branches

وقتی git push -u می‌زنید، branch محلی به remote متصل می‌شود:

# بررسی tracking
git branch -vv
# * main      a3f4b2c [origin/main] Latest commit
#   feature   b2c3d4e [origin/feature: ahead 2] Add new feature

# ahead 2: شما 2 commit جلوتر از remote هستید
# behind 3: شما 3 commit عقب‌ترید
# diverged: هر دو طرف تغییرات جداگانه دارند

# تنظیم tracking
git branch --set-upstream-to=origin/main main
git branch -u origin/main

# حذف tracking
git branch --unset-upstream

جریان کاری روزمره

# 1. شروع روز - گرفتن آخرین تغییرات
git switch main
git pull

# 2. ساخت branch جدید
git switch -c feature/add-search

# 3. کار + commit
echo "..." > search.py
git add .
git commit -m "feat: add search functionality"

# 4. push به remote (اولین بار)
git push -u origin feature/add-search

# 5. ادامه کار - commit‌های بعدی
git add .
git commit -m "fix: handle empty search query"
git push                            # حالا فقط git push کافی است

# 6. در GitHub: Pull Request باز کنید (فصل بعد)

Conflict هنگام pull

git pull origin main
# Auto-merging app.py
# CONFLICT (content): Merge conflict in app.py

# 1. حل conflict (مثل فصل قبل)
nano app.py

# 2. add و commit
git add app.py
git commit                          # پیام merge آماده می‌شود

# 3. push
git push

گزینه: rebase به‌جای merge

git pull --rebase origin main

# اگر conflict شد:
# 1. حل کنید
git add resolved-file.py

# 2. ادامه rebase
git rebase --continue

# یا لغو
git rebase --abort

Protected Branches

در GitHub می‌توانید branch‌های مهم را محافظت کنید (Settings → Branches):

  • Require pull request before merging: نمی‌توان مستقیم push کرد
  • Require approvals: حداقل N نفر تأیید کنند
  • Require status checks: تست‌ها قبول شوند
  • Require signed commits
  • Require linear history: نه merge commit
  • Restrict who can push

مثال کامل: همکاری روی پروژه

# --- روز اول ---
# 1. Clone پروژه تیم
git clone git@github.com:team/project.git
cd project

# 2. ساخت branch فیچر
git switch -c feature/user-profile

# 3. توسعه
# ...
git add .
git commit -m "feat: add user profile page"
git push -u origin feature/user-profile

# 4. در GitHub: Pull Request باز کنید
# 5. منتظر review

# --- روز دوم - تغییرات review ---
# اعمال feedback
git add .
git commit -m "fix: address review comments"
git push

# --- روز سوم - main تغییر کرده ---
# همگام‌سازی
git switch main
git pull
git switch feature/user-profile
git merge main                       # یا git rebase main
# (حل conflict اگر هست)
git push

# --- بعد از merge شدن PR ---
git switch main
git pull
git branch -d feature/user-profile          # حذف local
git push origin --delete feature/user-profile  # حذف remote (یا GitHub خودکار حذف می‌کند)

چند Remote

سناریو: شما fork یک پروژه را clone کرده‌اید و می‌خواهید با اصلی هم sync باشید:

# Clone از fork خود
git clone git@github.com:YOUR-USERNAME/django.git
cd django

# remote اصلی پروژه را اضافه کنید (به عنوان upstream)
git remote add upstream https://github.com/django/django.git

git remote -v
# origin    git@github.com:YOUR-USERNAME/django.git (fetch)
# origin    git@github.com:YOUR-USERNAME/django.git (push)
# upstream  https://github.com/django/django.git    (fetch)
# upstream  https://github.com/django/django.git    (push)

# گرفتن تغییرات از اصلی
git fetch upstream
git switch main
git merge upstream/main           # یا git rebase upstream/main
git push origin main              # به‌روز کردن fork شما

بهترین شیوه‌ها

  • SSH به‌جای HTTPS (راحت‌تر، امن‌تر)
  • قبل از شروع کار: git pull
  • قبل از push: یک git pull دیگر برای جلوگیری از conflict
  • هرگز روی main کسی دیگر force-push نکنید
  • --force-with-lease به‌جای --force
  • main را protected کنید در پروژه‌های تیمی
  • commit‌ها را زود push کنید (backup در GitHub)
  • secrets را push نکنید! (.env در .gitignore)
  • اگر اشتباهاً secret push شد: rotate کنید + git filter-branch یا BFG

جمع‌بندی

  • Remote نسخه‌ای از repo روی سرور است
  • SSH key برای احراز هویت بهتر از HTTPS
  • git clone: کپی یک repo از remote
  • git push: ارسال commit‌ها
  • git fetch: دانلود + بدون merge
  • git pull: fetch + merge
  • Tracking branch: link بین local و remote
  • Protected branches: امنیت در پروژه‌های تیمی
  • چند remote: برای fork و upstream

در فصل بعد، Fork و Pull Request – راه استاندارد همکاری در پروژه‌های open-source.

نمایش سایت

رنگ سایت
حالت نمایش
اندازهٔ متن
خوانایی

این تنظیمات فقط روی مرورگر شما ذخیره می‌شود.