Front-end Developer at Sepidz.com - lenus.org
چگونه یک پیغام git commit با معنا بنویسیم؟
در قسمت قبل شهاب ما رو با گیت آشنا کرد و فهمیدیم که گیت چیه؟ در این قسمت به اعماق کامیت ها در گیت میریم و خواهید دید که گیت چقدر هیجان انگیز هست!
نوشتن کامیت خوب یک هنر است! و این زمانی بیشتر خودشو نشون میده که در یک تیم مشغول به کار باشید یا اینکه بخواهید یک مروری بر آنچه که قبلا در پروژه انجام داده اید داشته باشید. خیلی وقتها می خواهیم با نوشتن یک پیغام نامفهوم یک کامیتی زده باشیم! ولی خب اگر بخواهید روی یک پروژه متن باز مشارکت کنید چی؟ یا اینکه درون یک تیم مشغول به کار باشید؟

قدرت گیت در کارهای تیمی بسیار مشخص تر خواهد بود. رعایت کردن یکسری استاندارد بین افراد یک پروژه می تواند روند کارها را سریعتر و اشتباهات را کاهش دهد. یکی از این استانداردها می تواند تدوین قوانینی برای نوشتن توضیحات برای Commitها در گیت باشد. [^]
در ادامه نوشته منظور از "کامیت (commit) با معنا" در واقع پیغام کامیت می باشد.
? هدف از نوشتن commit با معنا
- تولید خودکار فایل
CHANGELOG.md
توسط اسکریپت - در نظر نگرفتن بعضی از کامیت های بی اهمیت با git bisect (مانند مثل فورمت کردن کدها)
- داشتن اطلاعات بهتر و کاراتر هنگام بازببینی تاریخچه کامیت ها
تولید خودکار فایل CHANGELOG.md
توسط اسکریپت
فایلی است مارک داون که ما تغییرات هر نسخه منتشر شده (release) رو اونجا می نویسیم (مثال). و عمدتا سه قسمت داره: امکانات (features) جدید، رفع اشکال (bug) و تغییرات ایجاد شده (breaking changes).
که می توان اینها را توسط یک اسکریپت به شکل خودکار تولید کرد و لینک کامیت مربوطه هم کنار آن درج کنیم.
پرواضح است که خودمان نیز می توانیم فایل را تغییر دهیم اما می توان از اسکریپت برای تولید پایه و اساس فایل changelog بهره برد.
برای مثال دستور زیر لیستی از تمام موضوعات (خط اول هر پیغام کامیت) از اخرین انتشار (release)
git log <last tag> HEAD --pretty=format:%s
امکانات جدید نسخه جاری
git log <last release> HEAD --grep feature
شناخت کامیت های کم اهمیت
تغییراتی مانند فورمت کردن کد (اضافه/ حذف space ها، خط های خالی و فاصله گذاری indentation) یا فراموش کردن semi colon ها و نوشتن کامنت. پس زمانی که شما برای یک تغییر می گردید می توانید این کامیت ها را در نظر نگیرید. کامیتی است که منطق برنامه در آن عوض نمی شود.
وقتی از bisect استفاده می کنید، می توان از دستور زیر استفاده کرد
(git bisect skip $(git rev-list --grep irrelevant <good place> HEAD
داشتن اطلاعات بهتر و کاراتر هنگام بازببینی تاریخچه کامیت ها
کامیت های خوب تا حدی اطلاعات پایه ای را برایمان فراهم می کنند. برای مثال نگاهی به آخرین کامیت ها انگولار می اندازیم.
- (Fix small typo in docs widget (tutorial instruction)
- Fix test for scenario.Application - should remove old iframe
- docs - various doc fixes
- docs - stripping extra new lines
- Replaced double line break with single when text is fetched from Google
- Added support for properties in documentation
همین این پیام ها به نحوی مشخص می کند که تغییر کجا اتفاق افتاده است. اما هیچ قاعده (convention) مشترکی بین آنها دیده نمی شود. حال به این پیام (کامیت) ها نگاهی بیندازید:
- fix comment stripping
- fixing broken links
- Bit of refactoring
- Check whether links do exist and throw exception
- (Fix sitemap include (to work on case sensitive linux
آیا می توانید حدس بزنید که چه اتفاقی درون کدها افتاده است؟ این پیام ها محل انجام تغییرات را ذکر نکرده است. ممکن است تغییرات در قسمت هایی از کد از جمله (مستندات پروژه، کامپایلر و ...): docs, docs-parser, compiler, scenario-runner, …
بله ما هم می دانیم که به راحتی می توان تغییرات انجام شده را با بررسی فایل ها تغییر یافته اطلاعات لازم را بدست آورد، اما این روندی کند است. و البته با نگاهی به تاریخچه گیت (git log) می توان با کمی تلاش محل تغییرات را فهمید ولی باز از قاعده خاصی پیرو نمی کنند.
? قراردادی برای بهتر نوشتن پیام کامیت ها
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
برای مثال:
fix(middleware): ensure Range headers adhere more closely to RFC 2616
Add one new dependency, use `range-parser` (Express dependency) to compute
range. It is more well-tested in the wild.
Fixes #2310
هر خط از پیغام کامیت نباید بیشتر از 100 کاراکتر باشد. همین باعث می شود که خواندن متن کامیت هم در گیتهاب و هم در سایر ابزار های گیت آسان تر باشد. هر متن کامیت دارای سرآمد (header)، بدنه (body) و بخش زیرین (footer) است که توسط خط خالی (Blank line) از هم جدا می شود.
متن سرآمد
متن قسمت سرآمدیک خط است که به صورت خلاصه وارتوضیحاتی را در مورد تغییرات ارایه میدهد و شامل نوع (type)، محدوده [تغییرات] (scope) و موضوع (subject) می باشد.
مقادیر مجاز <type>
نوع تغییرات که کامیت شده را بیان می کند:
- افزودن یک ویژگی جدید به پروژه (feat (feature
- حل یک مشکل (fix (bug fix
- مستندات پروژه (docs (documentation
- فورمت کردن کد (...,style (formatting, missing semi colons
- refactor
- آزمون واحد و یکپارچه سازی (test (when adding missing tests
- کارهایی از قبیل اضافه کردن تسک های gulp و npm و... که تغییری در فایل های آزمون و src ایجاد نمی کنیم ?.(chore (maintain
مقادیر مجاز <scope>
محدوده هر چیزی می تواند باشد که محل انجام تغییرات را بیان می کند که در آن کامیت تغییر یافته اند. برای مثال: login, نام کامپوننت ، middleware، ... یا اگر محل مناسبی را برای تغییرات انجام شده نیافتید * می گذاریم.
متن <subject>
یک توضیح بسیار کوتاه در مورد تغییر انجام شده.
- از یک فعل امری و زمان حال استفاده کنید: برای مثال "change" و نه "changed" یا "changes"
- اولین حرف را بزرگ نمی نویسیم.
- اخر جمله . نمی گذاریم.
متن بدنه <body>
- همانند متن موضوع از یک فعل امری و زمان حال استفاده کنید: برای مثال "change" و نه "changed" یا "changes"
- دربرگیرنده انگیزه برای تغییر و بیان تفاوت با رفتار قبلی
متن بخش زیرین <footer>
تغییرات ایجاد شده Breaking changes
تمامی تغییرات ایجاد شده باید در قسمت Breaking changes فوتر آورده شود، که باید با کلمه BREAKING CHANGE با یک فاضله یا دو خط جدید. مابقی متن کامیت توضیحی است در مورد تغییرات و نکاتی برای توجیه و ارتقا به تغییرات جدید.
BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.
To migrate the code follow the example below:
Before:
...
After:
....
The removed `inject` wasn't generaly useful for directives so there should be no code using it.
ارجاع دادن به یک issue
اشکالات رفع شده (یا ایشو های بسته شده) باید در یک خط جداگانه در فوتر با پیشوند "Closes" نوشته شود.
Closes #234
یا چندین مورد را به این شکل می نویسیم:
Closes #123, #245, #992
مثال ها
feat($browser): onUrlChange event (popstate/hashchange/polling)
Added new event to $browser:
- forward popstate event if available
- forward hashchange event if popstate not available
- do polling when neither popstate nor hashchange available
Breaks $browser.onHashChange, which was removed (use onUrlChange instead)
fix($compile): couple of unit tests for IE9
Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.
Closes #392
Breaks foo.bar api, foo.baz should be used instead
کامیت های معنی دار در عمل
برای اینکه مطلب گفته شده روشن تر شود اجازه دهید که ابزار های لازم را برای این کار معرفی کنیم تا روند کار آسان تر و لذت بخش تر شود. برای این منظور مخزن بوت استرپ 4 راستچین را به نسخه بتا (آزمایش عمومی) به روزرسانی می کنیم.
قدم 1 : دانلود commitizen
اگر درون پروژه خود فایل package.json دارید کافیه است. با دستور زیر از طریق ترمینال بسته های لازم را دانلود کنید.
npm install -D commitizen cz-conventional-changelog
و سپس درون فایل package.json دو قسمت زیر را اضافه می کنیم.
"scripts": {
...
"commit": "git-cz"
}
.
.
.
,
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
}
و همچنین کد زیر را به فایل README.md اضافه می کنیم (کاملا اختیاری)
[](http://commitizen.github.io/cz-cli/)
حال با دستور git add
فایل های مورد نظر را انتخاب می کنیم. و سپس دستور npm run commit
رو می زنیم. سوالاتی را از ما می پرسد. که طبق مطالب اریه شده به راحتی می توان متن مناسب را بنویسیم.

به همین راحتی! حتی ایشو شماره 4 که باز کرده بودم را اتومات می بنده!

خوشحال می شویم مثل همیشه پیشنهادی، سوالی دارید؟ بپرسید
مطلب خوب و مفیدی بود.
امیدوارم ادامه بدید این مطالب رو
و مرسی از پکیجی که برای این کار معرفی کردی - خیلی کارو راحت تر میکنه
ممنون
خواهش می کنم :)