وراثت و چندریختی در جاوا (Inheritance و Polymorphism)
وراثت در جاوا یعنی یک کلاس با کلمه extends ویژگیها و رفتار کلاس دیگری را به ارث ببرد و فقط …
گیت سیستم کنترل نسخهای است که تاریخچه کامل پروژه را نگه میدارد و گیتهاب سرویسی آنلاین برای نگهداری مخزنها و همکاری تیمی است. در این آموزش از نصب و تنظیم گیت شروع میکنیم، با یک پروژه کوچک commit، branch، merge و حل تعارض را تمرین میکنیم و در پایان کد را به گیتهاب میفرستیم و یک Pull Request میسازیم.
آخرین بهروزرسانی: ۲۱ آبان ۱۴۰۵ — منابع بررسیشده در این روز: صفحه دانلود و کتاب Pro Git، مستندات git switch، git restore و gitignore، فهرست تغییرات ناسازگار گیت، معرفی Git 2.56 در وبلاگ گیتهاب، و مستندات Pull Request، SSH، توکن و قوانین تجاری گیتهاب.
⚡ پاسخ کوتاه
برای شروع گیت، بعد از نصب نام و ایمیل خود را با git config تنظیم کنید، در پوشه پروژه git init بزنید، تغییرات را با git add به Staging ببرید و با git commit ثبت کنید. برای هر قابلیت تازه با git switch -c شاخه بسازید و بعد با git merge ادغام کنید. برای همکاری، کد را با git push به گیتهاب بفرستید و Pull Request باز کنید. همه دستورها را با Git 2.56.1 اجرا کردهایم.
📑 فهرست مطالب
فرض کنید روی یک پروژه کار میکنید و بعد از چند روز تغییر، همه چیز خراب میشود. اگر نسخه سالم دیروز را نگه نداشته باشید، باید از حافظهتان کمک بگیرید. خیلیها برای حل این مشکل پوشههایی مثل «پروژه-نهایی» و «پروژه-نهایی-واقعا-آخر» میسازند. این روش زود به هم میریزد، مخصوصاً وقتی چند نفر روی یک پروژه کار کنند. گیت (Git) یک سیستم کنترل نسخه است. یعنی هر بار که بخواهید، از وضعیت پروژه یک عکس فوری میگیرد و همه این عکسها را با تاریخ، نویسنده و توضیح نگه میدارد. هر وقت لازم شد، میتوانید ببینید چه چیزی، کی و توسط چه کسی تغییر کرده و به هر نقطهای از گذشته برگردید. گیت توزیعشده است؛ یعنی هر نفر یک نسخه کامل از تاریخچه پروژه را روی سیستم خودش دارد و برای کار روزمره به اینترنت نیاز ندارد. گیت را لینوس توروالدز، سازنده لینوکس، در سال ۲۰۰۵ ساخت و امروز ابزار استاندارد کنترل نسخه در دنیای نرمافزار است. کتاب رایگان Pro Git در سایت رسمی گیت مرجع خوبی برای یادگیری عمیقتر است. در این آموزش، گیت را از صفر با یک پروژه کوچک تمرین میکنیم و بعد سراغ گیتهاب و Pull Request میرویم. همه دستورها را با Git 2.56.1 اجرا کردهایم.
این دو اسم شبیه هم هستند و خیلی از تازهکارها آنها را یکی میدانند. گیت ابزاری است که روی کامپیوتر شما نصب میشود و تاریخچه پروژه را مدیریت میکند. گیتهاب (GitHub) یک سرویس اینترنتی است که مخزنهای گیت را روی سرورهای خودش نگه میدارد و امکاناتی مثل Pull Request، بررسی کد، مدیریت مشکلات (Issues) و اجرای خودکار تستها را اضافه میکند. گیت بدون گیتهاب هم کار میکند، اما گیتهاب بدون گیت معنا ندارد. سرویسهای مشابه دیگری هم هستند؛ مهمترینشان GitLab است که هم نسخه آنلاین دارد و هم میشود آن را روی سرور خود سازمان نصب کرد. فرهنگ کاری تیم GitLab را در راهنمای GitLab Handbook و کار ریموت معرفی کردهایم.
| موضوع | گیت (Git) | گیتهاب (GitHub) |
|---|---|---|
| چیست؟ | نرمافزار کنترل نسخه | سرویس آنلاین میزبانی مخزن گیت |
| کجا اجرا میشود؟ | روی کامپیوتر شما | روی سرورهای گیتهاب |
| نیاز به اینترنت | برای کار روزمره ندارد | دارد |
| کار اصلی | ثبت تاریخچه، شاخه، ادغام | همکاری، Pull Request، بررسی کد، Actions |
| جایگزینها | Mercurial و SVN (کمتر رایج) | GitLab، Bitbucket، Gitea |
طبق صفحه قوانین تجاری گیتهاب، گیتهاب از وزارت خزانهداری آمریکا مجوز گرفته که سرویسهای ابریاش، چه رایگان و چه پولی، را به توسعهدهندگان ساکن ایران ارائه دهد. با این حال برخی محصولات مثل GitHub Copilot مشمول محدودیتهای صادراتی هستند و پرداخت از ایران هم مشکلهای خودش را دارد. پس ساخت حساب و کار با مخزنهای عمومی و خصوصی شدنی است، اما برای خدمات پولی پیش از اقدام قوانین تازه را بررسی کنید.
گیت را از صفحه دانلود رسمی گیت بگیرید. روی ویندوز، نصبکننده Git for Windows برنامه Git Bash را هم نصب میکند که ترمینال مناسبی برای دستورهای این آموزش است. روی مک میتوانید از Homebrew استفاده کنید و روی لینوکس از مدیر بسته توزیع خودتان. آخرین نسخه گیت در زمان نوشتن این مقاله 2.56 است که ۶ مهر ۱۴۰۵ (۲۸ سپتامبر ۲۰۲۶) منتشر شد. بعد از نصب، نسخه را بررسی کنید و نام و ایمیل خود را تنظیم کنید. این اطلاعات روی هر commit ثبت میشود:
git --version
git config --global user.name "Sara Ahmadi"
git config --global user.email "sara@example.com"
git config --global init.defaultBranch main
خط آخر اسم شاخه اصلی مخزنهای جدید را main میگذارد. اگر این را تنظیم نکنید، گیت هنوز اسم قدیمی master را استفاده میکند و پیامی نشان میدهد که این پیشفرض در Git 3.0 به main تغییر میکند. ما این پیام را در Git 2.56.1 دیدیم. فهرست تغییرات ناسازگار گیت هم تأیید میکند که در Git 3.0 اسم شاخه پیشفرض main خواهد بود، اما هنوز تاریخی برای انتشار آن تعیین نشده است. گیتهاب هم از قبل main را پیشفرض گذاشته؛ پس بهتر است از همین اول یکی باشند.
مهمترین مفهومی که باید در گیت بفهمید، این سه بخش است. اگر این را خوب بفهمید، نیمی از دستورها برایتان معنا پیدا میکنند. پوشه کاری (Working Directory) همان فایلهایی است که میبینید و ویرایش میکنید. ناحیه آمادهسازی (Staging Area) جایی است که تغییرات را برای commit بعدی انتخاب میکنید. مخزن (Repository) هم جایی است که commitها برای همیشه ذخیره میشوند و داخل پوشه پنهان .git قرار دارد. چرا staging لازم است؟ چون شاید در یک ساعت پنج فایل را عوض کرده باشید، اما فقط تغییر دو فایل به یک موضوع مربوط باشد. با staging میتوانید همان دو فایل را در یک commit با توضیح روشن ثبت کنید و بقیه را برای commit بعدی بگذارید. تاریخچه تمیز یعنی بعدها راحتتر بفهمید چه اتفاقی افتاده است.

یک پوشه برای پروژه بسازید و گیت را داخلش راه بیندازید:
mkdir my-site
cd my-site
git init
git init یک پوشه پنهان .git میسازد. از این لحظه گیت تغییرات این پوشه را زیر نظر دارد. حالا دو فایل میسازیم: README.md برای توضیح پروژه و .gitignore برای فایلهایی که نباید وارد گیت شوند.
بعضی فایلها نباید در تاریخچه ثبت شوند: رمزها و کلیدها، فایلهای موقت، پوشههای کتابخانه که دوباره ساخته میشوند و لاگها. اسم یا الگوی آنها را در .gitignore بنویسید. مستندات gitignore همه الگوهای مجاز را توضیح میدهد. یک نمونه ساده برای پروژه پایتون:
.env
__pycache__/
*.log
خیلی مهم است که فایل .env یا هر فایل حاوی رمز را از همان اول در .gitignore بگذارید. اگر رمزی یک بار commit شود، حتی اگر بعداً فایل را پاک کنید، در تاریخچه میماند. در آن صورت باید رمز را عوض کنید، نه فقط فایل را پاک کنید.
وضعیت پروژه را ببینید، فایلها را به staging ببرید و commit کنید:
git status --short
git add README.md .gitignore
git commit -m "Add README and gitignore"
در خروجی git status --short علامت ?? یعنی فایل هنوز زیر نظر گیت نیست. بعد از add و commit، گیت پیامی مثل این نشان میدهد: [main (root-commit) 4e0fdb5] Add README and gitignore. آن عدد و حروف کوتاه، شناسه commit است که برای هر commit یکتاست و روی سیستم شما عدد دیگری خواهد بود.
پیام commit باید بگوید این تغییر چه کاری انجام میدهد. پیامهایی مثل «fix» یا «update» یا «تغییرات» بعد از یک ماه هیچ کمکی نمیکنند. یک قاعده ساده: پیام را کوتاه و با فعل امری بنویسید، مثل Add login page یا Fix price rounding. هر commit هم بهتر است فقط یک کار انجام دهد. این همان نظمی است که در اصول کدنویسی تمیز برای خود کد هم توصیه میشود.
یک فایل دیگر اضافه و commit کنید، بعد تاریخچه را ببینید:
echo "<h1>Hello</h1>" > index.html
git add index.html
git commit -m "Add home page"
git log --oneline
git log --oneline هر commit را در یک خط نشان میدهد؛ جدیدترین بالاست. برای دیدن تغییرات فایلها پیش از commit هم از git diff استفاده کنید. این دستور خطهایی را که اضافه شده با + و خطهای حذفشده را با - نشان میدهد. عادت کنید قبل از هر commit یک بار git diff بزنید تا مطمئن شوید چیز ناخواستهای وارد نمیشود.
شاخه یکی از قویترین امکانات گیت است. شاخه به شما اجازه میدهد روی یک قابلیت تازه کار کنید، بدون اینکه کد اصلی دست بخورد. اگر کار خوب پیش رفت، آن را با شاخه اصلی ادغام میکنید؛ اگر نه، شاخه را پاک میکنید و هیچ چیزی خراب نشده است.
git switch -c feature/about
echo "<h1>About us</h1>" > about.html
git add about.html
git commit -m "Add about page"
git switch main
switch -c یک شاخه تازه میسازد و به آن میرود. شاید در آموزشهای قدیمی دستور git checkout را برای این کار ببینید. checkout هنوز کار میکند، اما چند کار متفاوت انجام میدهد و برای تازهکارها گیجکننده است. گیت برای همین دو دستور جداگانه git switch برای جابهجایی بین شاخهها و git restore برای برگرداندن فایلها را اضافه کرده است.
وقتی کار شاخه تمام شد، به main برگردید و آن را ادغام کنید:
git merge feature/about
git branch -d feature/about
اگر از زمان ساخت شاخه، commit تازهای روی main نیامده باشد، گیت فقط اشارهگر main را جلو میبرد. به این حالت Fast-forward میگویند و در خروجی ما هم همین کلمه دیده شد. بعد از ادغام، شاخه را با branch -d پاک کنید تا فهرست شاخهها شلوغ نشود.

تعارض وقتی پیش میآید که دو شاخه یک خط از یک فایل را به دو شکل متفاوت تغییر داده باشند. گیت نمیتواند حدس بزند کدام درست است و از شما میخواهد تصمیم بگیرید. تعارض ترسناک نیست؛ بخشی عادی از کار تیمی است. در آزمایش ما، در شاخه feature/title عنوان صفحه را Welcome گذاشتیم و همزمان روی main آن را Hello world کردیم. وقتی merge زدیم، گیت این پیام را داد: CONFLICT (content): Merge conflict in index.html. محتوای فایل این شکل شد:
<<<<<<< HEAD
<h1>Hello world</h1>
=======
<h1>Welcome</h1>
>>>>>>> feature/title
بخش بالای ======= نسخه شاخه فعلی (main) است و بخش پایین نسخه شاخهای که ادغام میکنید. فایل را باز کنید، نسخه نهایی را بنویسید و همه علامتهای <<<<<<< و ======= و >>>>>>> را پاک کنید. بعد فایل را stage و commit کنید.
تا قبل از Git 2.56 بیشتر افراد بعد از حل تعارض git add . یا git add -u میزدند. ایراد این کار این بود که ممکن بود تغییرات بیربط دیگر یا فایلی که هنوز علامت تعارض دارد هم stage شود. طبق معرفی Git 2.56 در وبلاگ گیتهاب، حالت تازه git add --resolved فقط فایلهایی را که در تعارض بودهاند stage میکند و اگر هنوز علامت تعارض در آنها مانده باشد، هیچ چیزی را stage نمیکند. ما این را آزمایش کردیم. وقتی علامتها هنوز در فایل بودند، گیت پیام fatal: the following paths still have conflict markers: index.html را داد. بعد از اصلاح فایل، دوباره زدیم و کار تمام شد:
git add --resolved
git commit -m "Merge feature/title"
git log --oneline --graph
اگر نسخه گیت شما قدیمیتر است، بهجای add --resolved اسم فایل را دقیق بنویسید، مثل git add index.html. خروجی log --graph هم دو شاخه و نقطه ادغامشان را با خطهایی ساده نشان میدهد که برای فهمیدن تاریخچه خیلی کمک میکند.
همه اشتباه میکنند. گیت چند راه برای برگشت دارد و انتخاب راه درست به این بستگی دارد که تغییر کجاست. اگر فایلی را خراب کردهاید و هنوز commit نکردهاید، git restore نام-فایل آن را به آخرین نسخه commitشده برمیگرداند. ما یک خط اضافه در README نوشتیم، با git diff دیدیم و با git restore README.md پاکش کردیم. مراقب باشید؛ این تغییرات برای همیشه از بین میروند. اگر commitی ثبت شده و حتی به گیتهاب فرستاده شده، از git revert استفاده کنید. revert تاریخچه را پاک نمیکند؛ یک commit تازه میسازد که دقیقاً برعکس commit قبلی است:
git revert --no-edit 950dbaa
شناسه را از git log بردارید. در آزمایش ما revert کردن commit «Add about page» یک commit تازه با پیام Revert "Add about page" ساخت و فایل about.html حذف شد، اما تاریخچه دست نخورد. احتمالاً درباره git reset --hard هم شنیدهاید. این دستور commitها را از تاریخچه پاک میکند و اگر روی شاخهای که دیگران استفاده میکنند به کار برود، کار تیم را به هم میریزد. تا وقتی مبتدی هستید، برای commitهای ارسالشده فقط از revert استفاده کنید.
| موقعیت | دستور | اثر |
|---|---|---|
| فایل را خراب کردهاید و هنوز add نکردهاید | git restore نام-فایل | برگشت به آخرین نسخه commitشده؛ تغییرات از بین میرود |
| فایلی را اشتباهی add کردهاید | git restore --staged نام-فایل | از Staging بیرون میآید ولی تغییرات میماند |
| پیام آخرین commit اشتباه است و push نشده | git commit --amend | آخرین commit اصلاح میشود |
| commitی push شده و باید خنثی شود | git revert شناسه | commit تازهای که اثر قبلی را برمیگرداند |
| وسط merge پشیمان شدهاید | git merge --abort | برگشت به وضعیت پیش از merge |
تا اینجا همه چیز روی سیستم خودمان بود. حالا میخواهیم پروژه را روی گیتهاب بگذاریم تا هم نسخه پشتیبان داشته باشیم و هم دیگران بتوانند همکاری کنند.
در گیتهاب از دکمه New repository یک مخزن خالی بسازید. برای فرستادن کد، گیتهاب رمز حساب را در خط فرمان قبول نمیکند؛ طبق مستندات مخزنهای راه دور گیتهاب ورود با رمز برای گیت حذف شده است. دو راه دارید: کلید SSH یا توکن دسترسی شخصی (Personal Access Token). راهنمای ساخت کلید SSH در گیتهاب ساخت کلید از نوع ed25519 را پیشنهاد میکند:
ssh-keygen -t ed25519 -C "sara@example.com"
کلید عمومی (فایلی که با .pub تمام میشود) را در تنظیمات حساب گیتهاب در بخش SSH and GPG keys اضافه کنید. اگر HTTPS را ترجیح میدهید، طبق مستندات توکنهای گیتهاب یک توکن بسازید و هنگام push بهجای رمز وارد کنید. با توکن مثل رمز رفتار کنید و هرگز آن را داخل کد نگذارید.
آدرس مخزن گیتهاب را بهعنوان remote اضافه کنید و کد را بفرستید:
git remote add origin git@github.com:sara/my-site.git
git push -u origin main
git remote -v
origin اسم قراردادی مخزن اصلی روی سرور است. گزینه -u شاخه محلی main را به شاخه main روی سرور وصل میکند تا دفعههای بعد فقط git push کافی باشد. ما این مراحل را با یک مخزن bare روی همان سیستم شبیهسازی کردیم؛ با گیتهاب فقط آدرس عوض میشود.
برای کار روی پروژهای که روی گیتهاب است، آن را clone کنید. clone کل تاریخچه را دریافت میکند و remote را هم خودکار تنظیم میکند. وقتی دیگران تغییر تازهای فرستادند، با git pull آن را بگیرید. عادت خوب این است که هر روز قبل از شروع کار یک بار pull بزنید تا با آخرین نسخه کار کنید و تعارضها کمتر شوند.
در کار تیمی معمولاً کسی مستقیم روی main نمینویسد. هر نفر یک شاخه میسازد، کارش را در آن انجام میدهد، شاخه را push میکند و بعد یک Pull Request (به اختصار PR) باز میکند. طبق مستندات Pull Request گیتهاب، PR پیشنهادی است برای ادغام تغییرات یک شاخه در شاخه دیگر که همتیمیها میتوانند آن را ببینند، نظر بدهند و تأیید کنند. مسیر کامل یک PR این شکلی است:
git switch -c feature/contact-form
git add contact.html
git commit -m "Add contact form"
git push -u origin feature/contact-form
بعد از push، گیتهاب پیشنهاد ساخت PR را نشان میدهد. یک عنوان روشن بنویسید و در توضیح بگویید چه چیزی تغییر کرده، چرا و چطور میشود آن را آزمایش کرد. همتیمیها کد را بررسی میکنند، روی خطها نظر میگذارند و اگر لازم بود، شما commit تازهای روی همان شاخه میفرستید و PR خودکار بهروز میشود. بعد از تأیید، دکمه Merge را میزنید. PR فقط برای تیمها نیست. اگر بخواهید در یک پروژه متنباز مشارکت کنید، اول آن را Fork میکنید (یک کپی در حساب خودتان)، تغییر را در Fork انجام میدهید و بعد به مخزن اصلی PR میفرستید. اگر هم پروژهای را با ابزارهای هوش مصنوعی ساختهاید، بردن آن به گیتهاب را در پروژه عملی وایب کدینگ نشان دادهایم.

در تیمهای حرفهای، هر PR پیش از ادغام بهطور خودکار تست میشود. این کار با ابزارهایی مثل GitHub Actions انجام میشود و بخشی از CI/CD است. اگر گیت را یاد گرفتید، قدم بعدی منطقی آموزش CI/CD با GitHub Actions و GitLab CI است. وقتی هم بخواهید برنامه را همراه همه وابستگیهایش بستهبندی کنید، آموزش مقدماتی داکر را بخوانید.
این جدول را نگه دارید و هر وقت لازم شد، به آن برگردید:
| دستور | کار |
|---|---|
| git init | ساخت مخزن تازه در پوشه فعلی |
| git clone آدرس | دریافت کامل یک مخزن |
| git status --short | دیدن وضعیت فایلها |
| git add فایل | بردن تغییرات به Staging |
| git commit -m "پیام" | ثبت تغییرات Staging در تاریخچه |
| git log --oneline --graph | دیدن تاریخچه خلاصه با شاخهها |
| git diff | دیدن تغییرات ثبتنشده |
| git switch -c نام | ساخت شاخه و رفتن به آن |
| git merge نام | ادغام شاخه در شاخه فعلی |
| git add --resolved | stage فایلهای تعارضدار حلشده (Git 2.56 به بعد) |
| git remote add origin آدرس | اتصال به مخزن روی سرور |
| git push -u origin main | فرستادن commitها به سرور |
| git pull | دریافت و ادغام تغییرات تازه سرور |
| git revert شناسه | خنثی کردن یک commit با commit تازه |
کار مستقیم روی main بدون شاخه، رایجترین اشتباه است. حتی اگر تنها کار میکنید، برای هر قابلیت یک شاخه بسازید؛ اگر کار خراب شد، main سالم میماند. اشتباه دوم commitهای خیلی بزرگ است، مثل یک commit با پیام «همه تغییرات این هفته». commit کوچک بهتر بررسی و راحتتر revert میشود. اشتباه سوم و خطرناکترین، commit کردن رمز، کلید API یا فایل .env است. اگر این اتفاق افتاد، فوراً آن رمز یا کلید را باطل کنید و کلید تازه بسازید. پاک کردن فایل در commit بعدی کافی نیست، چون در تاریخچه میماند. اشتباه چهارم استفاده از git push --force روی شاخه مشترک است که میتواند کار همتیمیها را پاک کند. یک نکته هم درباره اصول نرمافزارهای ابری: طبق فاکتور کدبیس در مجموعه دوازده فاکتور، هر برنامه باید یک مخزن کد داشته باشد و همه نسخههای اجرایی، از تست تا تولید، از همان مخزن بیایند. گیت ابزار اصلی پیاده کردن همین اصل است.
گیت کاملاً رایگان و متنباز است. گیتهاب برای مخزنهای عمومی و خصوصی نسخه رایگان دارد و برخی امکانات تیمی و سازمانی آن پولی است.
fetch فقط تغییرات تازه سرور را دریافت میکند ولی به فایلهای شما دست نمیزند. pull همان fetch است بهاضافه ادغام تغییرات در شاخه فعلی. اگر میخواهید اول ببینید چه چیزی آمده، fetch بزنید.
برای پروژههای جدید main را استفاده کنید. گیتهاب و GitLab آن را پیشفرض گذاشتهاند و Git 3.0 هم پیشفرض را main میکند. با git config --global init.defaultBranch main از همین حالا آن را تنظیم کنید.
اگر هنوز push نکردهاید، با git commit --amend میتوانید پیام یا فایلهای آخرین commit را اصلاح کنید. اگر push کردهاید، بهتر است یک commit تازه بزنید تا تاریخچه دیگران به هم نریزد.
نه. ویرایشگرهایی مثل VS Code و برنامه GitHub Desktop رابط گرافیکی دارند. اما دانستن دستورهای پایه کمک میکند بفهمید ابزار گرافیکی پشت صحنه چه میکند و وقتی مشکلی پیش آمد، خودتان آن را حل کنید.
نظرات 0
برای ارسال نظر وارد حساب کاربری شوید.
هنوز نظری ثبت نشده؛ اولین نفر باشید.