گیت برای دانشمند داده مدرن

منتشر شده در towardsdatascience به تاریخ ۶ می ۲۰۲۳
لینک منبع Git For the Modern Data Scientist: 9 Git Concepts You Can’t Ignore

معرفی

اکثر دانشمندان داده وقتی صحبت از گیت (Git) به میان می‌آید، احساس غریبی می‌کنند. مهندسان نرم‌افزاری هستند که در مورد چیزی به جز گیت-things صحبت نمی‌کنند و دانشمندان داده‌ای هستند که می‌گویند "ها؟"

که امروز این ماجرا متوقف می‌شود! از آنجایی که گیت یک ابزار ضروری برای همکاری است، من ۹ مورد از حیاتی‌ترین مفاهیم گیت را که دانشمندان داده باید مانند کف دست خود بشناسند، توضیح خواهم داد.

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

بیا شروع کنیم!

برای هزارمین بار…

شاید قبلاً چند صد بار آن را شنیده باشید، اما من با احتیاط اشتباه می‌کنم و برای چند صد و اولین بار آن را می‌گویم:

گیت یکی از حیاتی‌ترین ابزارها در توسعه سیستم‌های یادگیری ماشینی و هوش مصنوعی است.

اگر ایده شما از یک پروژه یادگیری ماشین یا علم داده شامل مدل‌هایی است که در نوت‌بوک‌هایی با فایل‌هایی با نام‌های خلاقانه مانند «notebook1»، «notebook2»، «notebook_final» و «notebook_final_final» پخته شده‌اند، پس Git را خسته نکنید.

با این حال، اگر قصد دارید مدل‌هایی را به کار بگیرید که دیگران بتوانند بدون میگرن از آن استفاده کنند، Git هزینه نسبتا کمی است.

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

علاوه‌بر این، Git به‌راحتی با سایر ابزارهای محبوب MLOpsمانند DVC برای کنترل نسخه داده ادغام می‌شود و آن را به ابزاری ضروری برای دانشمندان داده تبدیل می‌کند.

۰. مخزن

در اصل، یک مخزن این است:

این یک پوشه در دستگاه شما است. این می‌تواند هیچ فایلی، سه فایل یا صد فایل داشته باشد. تنها چیزی که برای تبدیل آن پوشه به یک مخزن Git نیاز است، فراخوانی git init در داخل آن است.

یک مخزن یادگیری ماشین معمولاً دارای پوشه‌هایی برای ذخیره داده‌ها، مدل‌ها و کدهایی برای بارگیری، تمیز کردن و تبدیل داده‌ها و همچنین انتخاب، آموزش و ذخیره مدل‌ها برای استقرار است.

فایل‌های متفرقه دیگری مانند پوشه .git برای فایل‌های داخلی Git و فراداده وجود خواهد داشت.

همه اینها یک مخزن واحد را تشکیل می‌دهند و Git معمولاً برای ردیابی آن‌ها کافی است.

۱. ردیابی‌شده، ردیابی‌نشده

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

این بدان معنی است که هر تغییری که در آینده در آن‌ها ایجاد کنید نیز پیگیری نخواهد شد. بنابراین، باید با اجرای git add path/to/file.py آن فایل‌ها را تحت نظارت Git قرار دهید.

پس از فراخوانی فایل‌های git add on، آن‌ها تحت Git-watch قرار می‌گیرند.

اگر می‌خواهید همه فایل‌ها را در مخزن اضافه کنید (اگرچه احتمال آن بسیار کم است)، می‌توانید git add.. را فراخوانی کنید.

همچنین مواردی وجود دارد که هرگز نمی‌خواهید فایل‌ها توسط Git ردیابی شوند. این زمانی است که شما یک فایل .gitignore ایجاد می‌کنید.

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

بقیه را مانند یک قهرمان اداره می‌کند.

پی‌نوشت: می‌توانید یک فایل .gitignore را در ترمینال با .gitignore ایجاد کنید و فایل‌ها/پوشه‌ها را با echo "filename" >> .gitignore در خطوط جدید به آن اضافه کنید.

۲. گیت کامیت

گیت کامیت (Git commit) چیز با ارزشی است. کل ایده کنترل نسخه بر اساس آن است.

وقتی git commit را در یک مخزن Git فراخوانی می‌کنید، از هر فایل ردیابی‌شده توسط Git برای آن زمان خاص یک عکس فوری می‌گیرید. به آن مانند یک کپسول زمانی با محتویات (نسخه‌های) پروژه خود از دوره‌های مختلف فکر کنید.

تمام commitهایی که انجام می‌دهید تاریخچه Git یا درخت Git شما را تشکیل می‌دهند، همانطور که در زیر نشان داده شده است.

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

سپس، می‌توانید صفحات این کتاب Git را از طریق commitها مرور کنید.

درست مانند یک نویسنده که برای نوشتن هر صفحه از کتاب خود تلاش زیادی می‌کند، شما نیز باید با احتیاط با کامیت‌های خود رفتار کنید.

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

توصیه سنتی: یک کامیت خوب دارای یک پیام آموزنده است که تغییرات ایجاد شده را توصیف می‌کند.

برخی از سناریوهای رایج برای انجام در یک پروژه یادگیری ماشین معمولی:

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

۳. منطقه صحنه

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

این شامل این است که به Git بگویید دقیقاً کدام تغییر را از کدام فایل می‌خواهید انجام دهید. گاهی اوقات، تغییرات جدید ممکن است از چندین فایل ایجاد شود و شما فقط بخواهید برخی از آن‌ها را commit کنید و بقیه را برای commit های بعدی بگذارید.

اینجاست که پرده‌ها را بلند می‌کنیم و محل صحنه‌سازی را آشکار می‌کنیم (جناسی در نظر گرفته شده):

ایده این است که قبل از اینکه دکمه commit را فشار دهید باید راهی برای بررسی مجدد، ویرایش یا لغو تغییراتی که می‌خواهید به تاریخچه Git خود اضافه کنید، داشته باشید.

افزودن تغییرات جدید به ناحیه مرحله بندی (یا به قول برخی بچه‌ها شاخص Git) به شما امکان می‌دهد این کار را انجام دهید. این ناحیه تغییراتی را که می‌خواهید در commit بعدی وارد کنید را در خود نگه می‌دارد.

فرض کنید هم clean.py و هم train.py را تغییر دادید. اگر تغییرات train.py را با git add train.py به قسمت مرحله اضافه کنید، commit بعدی فقط شامل آن تغییر خواهد شد. clean.pyاصلاح شده همانطور که هست باقی می‌ماند (تعهد نشده).

بنابراین، در اینجا یک گردش کار آسان برای شما وجود دارد:

ردیابی فایل‌های جدید با Git(فقط یک بار انجام می‌شود)

با git add change_file.extension تغییرات در فایل‌های ردیابی‌شده را به قسمت مرحله‌بندی اضافه کنید.

با git commit -m "Commit message" تغییرات ناحیه مرحله‌بندی را به تاریخچه انجام دهید.

۴. هش‌ها و برچسب‌ها

به غیر از پیام‌ها، تمام commit‌های Git دارای هش هستند تا بتوانید راحت‌تر به آن‌ها اشاره کنید.

هش رشته‌ای با ۴۰ کاراکتر هگزا دسیمال است که به هر یک از تعهدات شناسه‌های منحصربه‌فرد می‌دهد، مانند 1a3b5c7d9e2f4g6h8i0j1k2l3m4n5o6p7q8r9s0t.

آن‌ها جابجایی بین commitها (نسخه‌های مختلف پایه کد شما) را با git checkout HASH بسیار آسان‌تر می‌کنند. هنگام تعویض نیازی نیست هش کامل را بنویسید. فقط چند کاراکتر اول هش که آن را منحصر‌به‌فرد می‌کند کافی است.

می‌توانید تمام commit‌هایی را که با هش‌های آن‌ها انجام داده‌اید با استفاده از git log فهرست کنید (این نشان‌دهنده نویسنده و پیام commit است).

برای فهرست کردن فقط هش و پیام بدون به‌هم ریختن صفحه نمایش خود، می‌توانید از git log --oneline استفاده کنید.

اگر هش‌ها شما را می‌ترسانند، تگ‌های Git نیز وجود دارد. تگ Git یک نام مستعار دوستانه است که می‌توانید به برخی از تعهدات مهم (یا هر کدام) بدهید تا آن‌ها را راحت‌تر به خاطر بسپارید و به آن‌ها ارجاع دهید.

می‌توانید از دستور «git tag» برای تخصیص برچسب‌ها به commit‌های مهم استفاده کنید، مانند مواردی که حاوی یک ویژگی مهم یا انتشار کد قابل توجهی هستند (به‌عنوان‌مثال، v1.0.0). علاوه‌بر‌این، می‌توانید commitی را که بهترین مدل شما را نشان می‌دهد، مانند "random_forest_best" برچسب‌گذاری کنید.

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

برای روشن شدن، دستور git tag 'tag_name' تنها یک تگ به آخرین commit اضافه می‌کند. اگر می‌خواهید یک تگ به یک commit خاص اضافه کنید، باید هش commitرا در انتهای دستور، بعد از نام تگ مشخص کنید.

۵. شعبه (شاخه)

پس از commitها، شاخه‌ها نان و کره گیت هستند. ۹۹٪ مواقع، شما در یک شعبه Git کار خواهید کرد.

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

می‌توانید شاخه‌های دیگر را به عنوان واقعیت‌های جایگزین پایه کد خود در نظر بگیرید.

با ایجاد یک شاخه Git، می‌توانید ویژگی‌ها، ایده‌ها و راه‌حل‌های جدید را بدون ترس از خراب کردن پایه کد خود آزمایش و امتحان کنید.

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

شاخه‌های گیت بسیار ارزان هستند. وقتی شاخه git new_branch_name را فرا می‌خوانید، Git یک کپی شبه از شاخه اصلی بدون کپی کردن هیچ یک از فایل‌ها ایجاد می‌کند.

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

۶. هد (Head)

یک مخزن Git می‌تواند چندین شعبه و صدها commit داشته باشد. بنابراین ممکن است این سوال عالی را مطرح کنید "Git چگونه می‌داند که در کدام شاخه یا commit هستید؟". Git از یک اشاره‌گر ویژه به نام HEAD استفاده می‌کند و این پاسخ شما است.

در اصل، HEAD شما هستید. هر کجا که باشید، HEAD شما را در Git دنبال می‌کند. ۹۹٪ مواقع، HEAD به آخرین commit در شعبه فعلی اشاره می‌کند.

اگر یک commitجدید ایجاد کنید، HEAD به سمت آن حرکت خواهد کرد. اگر به یک شاخه جدید یا قدیمی تغییر دهید، HEAD به آخرین commit در آن شاخه سوئیچ می‌کند.

یکی از موارد استفاده HEAD هنگام مقایسه تغییرات در commitهای مختلف با یکدیگر است. برای مثال، فراخوانی git diff HEAD~1 آخرین commit را با commit بلافاصله قبل از آن مقایسه می‌کند.

این همچنین به این معنی است که نحو HEAD~n در Git به nامین commit قبل از هر کجا که HEAD باشد اشاره دارد.

همچنین ممکن است به حالت HEAD جدا‌شده مخوف بروید. این بدان معنا نیست که Git مسیر شما را گم کرده است و نمی‌داند کجا را نشان دهد.

حالت HEAD جدا زمانی رخ می‌دهد که به جای استفاده از git checkout branch_name از دستور git checkout HASH برای بررسی یک commit خاص استفاده می‌کنید. این امر HEAD را مجبور می‌کند که دیگر به نوک یک شاخه اشاره نکند، بلکه به یک commitخاص در وسط تاریخچه commit اشاره کند.

هر تغییر یا کامیتی که در حالت جدا شده HEAD انجام دهید، ایزوله یا یتیم خواهد بود و بخشی از تاریخچه Git شما نخواهد بود. دلیلش این است که HEAD رئیس شعبه است. به شدت دوست دارد خود را به نوک شاخه یا سر بچسباند، نه به شکم یا پاهایش.

بنابراین، اگر می‌خواهید تغییراتی را در حالت HEAD جدا انجام دهید، باید git switch -c new_branch را فراخوانی کنید تا یک شاخه جدید در commit فعلی ایجاد کنید. این شما را از حالت خارج می‌کند و HEAD را حرکت می‌دهد.

گرفتن HEAD به شما کمک می‌کند تا در هر درخت Git درهم حرکت کنید.

۷. ادغام

بنابراین، پس از ایجاد یک شعبه جدید چه اتفاقی می‌افتد؟

اگر آزمایش شما با شاخه git -d branch_name همراه نباشد، آن را کنار می‌گذارید؟ یا یک ادغام Git افسانه‌ای انجام می‌دهید؟

اساسا، ادغام Git یک مهمانی فانتزی است که در آن دو یا حتی چند شاخه با هم جمع می‌شوند تا یک شاخه ضخیم‌تر ایجاد کنند.

هنگامی که شاخه‌ها را ادغام می‌کنید، Git کد را از هر شاخه می‌گیرد و آن‌ها را در یک پایه کد منسجم ترکیب می‌کند.

اگر تغییرات همپوشانی در شاخه‌ها وجود داشته باشد، یعنی هر دو شاخه خطوط ۵-۱۰ را در train.py تغییر داده باشند، Git یک تضاد ادغام ایجاد می‌کند.

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

حل تعارضات ادغام شده بدون فحش دادن و حرص خوردن، یک مهارت نادر است که در طول زمان توسعه یافته است. بنابراین، من زیاد در مورد آن‌ها صحبت نمی‌کنم.

۸. مخفی کردن

من تمایل دارم هنگام کدنویسی خیلی خراب کنم. ایده‌ای به ذهنم خطور می‌کند؛ من آن را امتحان می‌کنم تا متوجه شوم که این یک آشغال است.

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

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

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

بعد از اینکه تغییرات خود را مخفی کردید، می‌توانید طبق معمول به کار خود ادامه دهید. هنگامی که می‌خواهید دوباره آن‌ها را بازیابی کنید (در هر مکانی)، می‌توانید از دستور git stash application یا git stash pop استفاده کنید. این دستورات تغییراتی را که قبلاً در stash ذخیره شده بودند در فهرست کاری بازیابی می‌کنند.

توجه داشته باشید که دستور git stash فقط تغییرات ایجاد‌شده در فایل‌های ردیابی‌شده را ذخیره می‌کند و نه فایل‌های ردیابی‌نشده. برای ذخیره فایل‌های ردیابی شده و ردیابی نشده، باید از پرچم -u با دستور git stash استفاده کنید. فایل‌های نادیده گرفته‌شده در انبار گنجانده نمی‌شوند.

۹. گیت هاب GitHub

بنابراین، به این سوال قدیمی می‌رسیم - تفاوت بین Git و GitHub چیست؟

این مثل این است که فرق بین برگر و چیزبرگر را بپرسید. Git یک سیستم کنترل نسخه است که مخازن را ردیابی می‌کند. از سوی دیگر، GitHub یک پلت‌فرم مبتنی‌بر وب است که برای ذخیره مخازن تحت کنترل Git به‌صورت آنلاین استفاده می‌شود.

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

بنابراین، GitHub را به‌عنوان یک آینه از راه دور مخزن محلی خود در نظر بگیرید که مردم می‌توانند آن را شبیه‌سازی کنند، از آن انشعاب بگیرند، و درخواست‌های دیگر را پیشنهاد دهند.

جمع‌بندی

بفرمایید! امیدوارم این مقاله به شما وضوح فوق‌العاده‌ای در مورد این ۹ مفهوم Gitداده باشد. به خصوص، من متوجه می‌شوم که مفهوم HEAD برای بسیاری از مردم یک خراش واقعی است :)

برای اطلاعات بیشتر (البته بسیار خسته‌کننده) حتما اسناد رسمی Git را بخوانید.

با تشکر از شما برای خواندن این مقاله!

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