امیر باباعلی
امیر باباعلی
خواندن ۸ دقیقه·۳ سال پیش

قدم به قدم تا پیام‌های بهتر برای کامیت‌های گیت

نوشته‌ی اصلی از Natalie Pina


مقدمه

خیلی از برنامه‌نویس‌ها اوایل آشنایی و بکارگیری Git در درک روال کار آن دچار مشکل می‌شوند. این مسئله به خصوص در برخورد با پیام‌هایی که برای کامیت‌ها باید نوشت نمود پیدا می‌کند. بسیاری در مورد اینکه تغییراتی که روی کد خود اعمال کرده‌اند و دلایل این تغییرات را چگونه می‌توانند به خوبی در چند سطر خلاصه کنند دچار تردید می‌شوند.

این نوشته سعی می‌کند راه‌هایی برای نوشتن پیام‌های بهتر را به شما نشان دهد؛ البته با این فرض که مبانی و روال کار گیت را می‌شناسید. در غیر این صورت، بهتر است ابتدا به سراغ منابعی مانند Git Handbook بروید.

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


چرا نوشتن پیام خوب برای کامیت مهم است؟

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

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

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

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


ساختار پیام کامیت

پیام ساده:

git commit -m <message>

پیام دارای جزئیات:

git commit -m <title> -m <description>
نمونه‌ی یک پیام ساده‌ی کامیت
نمونه‌ی یک پیام ساده‌ی کامیت

پنج گام برای نوشتن پیام‌های بهتر

به طور خلاصه می‌توان این راهنما را به این صورت بیان کرد:

  1. استفاده از حروف بزرگ (Capitalization) و نقطه‌گذاری (Punctuation): پیام را با حرف بزرگ (حرف اول کلمه‌ی اول) شروع کنید و آن را با نقطه‌گذاری تمام نکنید. اگر از قواعد Conventional Commits استفاده می‌کنید تمام پیام را با حروف کوچک (lowercase) بنویسید.
  2. لحن پیام: در عنوان (subject) از جمله‌ی امری استفاده کنید؛ بدین ترتیب لحنی دستوری یا درخواستی به پیام خود می‌بخشید. مثال:‌ Add fix for dark mode toggle state
  3. نوع کامیت: نوع کامیت را مشخص کنید. بهتر است مجموعه‌ای معین و ثابت از کلمات برای بیان تغییرات ایجاد شده داشته باشید، مثلا Bugfix (رفع ایراد)، Update (بروزرسانی)، Refactor (بازآرایی)،‌ Bump (نسخه‌زنی) و غیره. برای جزییات بیشتر به بخش Conventional Commits در ادامه‌ی نوشته مراجعه کنید.
  4. طول پیام: در حالت ایده‌آل سطر اول نباید بیشتر از ۵۰ کاراکتر و بدنه‌ی پیام حداکثر باید ۷۲ کاراکتر باشد.
  5. محتوا: جملات شفاف و سرراست به کار ببرید. سعی کنید تکه‌کلام‌ها و کلمات و عبارات زایدی مثل گرچه، شاید، فکر می‌کنم،‌ به نوعی و ... را از جملات خود حذف کنید. مثل یک روزنامه‌نگار فکر کنید.

چگونه روزنامه‌نویس درون خود را پیدا کنیم؟

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

در مورد پیام‌های کامیت‌ها حتما باید به پرسش‌های چه و چرا پاسخ داد. برای رسیدن به پیامی خوش‌ساخت و فکر شده برای کامیت خود باید این موارد را در نظر گرفت:

  • چرا این تغییرات را اعمال کرده‌ام؟
  • این تغییرات چه تاثیراتی داشته‌اند؟
  • چرا به این تغییرات نیاز بود؟
  • این تغییرات در ارتباط با چه چیزی می‌باشند؟

همیشه باید فرض کرد مخاطب (خواننده‌ی کد و پیام) قادر به درک تغییرات ایجاد شده طی کامیت نیست، و به داستان (User Story) بیان کننده‌ی دلیل و زمینه‌ی تغییرات نیز دسترسی ندارد. نباید کد خود را بدیهی و بی‌نیاز از توضیح دانست.

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

همیشه چرایی ایجاد هر تغییر را روشن و میزان اهمیت و تاثیر آن بر عملکرد برنامه را مشخص کنید.

دو پیام زیر را مقایسه کنید:

git commit -m 'Add margin'
git commit -m 'Add margin to nav items to prevent them from overlapping the logo'

ناگفته پیداست کدام یک برای مخاطبان آتی مناسب و سودمند خواهد بود.

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

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

افزونه‌‌هایی از قبیل Git Blame، Git History و GitLens در VSCode اطلاعات مربوط به هر کامیت، اعم از کسی که تغییرات را اعمال کرده،‌ تاریخ و زمان ایجاد تغییرات و نیز پیام نوشته شده برای کامیت را به صورت کامنت درون کد نشان می‌دهد. تصور کنید این کار چقدر می‌تواند در ریشه‌یابی ایراد رخ داده یا تغییرات اعمال شده راهگشا باشد. این نمونه‌ی خوبی برای نمایش زمانیست که پیام‌های کامیت‌ها به برنامه‌نویس‌های آتی کمک می‌کند و مفید واقع می‌شوند.

کارکرد افزونه‌ی Git Blame
کارکرد افزونه‌ی Git Blame

کامیت‌های قراردادی - Conventional Commits

اکنون که ساختار پایه‌ی یک پیام خوب برای کامیت را بررسی کرده‌ایم، بهتر است برای کمک به ارائه‌ی جزییاتی بیشتر در نوشتن پیام‌هایی مطمئن و یکپارچه با Conventional Commits آشنا شویم.
Conventional Commits یک قرارداد قالب‌بندیست که مجموعه‌ای قوانین برای بیان قاعده‌مند ساختاری یکدست برای پیام‌های کامیت ارائه می‌کند. برای نمونه:

<type>[optional scope]: <description> [optional body] [optional footer(s)]

نوع (type) کامیت الزامیست و می‌تواند شامل موارد زیر باشد:

  • feat – تغییرات شامل یک ویژگی جدید می‌باشند
  • fix – تغییراتی که شامل رفع یک ایراد می‌باشند
  • chore – تغییراتی که مربوط به ویژگی یا ایرادی نمی‌باشند و فایل‌های منبع و تست را نیز تغییر نمی‌دهند (برای مثال بروزرسانی وابستگی‌ها)
  • refactor – بازآرایی کد که نه ایرادی را رفع و نه ویژگی جدیدی را اضافه می‌کند
  • docs – readme تغییرات مربوط به بروزرسانی مستنداتی مانند فایل
  • style – تغییراتی که تاثیری روی معنای کد ندارند، و عمدتا مربوط به قالب‌بندی کد از قبیل فضاهای خالی و سطرهای فاصله و سمیکولون‌های جامانده و غیره می‌باشند
  • test – تغییراتی که شامل ایجاد آزمونی جدید یا تصحیح آزمون‌های قبلی می‌باشند
  • perf – تغییراتی که برای بهبود کارایی می‌باشند
  • ci – (continuous integration) تغییراتی که مربوط به یکپارچه سازی مداوم می‌باشند
  • build – (build system) تغییراتی که مربوط به سیستم ساخت یا وابستگی‌های بیرونی می‌باشند
  • revert – بازگردانی یکی از کامیت‌های پیشین

موضوع (description) نیز الزامیست و باید تماما با حروف کوچک نوشته شود و دارای محدودیت کاراکتری باشد تا کاربر را به خلاصه‌نویسی وادار و تشویق کند.

بدنه‌ی پیام (body) که اختیاریست باید برای ارائه‌ی جزییاتی که در محدودیت کاراکتر موضوع نمی‌گنجند به کار رود. همچنین این بخش جای مناسبیست که به صورت زیر تغییری شکننده (breaking change) که در کامیت وجود دارد را تشریح و دلیل آن را بیان کرد:

BREAKING CHANGE: <description>

پاورقی (footer) نیز اختیاریست. می‌توان از آن برای مشخص کردن شناسه‌ی داستان‌هایی (User Story) که در نتیجه‌ی این تغییرات بسته می‌شوند استفاده کرد.


نمونه‌ای کامل از Conventional Commit

fix: fix foo to enable bar This fixes the broken behavior of the component by doing xyz. BREAKING CHANGE Before this fix foo wasn't enabled at all, behavior changes from <old> to <new> Closes D2IQ-12345

برای اطمینان از اعمال این قرارداد روی تمامی کامیت‌ها، می‌توان با استفاده از ابزارهایی مانند Commitizen این قواعد را در محیط برنامه‌نویسی اعمال کرد تا هر کامیت پیش از ثبت توسط آن‌ها بررسی شود.

همچنین برای کمک به پذیرش و اشتراک این قرارداد میان برنامه‌نویسان، بهتر است این قواعد را در یک فایل مخصوص یا فایل readme در پروژه ثبت کرد.
Conventional Commits به ویژه در هماهنگی با نسخه‌زنی معنایی (semantic versioning)، که بر اساس نوع کامیت نسخه‌ی مناسب برای عرضه (release) را بروزرسانی می‌کند، عملکرد بسیار خوبی دارد. برای مطالعه‌ی بیشتر در مورد Conventional Commits می‌توانید به اینجا مراجعه کنید.


مقایسه‌ی پیام‌های کامیت

پیام‌های زیر را بررسی کنید و سعی کنید قواعد رعایت شده در هر یک را تشخیص دهید.

خوب

  • feat: improve performance with lazy load implementation for images
  • chore: update npm dependency to latest version
  • Fix bug preventing users from submitting the subscribe form
  • Update incorrect client phone number within footer body per client request

بد

  • fixed bug on landing page
  • Changed style
  • oops
  • I think I fixed it this time?
  • empty commit messages

جمع‌بندی

نوشتن پیام‌های مناسب برای کامیت‌ها مهارتی بسیار سودمند است که تقویت و بهره‌گیری آن به ارتباط و همکاری بهتر میان اعضای تیم کمک می‌کند. کامیت‌ها بایگانی تغییرات می‌باشند، اما می‌توانند مانند یک نسخه‌ی خطی تاریخی ما را در رمزگشایی گذشته و تصمیم‌گیری منطقی در آینده یاری کنند.

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

gitcommit messageConventional Commitsگیت
شاید از این پست‌ها خوشتان بیاید