یادتان هست آخرین باری که یک فایل را با FTP آپلود کردید و پنج دقیقه بعد فهمیدید که نسخه قدیمی را فرستاده‌اید؟ یا وقتی که یک همکار همزمان روی همان فایل کار می‌کرد و تغییراتش پاک شد؟ این‌ها واقعیت‌های دنیای FTP هستند. توسعه‌دهندگان حرفه‌ای امروز این مشکلات را با Git حل کرده‌اند — نه فقط برای مدیریت کد، بلکه برای استقرار (deployment) هم.

Git Deployment یعنی پل زدن بین کدنویسی و سرور. از ساده‌ترین حالت (git pull دستی) تا پیشرفته‌ترین روش (CI/CD کامل با GitHub Actions و zero-downtime deployment)، در این راهنما همه چیز را با جزئیات عملی بررسی می‌کنیم.

مشکل واقعی FTP چیست؟

FTP برای اواخر دهه ۹۰ طراحی شد. بعضی از مشکلاتش خیلی آشنا هستند:

  • خطای انسانی: ممکن است فایلی را فراموش کنید یا نسخه قدیمی آپلود کنید
  • عدم قابلیت ردیابی: نمی‌دانید چه تغییراتی کِی و توسط چه کسی اعمال شده
  • برگشت سخت: اگر آپدیت مشکل داشت، برگشت به نسخه قبلی دشوار است
  • کار تیمی مشکل: چند نفر نمی‌توانند به راحتی همزمان روی سرور کار کنند
  • امنیت پایین: FTP رمزگذاری ضعیفی دارد و credential ها در معرض خطر هستند
  • زمان‌بر: آپلود ده‌ها فایل یک به یک وقت زیادی می‌گیرد

جالب است که همه این مشکلات با یک ابزار حل می‌شوند: Git. اما چطور؟

Git چطور استقرار را متحول می‌کند؟

با Git Deployment:

  • تمام تغییرات ردیابی می‌شوند — چه کسی، چه وقت، چه چیزی تغییر داده
  • rollback به هر نسخه قبلی با یک دستور انجام می‌شود
  • استقرار با push کردن به یک branch خاص انجام می‌شود
  • می‌توانید قبل از استقرار، تست‌های خودکار اجرا کنید
  • محیط‌های staging و production جداگانه دارید
  • کار تیمی با branch ها و pull request ها سازماندهی می‌شود

روش‌های Git Deployment

۱. git pull دستی

ساده‌ترین روش: SSH به سرور وصل می‌شوید و git pull اجرا می‌کنید. این روش هنوز دستی است اما نسبت به FTP مزایای زیادی دارد: فقط فایل‌های تغییر کرده دانلود می‌شوند، تاریخچه تغییرات حفظ می‌شود و rollback با یک دستور ممکن است. مناسب برای پروژه‌های کوچک یا تیم‌های یک نفره که می‌خواهند سریع شروع کنند.

۲. Git Hooks

Git Hooks اسکریپت‌هایی هستند که در رویدادهای خاص Git اجرا می‌شوند. post-receive hook بعد از هر push به سرور اجرا می‌شود و می‌توانید deployment را در آن قرار دهید. این روش automation واقعی می‌دهد بدون نیاز به سرویس‌های خارجی — فقط Git و یک اسکریپت shell.

۳. CI/CD پیشرفته

سرویس‌هایی مثل GitHub Actions، GitLab CI یا Jenkins فرایند deployment را کاملاً خودکار می‌کنند. مراحل معمول یک pipeline CI/CD:

  1. Push به branch
  2. اجرای تست‌های خودکار
  3. بررسی کیفیت کد (linting)
  4. build کردن assets
  5. استقرار روی staging
  6. تست‌های integration
  7. استقرار روی production

۴. ابزارهای اختصاصی Deployment

ابزارهایی مثل Deployer.org، Capistrano یا Laravel Envoyer برای deployment حرفه‌ای طراحی شده‌اند. مزیت اصلی‌شان zero-downtime deployment، نگه داشتن چند نسخه برای rollback سریع و اجرای tasks موازی روی چند سرور است.

راه‌اندازی Git Hook: گام به گام

مرحله ۱: ساخت Bare Repository روی سرور

یک bare repository فایل‌های working directory ندارد و فقط تاریخچه Git را نگه می‌دارد. این حالت ایده‌آل برای سرور مرکزی است:

  • git init --bare /home/user/myproject.git

مرحله ۲: نوشتن post-receive Hook

فایل /home/user/myproject.git/hooks/post-receive را بسازید. یک نمونه ساده برای استقرار لاراول:

  • GIT_WORK_TREE=/var/www/mysite git checkout -f main
  • cd /var/www/mysite
  • composer install --optimize-autoloader --no-dev
  • php artisan migrate --force
  • php artisan optimize

بعد از نوشتن، فایل را اجرایی کنید: chmod +x hooks/post-receive

مرحله ۳: اضافه کردن Remote در محیط توسعه

در کامپیوتر local خود، سرور را به عنوان remote اضافه کنید:

  • git remote add production user@yourserver.com:/home/user/myproject.git

مرحله ۴: Deploy کردن

از این پس deployment به این سادگی است:

  • git push production main

Git کد را به سرور می‌فرستد، hook اجرا می‌شود و تمام مراحل (checkout، composer، migrate، optimize) به صورت خودکار انجام می‌شود.

GitHub Actions: CI/CD مدرن

GitHub Actions یکی از محبوب‌ترین راه‌حل‌های CI/CD است و برای repository های GitHub رایگان است (تا حد مشخصی). برای راه‌اندازی، فایل .github/workflows/deploy.yml بسازید.

اتصال SSH امن به سرور

برای اتصال ایمن از GitHub Actions به سرور:

  1. یک SSH key pair بسازید: ssh-keygen -t ed25519 -C "github-actions"
  2. public key را به سرور اضافه کنید: فایل ~/.ssh/authorized_keys
  3. private key را در GitHub Secrets ذخیره کنید (Settings → Secrets)
  4. در workflow با secrets.SSH_PRIVATE_KEY استفاده کنید

ساختار یک Workflow معمول

یک workflow تیپیک برای deployment به سرور شامل این مراحل است:

  • checkout کد با actions/checkout
  • نصب PHP و Node.js با نسخه مناسب
  • اجرای composer install و npm install
  • اجرای تست‌ها — اگر fail شد، deployment انجام نمی‌شود
  • build کردن assets با npm run build
  • اتصال SSH به سرور
  • اجرای git pull، composer install، php artisan migrate و php artisan optimize

مزیت بزرگ این روش این است که اگر تست‌ها fail کنند، کد هرگز به سرور نمی‌رسد.

Zero-Downtime Deployment

روش atomic deployment یا symlink switching یکی از بهترین روش‌های zero-downtime deployment است که سایت یک لحظه هم down نمی‌شود.

چطور کار می‌کند؟

  1. نسخه جدید در یک پوشه جدید (مثل releases/20240115_143022) deploy می‌شود
  2. تمام مراحل (composer install، migrate، optimize) در پوشه جدید انجام می‌شود
  3. یک symlink به نام current به پوشه جدید اشاره می‌کند — این لحظه‌ای است، سایت یک frame هم قطع نمی‌شود
  4. پوشه‌های قبلی برای rollback نگه داشته می‌شوند (معمولاً ۵ نسخه آخر)

Deployer.org این pattern را به صورت آماده پیاده می‌کند و برای لاراول، Symfony و WordPress رسپی‌های از پیش آماده دارد.

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

مدیریت فایل‌های حساس

فایل .env، فایل‌های حاوی credential و کلیدهای SSH هرگز نباید در git باشند. آن‌ها را در .gitignore قرار دهید و روی سرور به صورت جداگانه مدیریت کنید. از GitHub Secrets یا Vault برای مدیریت credential های CI/CD استفاده کنید. یک بار دیدن .env در تاریخچه git کافی است تا بفهمید چرا این قانون اینقدر مهم است.

Branch Strategy

یک استراتژی branch مشخص داشته باشید:

  • GitHub Flow: ساده — main و feature branch ها. مناسب برای تیم‌های کوچک با deployment مداوم
  • Gitflow: feature، develop، release و main جداگانه. مناسب برای پروژه‌هایی با release cycle مشخص
  • Trunk-based: همه در main commit می‌کنند با feature flags. مناسب برای تیم‌های بزرگ با CI/CD قوی

تست قبل از Deploy

قبل از هر deployment، حداقل این تست‌ها باید اجرا شوند:

  • Unit tests و Integration tests
  • بررسی syntax برای PHP: php -l filename.php
  • اطمینان از اینکه لاگ‌های CI warning ندارند

Rollback آماده داشته باشید

همیشه باید بتوانید به نسخه قبلی برگردید. راه‌های مختلف:

  • با git: git revert HEAD و دوباره deploy کنید
  • با symlink: symlink را به پوشه نسخه قبلی برگردانید — یک دستور، سریع‌ترین rollback ممکن
  • با Deployer: دستور dep rollback production تمام کار را می‌کند

Migration های دیتابیس در Deployment

یک نکته که خیلی‌ها نادیده می‌گیرند: migration های دیتابیس باید backward compatible باشند. یعنی migration جدید نباید کاری کند که نسخه قبلی کد crash کند. برای تغییرات بزرگ دیتابیس، از روش expand-contract استفاده کنید: اول ستون جدید اضافه کنید (بدون حذف قدیمی)، بعد کد جدید deploy کنید، بعد ستون قدیمی را حذف کنید.

سوالات متداول

Git Hook یا GitHub Actions، کدام بهتر است؟

Git Hook ساده‌تر است و به سرویس خارجی نیاز ندارد، اما تست‌های پیچیده را نمی‌توانید اجرا کنید و مدیریت multiple server دشوار است. GitHub Actions قدرتمندتر است — تست، build و deploy همه یکجا انجام می‌شود. برای شروع و پروژه‌های کوچک، Git Hook کافی است؛ با بزرگ‌تر شدن پروژه به CI/CD کامل بروید.

چطور assets (CSS و JavaScript) را در deployment مدیریت کنم؟

دو رویکرد وجود دارد: build در CI/CD (npm run build را در pipeline اجرا کنید و output را به سرور کپی کنید) یا build کردن مستقیم روی سرور (اما این به نصب Node.js روی سرور نیاز دارد). رویکرد اول بهتر است چون پوشه dist را در git نگه نمی‌دارید و سرور production به Node.js نیاز ندارد.

اگر deploy شکست خورد چه کار کنم؟

وحشت نکنید. مراحل: اول لاگ‌های CI را بررسی کنید. مشکل را شناسایی کنید. اگر deployment ناقص بود، rollback کنید. مشکل را fix کنید، تست کنید و دوباره deploy کنید. برای جلوگیری از این وضعیت، staging environment داشته باشید و ابتدا روی staging deploy کنید — این ساده‌ترین راه برای کم کردن deployment failures در production است.

چطور database backup را قبل از migration در CI/CD بگیرم؟

در workflow خود، قبل از مرحله migration یک step اضافه کنید که از دیتابیس بکاپ می‌گیرد. برای MySQL: mysqldump -u user -p database > backup_$(date +%Y%m%d_%H%M%S).sql. این فایل را در یک storage ایمن ذخیره کنید. اگر migration مشکل داشت، می‌توانید از این بکاپ استفاده کنید.

جمع‌بندی

Git Deployment یک ضرورت برای هر پروژه جدی است، نه یک لوکس. از ساده‌ترین روش (git pull دستی) شروع کنید و به مرور به CI/CD کامل برسید. Git Hook برای پروژه‌های کوچک کافی است، GitHub Actions برای تیم‌ها و پروژه‌های متوسط عالی است، و ابزارهایی مثل Deployer.org برای نیازهای پیشرفته مثل zero-downtime deployment مناسب‌اند.

مهم‌ترین چیز این است که از همان ابتدا یک workflow مشخص داشته باشید، فایل‌های حساس را در git نگذارید، تست‌ها را اجرا کنید و همیشه امکان rollback داشته باشید. با گذر از FTP به Git Deployment، نه تنها سرعت استقرار بالا می‌رود، بلکه خواب راحت‌تری هم خواهید داشت — چون می‌دانید هر لحظه می‌توانید به نسخه سالم برگردید.