آموزش گیت و گیتهاب
گیت برنامه ای روی کامپیوتر خود شماست که هر وقت بگویید، از وضعیت پروژه یک عکس تاریخ دار با یک یادداشت نگه می دارد و بعدا اجازه می دهد به هر کدام از آن عکس ها برگردید. گیتهاب یکی از جاهایی است که می شود نسخه ای از این تاریخچه را رویش گذاشت؛ خود گیت بدون اینترنت و بدون هیچ حسابی هم کامل کار می کند.
- درس ۹ از ۱۴
- مقدماتی
- رایگان، بدون ثبت نام
زندگی یک تغییر، از ویرایش تا تاریخچه
-
۱
ویرایش فایل
تا اینجا گیت هیچ کاری نکرده. تغییر روی دیسک هست و در تاریخچه نیست.
-
۲
git add
انتخاب می کنید چه چیزی داخل این عکس باشد. همین پله است که معمولا فراموش می شود.
-
۳
git commit
عکس با تاریخ، نام و یک پیام ثبت می شود. از این لحظه قابل برگشت است.
-
۴
git push
نسخه ای از تاریخچه روی یک میزبان هم می نشیند. تنها قدمی که به شبکه نیاز دارد.
-
۵
git log
هر عکس با تاریخ و پیامش برمی گردد. اینجا معلوم می شود پیام خوب چقدر می ارزید.
این ترتیب برای یک نفر و یک شاخه است. کار تیمی، pull و merge و حل تعارض را اضافه می کند و این درس آنها را پوشش نمی دهد.
آخرین بررسی: فکت ها و نام ابزارهای این درس در همین تاریخ با منابعشان بازبینی شده اند.
گیت چه مشکلی را حل می کند که کپی گرفتن از پوشه حل نمی کند؟
روش قبل از گیت را همه دیده ایم: site، site-final، site-final-2، و آن پوشه ای که کسی جرات ندارد پاکش کند. ایراد این روش زشتی اش نیست؛ این است که هیچ کدام از آن پوشه ها نمی گویند چرا ساخته شده اند و کدام فایل ها با هم عوض شده اند.
گیت یک سیستم کنترل نسخه است: به جای نگه داشتن چند کپی کامل، وضعیت پروژه را در نقطه هایی که خودتان تعیین می کنید ثبت می کند. هر نقطه یک کامیت است و سه چیز دارد که پوشه کپی شده هیچ کدام را ندارد: تاریخ و ساعت دقیق، اسم کسی که ثبتش کرده، و یک پیام که می گوید چرا این تغییر انجام شده.
ارزش واقعی گیت هم همان چیز سوم است. شش ماه بعد، وقتی به خطی می رسید که معنایش را نمی فهمید، سوال شما این نیست که این خط از کجا آمد؛ این است که چرا کسی این کار را کرده. گیت به همان سوال جواب می دهد، به شرطی که پیام ها را جدی نوشته باشید. تاریخچه ای پر از «تغییرات» و «اصلاح» دقیقا همان قدر بی فایده است که پوشه final-2.
و یک تفاوت عملی که زودتر از بقیه به دردتان می خورد: گیت به شما اجازه می دهد ببینید بین دو نقطه دقیقا کدام خط ها عوض شده اند. وقتی سایتی که دیروز کار می کرد امروز خراب است، این یک قابلیت راحتی نیست، تنها راه پیدا کردن علت در چند دقیقه به جای چند ساعت است.
گیت و گیتهاب یکی نیستند
گیت یک برنامه است که روی کامپیوتر خودتان نصب می شود و کارش نگه داشتن تاریخچه است. گیتهاب یک شرکت است که این تاریخچه ها را روی سرورهایش میزبانی می کند و دور آن چیزهای دیگری ساخته: صفحه پروفایل، گزارش خطا، بررسی کد و بقیه. یکی ابزار است و دیگری خدمات؛ همان نسبتی که ورد با ایمیل دارد.
این تفکیک یک خاصیت مهم دارد که معمولا در آموزش ها گم می شود: گیت توزیع شده است، یعنی روی کامپیوتر شما یک نسخه کامل از تاریخچه هست، نه یک اشاره گر به سرور. می توانید کل روز کامیت بزنید، تاریخچه را بخوانید و به عقب برگردید بدون اینکه یک بار به اینترنت وصل شوید. push فقط نسخه ای از همان تاریخچه را جای دیگری هم می گذارد.
پس اگر فردا آن میزبان از دسترس خارج شود، مخزن روی دستگاه شما ناقص نمی شود و می توانید همان را به هر جای دیگری بفرستید: گیت لب، یک سرور شخصی، یا حتی یک هارد. چیزی که با میزبان از دست می رود، ایشیوها و پول ریکوئست ها و بحث های زیر آنهاست، چون آنها اصلا داخل گیت نیستند و ساخته خود آن شرکت اند.
برای خواننده ایرانی یک جمله عملی: در دسترس بودن سرویس های میزبانی خارجی چیزی است که باید همان روز خودتان امتحان کنید و ما ادعای امروز درباره اش نمی نویسیم. ولی تصمیم درست، مستقل از این است: تاریخچه را جایی نگه دارید که اگر یک سرویس رفت، کارتان نایستد. این با ذات گیت جور است و به هیچ سرویسی هم وابسته نیست.
تاریخچه کجاست؟ روی هر دو کامپیوتر
کامپیوتر شما
- یک نسخه کامل از تاریخچه، نه یک اشاره گر
- commit بدون اینترنت کار می کند
کامپیوتر همکار
- او هم همان تاریخچه کامل را دارد
- هر کدام مستقل کار می کنید و بعد همگام می شوید
میزبان فقط یک نسخه است، نه مالک تاریخچه
گیتهاب یا هر میزبان دیگر
- یک نسخه مشترک در میانه، برای همگام شدن
- ایشیو، بررسی کد و پروفایل را خودش اضافه کرده
اگر میزبان از دسترس خارج شود، تاریخچه کد سالم است و به هر جای دیگری push می شود. چیزی که با میزبان می رود ایشیوها و بررسی های کد است، چون آنها داخل گیت نیستند.
چهار دستور اول، و اینکه add اصلا برای چیست
یک پروژه را با git init زیر نظر گیت می برید. این دستور یک پوشه پنهان به اسم .git می سازد و از آن به بعد هر چه در آن پوشه اتفاق بیفتد قابل ثبت است. تا اینجا هیچ چیزی ثبت نشده؛ فقط دفتر باز شده.
git init
git add index.html
git commit -m "صفحه اول با فرم تماس"
git push origin mainدستوری که تازه کارها گیجشان می کند add است، چون به نظر می رسد یک قدم اضافه است. نیست. بین فایل های شما و تاریخچه یک میز میانی هست به اسم استیج، و add یعنی «این را بگذار روی میز، می خواهم داخل عکس بعدی باشد». وجود این میز به شما اجازه می دهد از میان ده فایلی که امروز عوض کرده اید، فقط سه تای مربوط به یک کار را در یک کامیت ثبت کنید.
همین جاست که اولین عادت حرفه ای شکل می گیرد: یک کامیت باید یک کار باشد. اگر مجبورید در پیام کامیت از «و» استفاده کنید، احتمالا باید دو کامیت باشد. این توصیه سلیقه ای نیست؛ روزی که بخواهید یک تغییر را برگردانید و آن تغییر با دو کار دیگر در یک کامیت قاطی شده باشد، هزینه اش را می دهید.
و push تنها دستوری از این چهارتاست که به شبکه نیاز دارد. سه تای اول کاملا روی دستگاه خودتان کار می کنند. اگر این را در ذهن نگه دارید، پیام های خطای گیت هم معنادار می شوند: خطای دسترسی و احراز هویت تقریبا همیشه مال push است، و خطای «چیزی برای ثبت نیست» تقریبا همیشه یعنی add را فراموش کرده اید.
اولین چیزی که خراب می شود: فایلی که نباید ثبت می شد
فایلی به اسم .gitignore در ریشه پروژه می گوید گیت به چه چیزهایی کار نداشته باشد. سه دسته همیشه در آن هستند: پوشه وابستگی ها که دوباره نصب می شود، فایل هایی که موقع بیلد ساخته می شوند، و هر چیزی که رمز یا کلید واقعی دارد.
دسته سوم جایی است که آدم ها ضربه می خورند. فایل تنظیمات با رمز پایگاه داده یک بار ثبت می شود، بعد کسی متوجه می شود، رمز را از فایل برمی دارد و کامیت جدید می زند. کار انجام نشده: گیت تاریخچه را نگه می دارد، و آن رمز هنوز داخل کامیت قبلی هست و با یک دستور ساده قابل دیدن است.
راهنمای خود گیتهاب هم همین را می گوید: بعد از چنین اتفاقی باید آن اعتبارنامه را سوخته حساب کنید و عوضش کنید، و پاک کردن فایل از تاریخچه به تنهایی کافی نیست. ترتیب درست هم برعکس چیزی است که آدم انتظار دارد: اول رمز را عوض کنید، بعد به فکر تمیز کردن تاریخچه بیفتید.
پس عادتی که از روز اول ارزش دارد این است: قبل از اولین کامیت، .gitignore را بنویسید، نه بعد از آن. و اگر پروژه یک نمونه تنظیمات لازم دارد، فایلی مثل config.example با مقدارهای خالی بگذارید تا نفر بعدی بداند چه چیزهایی لازم است، بدون اینکه مقدار واقعی جایی ثبت شود.
ثبت شود
- کد و فایل های متنی خود پروژه
- فایل قفل وابستگی ها، تا همه یک نسخه نصب کنند
- نمونه تنظیمات با مقدارهای خالی
- خود فایل gitignore
هرگز ثبت نشود
- فایل تنظیمات با رمز یا کلید واقعی
- پوشه وابستگی ها که با یک دستور دوباره نصب می شود
- خروجی بیلد و فایل های ساخته شده
- پشتیبان پایگاه داده و فایل های آپلود کاربران
این فایل فقط جلوی چیزی را می گیرد که هنوز ثبت نشده. فایلی که یک بار commit شده، با اضافه کردن به این فهرست از تاریخچه پاک نمی شود.
سایتی که این درس رویش نوشته شده در گیت نیست
rgb.ir روی یک سرور زنده ویرایش می شود و مخزن گیت ندارد. این را می نویسیم چون درسی که فقط توصیه می کند و نمی گوید خودش کجا ایستاده، نصف حقیقت است.
جای گیت را چه چیزی گرفته؟ ویرایشگری که برای قالب نوشته ایم، پیش از هر ذخیره، یک کپی از فایل با نام تاریخ و ساعت کنار می گذارد و بیست نسخه آخر هر فایل را نگه می دارد. بعد فایل جدید را با token_get_all و پرچم TOKEN_PARSE تحلیل می کند، چون روی این سرور هم php -l و هم proc_open غیرفعال اند و راه معمول بررسی نحو در دسترس نیست. اگر فایل جدید پارس نشود، همان کپی قبلی خودکار برمی گردد تا صفحه زنده نخوابد.
این تقریبا تعریف کمینه یک سیستم نسخه است و برای کاری که می کند خوب کار می کند. ولی فرقش با گیت دقیقا همان چیزهایی است که این درس درباره شان بود: هیچ کدام از آن بیست کپی نمی گوید چرا ذخیره شده، هیچ چیزی دو فایلی را که با هم عوض شده اند به هم وصل نمی کند، و از نسخه بیست و یکم به بعد چیزی باقی نمی ماند.
پس اگر پروژه شما هنوز در گیت نیست، این درس یک سرزنش نیست. ولی هزینه اش را بشناسید: نبود گیت روزی که همه چیز کار می کند هیچ هزینه ای ندارد، و روزی که کار نمی کند تمام هزینه اش را یک جا می گیرد.
مسیر سریع با هوش مصنوعی
کاری که در ۲۰۲۶ حرفه ای ها با هوش مصنوعی و گیت می کنند، دادن دسترسی به مدل برای اجرای دستور نیست؛ برعکس است. شما تغییرات آماده ثبت را به او نشان می دهید و قبل از کامیت سه چیز می خواهید: آیا چند کار نامربوط را قاطی کرده ام، آیا چیزی شبیه رمز داخل این تغییرات هست، و پیام کامیتی که «چرا» را بگوید نه «چه». بند دوم همان بندی است که این دستور را از یک درخواست معمولی پیام کامیت جدا می کند و بیشترین ارزش را هم دارد.
- با <code>git add -p</code> تکه تکه انتخاب کنید چه چیزی روی میز برود، نه با add کردن کل پوشه. همین یک دستور، نصف اشتباه های این کار را از اول حذف می کند.
- خروجی <code>git diff --staged</code> را بردارید و با دستور زیر بفرستید. اول جواب بند یک و دو را بخوانید، بعد سراغ پیام بروید.
- اگر چیزی شبیه کلید یا رمز فهرست شد، همان جا بایستید: با <code>git restore --staged</code> از میز برش دارید، فایل را در gitignore بگذارید، و اگر آن مقدار واقعی بوده عوضش کنید.
- پیام را از پیش نویس مدل بردارید ولی خودتان بازنویسی کنید. مدل «چه چیزی عوض شده» را از diff می خواند، ولی «چرا» را فقط شما می دانید و همان است که شش ماه بعد به درد می خورد.
نسخه آماده کپی
این خروجی git diff --staged است.
{خروجی diff}
سه چیز بده، به همین ترتیب:
۱. اگر در این تغییرات بیش از یک کار نامربوط هست، بگو کدام خط ها به کدام کار مربوط اند و پیشنهاد بده در چند کامیت جدا بروند.
۲. هر چیزی که شبیه رمز، کلید، توکن، آدرس داخلی یا اطلاعات یک مشتری واقعی است را فهرست کن. اگر هیچ کدام نبود، صریح بنویس که نبود.
۳. یک پیام کامیت بنویس: خط اول حداکثر پنجاه کاراکتر و به شکل دستوری، بعد یک خط خالی، بعد دو تا چهار خط که «چرا» را توضیح می دهد نه «چه».
هیچ دستور گیتی برای اجرا ننویس. اگر برای جواب دادن به کدی نیاز داری که در این diff نیست، بگو کدام و چرا؛ حدس نزن.
قبل از اعتماد به خروجی: دو مرز که این دستور از آنها فراتر نمی رود. اول اینکه مدل فقط همان diff را می بیند: اگر تغییر شما جای دیگری از پروژه چیزی را خراب کند، در این خروجی نشانی از آن نیست و تنها راه، اجرا کردن خود برنامه است. دوم اینکه فرستادن diff یعنی فرستادن کد شما به یک شرکت دیگر؛ اگر پروژه مال مشتری است، اجازه اش را قبلا گرفته باشید و صفحه استفاده از داده همان سرویس را خوانده باشید. جمله آخر دستور هم تزئینی نیست: دستور گیتی که به شما داده می شود و شما نمی توانید توضیحش بدهید، اجرا نمی شود.
هوش مصنوعی در این کار
موضع ما درباره گیت و هوش مصنوعی روشن است: مدل را در نقش خواننده و نویسنده متن بگذارید، نه در نقش کسی که مخزن شما را می گرداند. نوشتن پیام کامیت، خلاصه کردن یک diff طولانی، و توضیح دادن اینکه یک کامیت قدیمی چه کاری کرده، سه کاری است که مدل ها واقعا خوب انجام می دهند و وقت شما را برمی گردانند. اجرای دستور اما کار دیگری است و دلیلش را در بخش خطر می گوییم.
ابزارهایی که واقعا کمک می کنند
- Claude Code در ترمینال کنار مخزن می نشیند، پس به جای اینکه diff را دستی کپی کنید خودش می خواندش. برای «این کامیت چه کاری کرد» و «چرا این خط اینجاست» بهترین گزینه این فهرست است. رایگان نصب می شود ولی بدون اشتراک کلود یا حساب کنسول انتروپیک کار نمی کند و ایران در فهرست کشورهای پشتیبانی شده انتروپیک نیست.
- Claude برای همان دستور بالا در یک پنجره چت کافی است: diff را می چسبانید و سه بند را می گیرید. ایران در هیچ کدام از دو فهرست کشورهای پشتیبانی شده انتروپیک نیست؛ این را از صفحه خود انتروپیک خوانده ایم، نه از تست شبکه.
- Gemini برای پیام کامیت و خلاصه کردن diff، یک مدل سریع و ارزان کافی است و همین جا جایش است؛ برای تشخیص اینکه دو کار نامربوط قاطی شده اند، مدل قوی تر جواب بهتری می دهد. صفحه خود گوگل می گوید اپ وب جمنای در بیش از دویست و سی کشور و منطقه کار می کند و ایران در آن فهرست نیست.
کجا نتیجه معکوس می دهد
خطر اصلی اینجا یک دسته خاص از دستورهاست، نه ابزارها. بیشتر کارهای گیت قابل برگشت اند، ولی سه تا نیستند و مدل ها همان سه تا را با اطمینان کامل پیشنهاد می دهند: git reset --hard که طبق مستندات خود گیت تغییرات ثبت نشده در پوشه کار را دور می ریزد، git clean -fd که فایل های ردیابی نشده را حذف می کند، و git push --force که شاخه روی سرور را با نسخه شما جایگزین می کند و می تواند کار کسی دیگر را پاک کند. قاعده ساده است: دستوری که نمی توانید توضیح بدهید اجرا نمی شود، و قبل از هر کدام از این سه، یک git status بگیرید.
خطر دوم مال چسباندن است نه اجرا کردن: هر diff یا فایلی که در چت می گذارید از دستگاه شما بیرون رفته، و اینکه با آن چه می کنند به پلن و تنظیمات همان سرویس بستگی دارد و روی صفحه استفاده از داده خودش نوشته شده. برای پروژه شخصی مساله ای نیست؛ برای کد مشتری اول باید اجازه بگیرید. برای اینکه بدانید هر کدام از این ابزارها از ایران چطور قابل پرداخت است راهنمای خرید را ببینید، و برای انتخاب فعلی ما میان مدل های کدنویسی بهترین هوش مصنوعی برای کدنویسی.
منبع ها: git-scm: git reset git-scm: git clean git-scm: git push, the force option Anthropic: supported countries Google: where the Gemini web app is available
حد این توصیه
این درس یک نفر و یک شاخه را پوشش می دهد. هر چیزی که کار تیمی اضافه می کند بیرون مانده و هر کدام درس خودش را می خواهد: شاخه بندی، merge و رفع تعارض، rebase، بررسی کد و پول ریکوئست، و فایل های بزرگ که گیت برایشان ساخته نشده. یک مرز بزرگ تر هم هست که کمتر گفته می شود: گیت برای فایل های متنی ساخته شده، و اگر چیزی که در پروژه شما عوض می شود داخل پایگاه داده است، نه در فایل ها، گیت آن را نمی بیند. یک سایت وردپرسی دقیقا همین شکل است و به همین دلیل هم داشتن گیت برای قالب، به تنهایی پشتیبان سایت حساب نمی شود.
از تجربه خود ما
همین سایت مخزن گیت ندارد و روی سرور زنده ویرایش می شود. چیزی که جایش را گرفته، افزونه ویرایشگر قالب خودمان است: قبل از هر ذخیره یک کپی از فایل با نام تاریخ و ساعت به اضافه شش کاراکتر تصادفی کنار می گذارد، بیست نسخه آخر هر فایل را نگه می دارد و قدیمی تر را پاک می کند، و یک دفتر رخداد با سقف دویست ردیف دارد. بعد از نوشتن، فایل جدید را با token_get_all و پرچم TOKEN_PARSE پارس می کند، چون روی این سرور php -l و proc_open هر دو غیرفعال اند؛ و اگر پارس نشود همان کپی قبلی را خودکار برمی گرداند. این تقریبا حداقل چیزی است که به آن سیستم نسخه می گویند، و فاصله اش با گیت دقیقا سه چیز است: پیامی که بگوید چرا، پیوندی بین دو فایلی که با هم عوض شده اند، و تاریخچه ای که به بیست نسخه محدود نباشد.
سوال هایی که واقعا پرسیده می شوند
برای پروژه یک نفره هم گیت لازم است؟
بله، ولی نه به دلیلی که معمولا می گویند. دلیلش پشتیبان گرفتن نیست، چون برای پشتیبان راه های ساده تری هست؛ دلیلش این است که شش ماه بعد خودتان تنها کسی هستید که باید بفهمد چرا این خط نوشته شده. گیت جواب همان سوال را نگه می دارد.
فرق git pull و git fetch چیست؟
fetch تغییرات سرور را می آورد ولی به کار شما دست نمی زند، پس می توانید اول ببینید چه خبر است. pull همان کار را می کند و بلافاصله با شاخه شما ادغام می کند. وقتی مطمئن نیستید، اول fetch بگیرید.
پیام کامیت را اشتباه نوشتم، می شود عوضش کرد؟
اگر هنوز push نکرده اید، git commit --amend پیام آخرین کامیت را عوض می کند و کارتان تمام است. اگر push کرده اید، این کار تاریخچه را بازنویسی می کند و برای هر کسی که آن شاخه را گرفته دردسر می سازد؛ در یک مخزن مشترک بهتر است پیام غلط بماند.