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

گیت‌هاب (GitHub) و سرویس‌های مشابه مثل GitLab چیز دیگری‌اند: جایی برای نگه‌داشتن نسخه‌ی مشترک مخزن روی اینترنت، به‌همراه امکاناتی مثل Pull Request، بررسی کد و CI. گیت ابزار است و روی سیستم خودتان اجرا می‌شود؛ گیت‌هاب میزبانی است که مخزن گیت شما را نگه می‌دارد. در ادامه دستورات مهم گیت را به ترتیبی که در کار روزمره به آن‌ها نیاز پیدا می‌کنید مرور می‌کنیم.

پیش از شروع: نصب و معرفی خودتان

روی Ubuntu 24.04 گیت با یک دستور نصب می‌شود. بعد باید نام و ایمیلتان را تنظیم کنید، چون روی هر commit ثبت می‌شوند:

bash
sudo apt install git
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

خط آخر باعث می‌شود شاخه‌ی اصلی مخزن‌های تازه main نام بگیرد، که امروز رایج‌ترین نام است.

سه بخش گیت را بشناسید

بیشتر سردرگمی‌های گیت از نشناختن این سه بخش است:

  • پوشه‌ی کاری (working tree): فایل‌هایی که می‌بینید و ویرایش می‌کنید.
  • ناحیه‌ی آماده‌سازی (staging area یا index): تغییراتی که برای commit بعدی انتخاب کرده‌اید.
  • مخزن (repository): تاریخچه‌ی commitها که در پوشه‌ی .git نگه‌داری می‌شود.

چرخه‌ی کار همیشه همین است: فایل را عوض می‌کنید، با add آن را به staging می‌برید و با commit در تاریخچه ثبتش می‌کنید.

دستورات روزمره‌ی گیت

شروع پروژه: init یا clone

اگر پروژه از صفر شروع می‌شود، داخل پوشه‌اش مخزن بسازید:

bash
mkdir my-project && cd my-project
git init

اگر مخزن از قبل جایی مثل گیت‌هاب وجود دارد، آن را کپی کنید. این کار کل تاریخچه را می‌آورد و remote به نام origin را هم خودکار تنظیم می‌کند:

bash
git clone git@github.com:user/my-project.git

status: همیشه اول ببینید کجایید

bash
git status

این دستور می‌گوید روی کدام شاخه‌اید، کدام فایل‌ها تغییر کرده‌اند، کدام‌ها در staging هستند و کدام‌ها هنوز اصلاً زیر نظر گیت نیستند. عادت خوبی است پیش از هر add و commit یک بار اجرایش کنید.

add و commit: ثبت یک قدم

bash
git add index.php          # یک فایل
git add src/               # یک پوشه
git add -p                 # تکه‌به‌تکه، با پرسیدن درباره‌ی هر تغییر
git commit -m "Validate email before saving the contact form"

git add -p کمتر شناخته شده اما بسیار مفید است: وقتی در یک فایل دو کار نامرتبط کرده‌اید، می‌توانید هر کدام را در commit جدا ثبت کنید.

پیام commit را برای کسی بنویسید که یک سال بعد آن را می‌خواند: چه چیزی عوض شد و چرا. «fix» و «update» چیزی به او نمی‌گویند.

log و diff: دیدن تاریخچه و تفاوت‌ها

bash
git log --oneline            # هر commit در یک خط
git log --oneline --graph    # همراه با نمودار شاخه‌ها
git diff                     # تغییراتی که هنوز add نشده‌اند
git diff --staged            # تغییراتی که add شده‌اند و در commit بعدی می‌روند
git diff main..feature       # تفاوت دو شاخه

پیش از هر commit یک git diff --staged بزنید. بارها جلوی رفتن یک dd() یا رمز آزمایشی به مخزن را می‌گیرد.

branch و switch: کار موازی بدون دردسر

شاخه (branch) یک خط کار جداست. برای هر قابلیت یا رفع باگ یک شاخه بسازید تا main همیشه سالم بماند:

bash
git branch                    # فهرست شاخه‌ها
git switch -c feature/login   # ساخت شاخه‌ی تازه و رفتن به آن
git switch main               # برگشت به main
git branch -d feature/login   # حذف شاخه‌ای که merge شده

دستور switch در نسخه‌های جدید گیت جای کاربرد شاخه‌ای checkout را گرفته و خواناتر است. checkout هنوز کار می‌کند، اما چند کار متفاوت انجام می‌دهد و همین آن را گیج‌کننده می‌کند.

merge: یکی‌کردن شاخه‌ها

وقتی کار روی شاخه تمام شد، به main برگردید و آن را merge کنید:

bash
git switch main
git merge feature/login

اگر هر دو شاخه یک خط از یک فایل را عوض کرده باشند، conflict پیش می‌آید. گیت فایل را با نشانه‌های <<<<<<<، ======= و >>>>>>> علامت می‌زند؛ آن را دستی درست کنید، نشانه‌ها را پاک کنید و بعد:

bash
git add path/to/file
git commit

remote، push و pull: کار با گیت‌هاب

bash
git remote -v                                         # remoteهای تعریف‌شده
git remote add origin git@github.com:user/repo.git   # افزودن remote به مخزنی که با init ساخته‌اید
git push -u origin main                               # اولین push و وصل‌کردن شاخه به origin
git push                                              # pushهای بعدی
git pull                                              # گرفتن و ادغام تغییرات دیگران

git pull در واقع دو کار است: fetch (گرفتن تغییرات) و بعد merge آن‌ها. اگر می‌خواهید اول ببینید چه چیزی آمده، git fetch بزنید و با git log --oneline main..origin/main آن را مرور کنید.

برای اتصال به گیت‌هاب با آدرس‌های git@github.com:… به کلید SSH نیاز دارید؛ ساختنش را در کلید SSH و اتصال به سرور توضیح داده‌ایم.

برگرداندن تغییرات، بدون از دست دادن کار

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

restore: دور ریختن تغییرات یک فایل

bash
git restore index.php            # برگرداندن فایل به آخرین commit (تغییرات پاک می‌شوند)
git restore --staged index.php   # بیرون آوردن از staging؛ تغییرات در فایل می‌مانند

دقت کنید: git restore بدون --staged تغییرات commit‌نشده را برای همیشه پاک می‌کند و گیت راهی برای برگرداندنشان ندارد.

reset --soft در برابر reset --hard

فرض کنید commit آخر را زود زدید و می‌خواهید پیامش را عوض کنید یا فایلی به آن اضافه کنید:

bash
git reset --soft HEAD~1

commit حذف می‌شود اما همه‌ی تغییراتش در staging باقی می‌مانند. کاملاً امن است.

اما این یکی را با احتیاط بزنید:

bash
git reset --hard HEAD~1

--hard هم commit را حذف می‌کند، هم همه‌ی تغییرات commit‌نشده‌ی پوشه‌ی کاری را دور می‌ریزد. دو قاعده:

  • پیش از reset --hard یک git status بزنید و مطمئن شوید چیزی commit‌نشده ندارید که لازمش دارید.
  • روی commitهایی که push کرده‌اید reset نزنید. تاریخچه‌ی شما با نسخه‌ی دیگران ناسازگار می‌شود و برای push مجبور به --force می‌شوید که کار دیگران را پاک می‌کند.

اگر commitی را با reset از دست دادید، git reflog فهرست جاهایی را که HEAD اخیراً بوده نشان می‌دهد و معمولاً می‌شود از آنجا برش گرداند.

revert: راه امن برای commitهای push‌شده

revert تاریخچه را پاک نمی‌کند؛ یک commit تازه می‌سازد که دقیقاً اثر commit قبلی را خنثی می‌کند:

bash
git log --oneline
git revert a1b2c3d
git push

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

stash: کنار گذاشتن موقت کار نیمه‌تمام

وسط کارید و باید سریع به شاخه‌ی دیگری بروید:

bash
git stash push -m "half-done login form"
git switch main
# ... کار فوری ...
git switch feature/login
git stash pop

git stash list همه‌ی موارد کنارگذاشته را نشان می‌دهد. stash را انبار بلندمدت نکنید؛ اگر کار بیش از یک روز طول می‌کشد، یک commit موقت روی شاخه‌ی خودش امن‌تر است.

فایل gitignore: چه چیزهایی نباید در مخزن برود

فایل .gitignore در ریشه‌ی پروژه به گیت می‌گوید کدام فایل‌ها را نادیده بگیرد. برای یک پروژه‌ی Laravel نمونه‌ی معقولی این است:

.gitignore
# وابستگی‌ها؛ با composer و npm دوباره ساخته می‌شوند
/vendor/
/node_modules/

# اطلاعات محرمانه و تنظیمات محلی
.env
.env.*
!.env.example

# خروجی‌ها و فایل‌های موقت
/public/build/
/storage/*.key
*.log

# فایل‌های ویرایشگر و سیستم‌عامل
.idea/
.vscode/
.DS_Store

دو نکته‌ی مهم:

  • .gitignore فقط روی فایل‌هایی اثر دارد که هنوز track نشده‌اند. اگر .env قبلاً commit شده، باید با git rm --cached .env از مخزن بیرونش بیاورید.
  • اگر رمز یا کلیدی یک بار commit و push شده، حذفش از commit بعدی کافی نیست؛ در تاریخچه باقی است. آن رمز را عوض کنید.

جدول خلاصه‌ی دستورات گیت

کار دستور
ساخت مخزن تازه git init
کپی مخزن موجود git clone <url>
دیدن وضعیت git status
افزودن به staging git add <file> یا git add -p
ثبت commit git commit -m "پیام"
تاریخچه‌ی خلاصه git log --oneline --graph
تغییرات add‌نشده / add‌شده git diff / git diff --staged
ساخت و رفتن به شاخه git switch -c <name>
رفتن به شاخه‌ی موجود git switch <name>
ادغام شاخه در شاخه‌ی فعلی git merge <name>
فهرست و افزودن remote git remote -v / git remote add origin <url>
فرستادن و گرفتن git push / git pull
دور ریختن تغییرات یک فایل git restore <file>
بیرون آوردن از staging git restore --staged <file>
لغو commit آخر، حفظ تغییرات git reset --soft HEAD~1
لغو commit و حذف تغییرات (خطرناک) git reset --hard HEAD~1
خنثی‌کردن commit push‌شده git revert <hash>
کنار گذاشتن و برگرداندن کار git stash push / git stash pop
پیدا کردن commit گم‌شده git reflog

جمع‌بندی

برای کار روزمره با گیت به ده‌دوازده دستور بیشتر نیاز ندارید: status، add، commit، log، diff، switch، merge، pull و push. آنچه گیت‌کار مطمئن را از تازه‌کار جدا می‌کند، شناختن راه‌های برگشت است: restore و reset --soft برای کار محلی، revert برای چیزی که push شده، و احتیاط همیشگی با reset --hard. commitهای کوچک با پیام روشن بزنید، برای هر کار شاخه بسازید و .env را از همان روز اول در .gitignore بگذارید.

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