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

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

قبل از شروع: چه چیزی نباید در مخزن باشد#

استقرار با گیت فقط وقتی امن است که چیزهای حساس وارد مخزن نشده باشند. فایل .gitignore پروژه باید دست‌کم این‌ها را ببندد:

Bash
.env
vendor/
node_modules/
storage/logs/*
wp-config.php
wp-content/uploads/

آپلودهای کاربران و فایل تنظیمات واقعی روی سرور می‌مانند و در مخزن نیستند. اگر پروژه‌تان لاراول است، پیش از ادامه لاراول در public_html و htaccess و چک‌لیست هاست اشتراکی برای لاراول را هم نگاه کنید.

دو روش رایج#

روشنیازمزیتایراد
۱. push به مخزن bare و hookSSHاستقرار با یک push، بدون نیاز به دسترسی مخزن از سمت سرورساخت اولیه کمی کار دارد
۲. git pull روی سرورSSH یا ابزار Git کنترل‌پنلساده‌ترین مسیرسرور باید به مخزن دسترسی بخواند

روش اول تمیزتر است و این‌جا مفصل‌تر توضیح داده می‌شود.

روش اول: مخزن bare و hook پس از push#

ایده این است که روی هاست یک مخزن «برهنه» (فقط تاریخچه، بدون فایل‌های کار) بسازید. وقتی از کامپیوتر خودتان به آن push می‌کنید، یک hook فایل‌های آخرین نسخه را در پوشه‌ی سایت بیرون می‌ریزد.

۱. ساخت مخزن روی سرور#

از طریق SSH به هاست وصل شوید. مخزن را بیرون از پوشه‌ی عمومی بسازید:

Bash
mkdir -p ~/repos/site.git
cd ~/repos/site.git
git init --bare --initial-branch=main

۲. نوشتن hook#

فایل hooks/post-receive را بسازید. این اسکریپت فقط وقتی شاخه‌ی main push شود، فایل‌ها را در پوشه‌ی سایت قرار می‌دهد:

Bash
cat > ~/repos/site.git/hooks/post-receive <<'EOF'
#!/bin/bash
set -euo pipefail

TARGET="$HOME/public_html"
GIT_DIR="$HOME/repos/site.git"

while read -r oldrev newrev ref; do
  if [ "$ref" = "refs/heads/main" ]; then
    echo "Deploying main to $TARGET"
    git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f main

    cd "$TARGET"
    if [ -f composer.json ]; then
      composer install --no-dev --optimize-autoloader --no-interaction
    fi
  fi
done
EOF
chmod +x ~/repos/site.git/hooks/post-receive

چند نکته درباره‌ی این اسکریپت:

  • set -euo pipefail اجرا را در اولین خطا متوقف می‌کند و استقرار نیمه‌کاره را کم می‌کند.
  • checkout -f فایل‌های ردیابی‌شده را رونویسی می‌کند، ولی فایل‌هایی که در مخزن نیستند (مثل .env و آپلودها) را پاک نمی‌کند.
  • اگر composer روی هاست در دسترس نیست یا توابع لازمش بسته است، وابستگی‌ها را روی کامپیوتر خودتان نصب و فقط همان نتیجه را منتقل کنید؛ بخشی از آن در توابع بسته‌ی PHP روی هاست اشتراکی آمده است.

۳. اتصال و اولین push#

روی کامپیوتر خودتان، مخزن سرور را به‌عنوان remote اضافه کنید. آدرس را با اطلاعات واقعی هاستتان جایگزین کنید:

Bash
git remote add production ssh://USER@HOST/home/USER/repos/site.git
git push production main

از این به بعد هر بار git push production main سایت را به‌روز می‌کند. برای ورود، از کلید SSH استفاده کنید نه رمز حساب هاست.

روش دوم: git pull روی سرور#

اگر مخزن شما در یک سرویس مثل گیت‌هاب است و می‌خواهید سرور آن را بکشد، در پوشه‌ی پروژه یک بار git clone و بعد هر بار به‌روزرسانی انجام دهید:

Bash
cd ~/public_html
git fetch origin
git reset --hard origin/main

برای این‌که سرور به مخزن خصوصی دسترسی داشته باشد، از Deploy key استفاده کنید: یک جفت کلید SSH مخصوص همین سرور بسازید، بخش عمومی را در تنظیمات مخزن به‌عنوان کلید فقط‌خواندنی اضافه کنید و بخش خصوصی را فقط روی همان سرور نگه دارید. به این ترتیب اگر هاست آلوده شد، مهاجم نمی‌تواند در مخزن بنویسد. به‌جای git reset --hard که تغییرهای دستی روی سرور را دور می‌اندازد، بهتر است اصلاً روی سرور کد را دستی ویرایش نکنید.

بعضی کنترل‌پنل‌ها هم ابزار Git داخلی دارند که همین کار را با رابط گرافیکی انجام می‌دهد؛ اگر هاستتان دارد، همان را بخوانید و گزینه‌ها را از مستندات خود هاست ببینید.

پنهان‌کردن پوشه‌ی .git#

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

Apache
RedirectMatch 404 /\.git

بعد در مرورگر آدرس https://example.com/.git/config را امتحان کنید؛ باید خطای ۴۰۴ یا ۴۰۳ بگیرید، نه محتوای فایل.

بعد از استقرار#

  • کش را پاک کنید. در لاراول php artisan config:cache و در وردپرس پاک‌کردن افزونه‌ی کش لازم است، وگرنه تغییرها دیده نمی‌شوند.
  • مایگریشن دیتابیس را جدا و با احتیاط اجرا کنید. قبلش پشتیبان بگیرید؛ بک‌آپ خودکار دیتابیس در این‌جا به کار می‌آید.
  • برچسب نسخه بزنید. git tag release-checkout-fix کمک می‌کند بدانید چه چیزی کی مستقر شد.

خلاصه#

  • استقرار با گیت، سایت را به یک کامیت مشخص وصل می‌کند و برگشت را ممکن می‌سازد.
  • روش push به مخزن bare و hook، تمیزترین راه روی هاستی با SSH است.
  • رمزها، .env و آپلودها نباید در مخزن باشند.
  • از Deploy key فقط‌خواندنی استفاده کنید و رمز حساب هاست را در اسکریپت نگذارید.
  • مخزن را بیرون پوشه‌ی عمومی نگه دارید یا دسترسی به .git را ببندید و با مرورگر امتحان کنید.
  • پیش از هر تغییر دیتابیس پشتیبان بگیرید.