ذخیره کردن تغییرات در سیستم‌های کنترل نسخه، تفاوت بنیادی با زدن دکمه ذخیره (Save) در نرم‌افزارهای معمولی دارد.

در پروژه‌های واقعی و محیط‌های توسعه نرم‌افزار، توسعه‌دهنده نیاز دارد کنترل کاملی روی جزییات کدهای خود داشته باشد تا مشخص کند دقیقاً کدام بخش از تغییرات، در چه زمانی و با چه هدفی به تاریخچه اصلی پروژه اضافه می‌شوند.

این مدیریت دقیق به کمک دو مفهوم کلیدی یعنی محیط استیج (Staging Area) و ثبت نهایی (Commit) انجام می‌شود.

گیت این امکان را فراهم می‌کند که ابتدا کدهای اصلاح‌شده را در یک صف انتظار یا همان محیط استیج سازماندهی کرد و سپس با اطمینان از صحت آن‌ها، یک نسخه دائمی و شناسنامه‌دار از تغییرات ایجاد نمود. 

در این درس، فرآیند انتقال فایل‌ها با دستور git add و ثبت نهایی آن‌ها با دستور git commit به صورت گام‌به‌گام و بر اساس استانداردهای تیم‌های فنی بررسی خواهد شد.

درک چرخه حیات فایل‌ها در گیت (File Lifecycle)

برای درک عمیق نحوه کارکرد دستورات git add و git commit، ابتدا باید با مسیر حرکت و چرخه حیات فایل‌ها در گیت آشنا شوید. گیت بر خلاف ابزارهای ذخیره‌سازی سنتی، فایل‌های موجود در پوشه پروژه را به یک چشم نگاه نمی‌کند، بلکه آن‌ها را بر اساس موقعیت و وضعیتی که دارند، در ۴ لایه یا حالت مجزا دسته‌بندی می‌کند.

در ادامه، این وضعیت‌ها و منطق حاکم بر آن‌ها به صورت دقیق بررسی می‌شود.

وضعیت‌های ۴گانه فایل در چرخه حیات گیت

وقتی یک مخزن گیت در پروژه راه‌اندازی می‌شود، هر فایلی که ساخته یا ویرایش می‌شود، قطعاً در یکی از این ۴ وضعیت قرار دارد:

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

۲. وضعیت Unmodified (تغییر نیافته): وقتی فایلی را کامیت می‌کنید، آن فایل به یک نسخه مصوب و ثبت‌شده در تاریخچه گیت تبدیل می‌شود. در این حالت، فایل روی سیستم شما دقیقاً مشابه آخرین نسخه ثبت‌شده در گیت است و هیچ تغییر جدیدی ندارد.

۳. وضعیت Modified (تغییر یافته): اگر فایلی را که قبلاً در گیت ثبت شده بود باز کنید و حتی یک کاراکتر از آن را تغییر دهید یا خطی به آن اضافه کنید، فایل بلافاصله به وضعیت Modified منتقل می‌شود. این یعنی گیت متوجه تفاوت نسخه فعلی با نسخه ثبت‌شده قبلی شده است، اما این تغییرات هنوز در صف ذخیره قرار نگرفته‌اند.

۴. وضعیت Staged (آماده‌سازی شده): این وضعیت، مرحله ماقبل ثبت نهایی است. وقتی فایلی را به محیط استیج می‌فرستید، یعنی آن را در صف انتظار برای کامیت بعدی قرار داده‌اید. گیت در این مرحله یک تصویر موقت از تغییرات فایل تهیه می‌کند.

چرا گیت مستقیماً فایل‌ها را کامیت نمی‌کند؟

یکی از سوالات رایج در شروع یادگیری گیت این است که چرا فرآیند ثبت تغییرات دو مرحله‌ای است و چرا دستور مستقیمی برای کامیت کردن مستقیم فایل‌های تغییریافته وجود ندارد؟ پاسخ این سوال در فلسفه وجودی «محیط استیج» (Staging Area) نهفته است.

محیط استیج به عنوان یک فیلتر کنترل کیفیت و سازماندهی کدهای آماده عمل می‌کند. در پروژه‌های واقعی و تیمی، بسیار پیش می‌آید که شما به طور هم‌زمان روی چند بخش مختلف کد کار کنید؛ برای مثال، بخشی از یک باگ را برطرف کرده‌اید، چند خط کد برای تست نوشته‌اید و یک قابلیت جدید را هم تا نیمه جلو برده‌اید.

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

شما فقط فایل‌های مربوط به رفع باگ را به محیط استیج می‌فرستید، یک کامیت تمیز و مشخص برای آن ثبت می‌کنید، و کدهای نیمه‌کاره را در سیستم خود نگه می‌دارید تا در زمان مناسب روی آن‌ها کار کنید. این تفکیک دقیق، تضمین‌کننده یک تاریخچه منظم و بدون نقص در پروژه‌های بزرگ است.

مدیریت محیط استیج با دستور git add

انتقال فایل‌ها به محیط آماده‌سازی یا همان استیج (Staging Area)، اولین گام عملی برای ثبت تغییرات در گیت است. دستور git add به عنوان پل ارتباطی میان پوشه کاری شما (Working Directory) و محیط استیج عمل می‌کند.

با استفاده از این دستور، مشخص می‌کنید که کدام یک از تغییرات اعمال‌شده در کدها، ارزش قرارگیری در کامیت بعدی را دارند.

افزودن فایل‌ها به محیط استیج

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

۱. انتقال یک فایل مشخص

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

git add main.py

۲. انتقال گروهی با دستور git add .

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

git add .

۳. تفاوت git add . و git add -A
در نسخه‌های قدیمی گیت، عملکرد این دو دستور متفاوت بود؛ اما در نسخه‌های مدرن و فعلی گیت، هر دو دستور رفتار مشابهی دارند و تمام تغییرات شامل فایل‌های جدید (Untracked)، ویرایش‌شده (Modified) و حذف‌شده (Deleted) را در کل پروژه ردیابی و استیج می‌کنند.

با این حال، دستور git add . بر اساس پوشه‌ای که ترمینال شما در آن باز است عمل می‌کند، در حالی که سوییچ -A یا --all کل مخزن پروژه را بدون توجه به مسیر فعلی ترمینال تحت پوشش قرار می‌دهد.

بررسی وضعیت صف انتظار با git status

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

git status

خروجی این دستور فایل‌های موجود در استیج را با رنگ سبز و تحت عنوان "Changes to be committed" نشان می‌دهد. فایل‌هایی که هنوز به استیج منتقل نشده‌اند نیز با رنگ قرمز به نمایش در می‌آیند.

خارج کردن فایل از محیط استیج (Unstaging)

بسیار پیش می‌آید که فایلی را اشتباهاً با دستور git add . به محیط استیج بفرستید در حالی که کار آن هنوز تمام نشده است. برای بازگرداندن فایل از صف انتظار به پوشه کاری (بدون اینکه کدهای نوشته‌شده حذف شوند)، از دستور زیر استفاده کنید:

git restore --staged main.py

اجرای این دستور تداخلی در کدهای شما ایجاد نمی‌کند، بلکه صرفاً وضعیت فایل را در دیدگاه گیت از Staged دوباره به Modified یا Untracked تغییر می‌دهد تا در کامیت بعدی ثبت نشود.

ثبت دائمی تغییرات با دستور git commit

ثبت نهایی تغییرات یا کامیت کردن (Commit)، نقطه‌ عطف ذخیره‌سازی در گیت است. اگر محیط استیج را به عنوان صف انتظار یا سناریوی آماده‌سازی برای عکاسی در نظر بگیرید، دستور git commit دقیقاً همان لحظه‌ای است که دکمه ثبت عکس را فشار می‌دهید.

این دستور یک تصویر دائمی، فشرده و شناسنامه‌دار از وضعیت فعلی کدهای موجود در محیط استیج تهیه می‌کند و آن را به تاریخچه مخزن (Repository) می‌سپارد.

مفهوم کامیت به عنوان یک Snapshot

گیت برای ذخیره اطلاعات، از فایل‌ها کپی‌برداری سنتی نمی‌کند. هر کامیت یک «اسنپ‌شات» (Snapshot) یا تصویر لحظه‌ای از کل پروژه است. گیت در هر کامیت، وضعیت ساختار پوشه‌ها و محتوای فایل‌های استیج‌شده را بررسی می‌کند.

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

ساختار دستور و ثبت پیام کامیت

برای ثبت یک کامیت، استفاده از سوییچ -m (مخفف Message) الزامی است تا بتوانید توضیحی کوتاه درباره تغییرات اعمال‌شده بنویسید. این دستور به شکل زیر اجرا می‌شود:

git commit -m "feat: add user authentication layout"

نوشتن پیام کامیت یک کار سلیقه‌ای نیست. در شرکت‌های توسعه نرم‌افزار، پیام کامیت مشخص می‌کند که چه تغییراتی و با چه هدفی ایجاد شده‌اند. پیام‌های مبهم مثل "up" یا "fix" در پروژه‌های تیمی یک فاجعه به شمار می‌روند، زیرا هم‌تیمی‌ها هنگام بررسی تاریخچه پروژه متوجه جزییات تغییرات نخواهند شد.

پشت صحنه یک کامیت در گیت

وقتی دستور commit اجرا می‌شود، گیت یک موجودیت (Object) جدید در دیتابیس خود می‌سازد که شامل اطلاعات زیر است:

  • شناسه کامیت (SHA-1 Hash): یک کد ۴۰ کاراکتری منحصربه‌فرد (مثلاً 7b9a4c...) که بر اساس الگوریتم‌های رمزنگاری و با توجه به محتوای تغییرات تولید می‌شود. این کد به عنوان اثر انگشت آن کامیت عمل می‌کند.
  • اطلاعات نویسنده (Author): نام و ایمیل سازمانی فردی که کد را نوشته است (که قبلاً با دستور git config تنظیم شده).
  • برچسب زمانی (Timestamp): تاریخ و ساعت دقیق ثبت کامیت.
  • ارجاع به کامیت قبلی (Parent): هر کامیت (به جز کامیت اول پروژه) به کامیت قبل از خود متصل است که این امر زنجیره تاریخچه پروژه را شکل می‌دهد.

وضعیت پروژه پس از ثبت کامیت

بلافاصله پس از اجرای موفقیت‌آمیز دستور کامیت، گیت تغییرات را از محیط استیج به بخش دیتابیس اصلی منتقل می‌کند. اگر در این مرحله دستور git status را اجرا کنید، با پیام زیر مواجه می‌شوید:

nothing to commit, working tree clean

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

تمرین عملی و سناریوی واقعی

بهترین راه برای تثبیت مفاهیم چرخه حیات و دستورات گیت، اجرای آن‌ها در یک سناریوی واقعی است. در ادامه، یک شبیه‌سازی دقیق از کارهای روزمره‌ای که در یک شرکت نرم‌افزاری انجام می‌شود را گام‌به‌گام پیاده‌سازی می‌کنیم.

تعریف سناریو

فرض کنید به عنوان توسعه‌دهنده به یک تیم پیوسته‌اید و وظیفه دارید یک سیستم ثبت‌نام ساده ایجاد کنید. برای این کار باید یک فایل کد اصلی بسازید، یک فایل تنظیمات فرعی ایجاد کنید و در نهایت تغییرات تاییدشده را کامیت کنید.

گام اول: ساخت فایل‌ها و بررسی وضعیت اولیه

ابتدا دو فایل جدید در پوشه پروژه خود ایجاد کنید. فایل اول auth.py (کد اصلی سیستم) و فایل دوم debug.log (فایل موقتی گزارش خطاها) نام دارد.

پس از ساخت فایل‌ها، دستور زیر را در ترمینال اجرا کنید:

git status

گیت در خروجی اعلام می‌کند که دو فایل در وضعیت Untracked قرار دارند. این یعنی گیت متوجه حضور آن‌ها شده است اما هیچ تاریخچه‌ای از آن‌ها ثبت نمی‌کند.

گام دوم: انتقال کدهای اصلی به محیط استیج

از آنجا که فایل debug.log یک فایل موقتی است و نباید ذخیره شود، فقط فایل اصلی را با دستور زیر به صف انتظار منتقل کنید:

git add auth.py

حالا اگر دوباره وضعیت پروژه را بررسی کنید، تغییرات را به دو رنگ متفاوت خواهید دید:

git status

فایل auth.py به رنگ سبز (در وضعیت Staged) تغییر یافته و آماده کامیت است، در حالی که فایل debug.log همچنان به رنگ قرمز (Untracked) باقی مانده است.

گام سوم: ثبت اولین کامیت

اکنون زمان آن است که از فایل موجود در محیط استیج یک اسنپ‌شات دائمی تهیه کنید. دستور کامیت را همراه با یک پیام استاندارد اجرا کنید:

git commit -m "feat: implement initial user authentication logic"

گیت تایید می‌کند که یک کامیت جدید با یک شناسه منحصربه‌فرد ساخته شده و فایل auth.py با موفقیت در تاریخچه پروژه ذخیره گردیده است.

گام چهارم: ویرایش مجدد و تکمیل چرخه

تصور کنید نیاز است تغییر کوچکی در کدهای سیستم ثبت‌نام ایجاد کنید. فایل auth.py را باز کرده و یک خط کد جدید به آن اضافه کنید. با اجرای دستور بررسی وضعیت:

git status

خواهید دید که وضعیت فایل auth.py از حالت قبلی به وضعیت Modified (تغییر یافته) تبدیل شده است. گیت متوجه تفاوت کدهای جدید با آخرین کامیت ثبت‌شده می‌شود.

برای ثبت نهایی این تغییر جدید، کل چرخه را با دستورات زیر کامل کنید:

git add auth.py
git commit -m "fix: resolve login redirect issue in auth module"

با اجرای این گام‌ها، شما یک چرخه کامل از جریان کار واقعی در شرکت‌ها شامل ساخت فایل، بررسی وضعیت، انتقال به استیج، ویرایش مجدد و ثبت کامیت‌های منظم و تفکیک‌شده را به طور عملی تمرین کرده‌اید.