Dörd Git əmri kommit tarixçənizin sənədləşmə, yoxsa sadəcə səs-küy olduğunu bir dəqiqədən az vaxtda göstərir. Bu əmrləri öz repozitoriyamda işlətdim və nəticə ürəkaçan olmadı: 24 commitdən heç birində gövdə yox idi, 11 mövzu sətri 72 simvol həddini aşırdı, ən uzunu isə 2550 simvol idi. Əslində bu, Git-in birsətirlik xülasə üçün nəzərdə tutduğu sahəyə sıxışdırılmış beş abzaslıq izah idi. Bu yazı həmin auditdir. Burada istifadə etdiyim əmrləri, repozitoriyamdan real nəticələri, pozulan qaydaları, Conventional Commits və öz `000-` prefiksim haqqında dürüst fikirlərimi, eləcə də sonradan keçdiyim commit şablonunu paylaşacağam.
TL;DR
- Dörd Git əmri istənilən repozitoriyanı bir dəqiqədən az müddətdə yoxlayır: neçə commitdə gövdə var, mövzu sətirləri 50/72 qaydasına nə dərəcədə uyğundur, ən uzun mövzu hansıdır və commit mesajları adətən hansı feillə başlayır.
- Əsas qayda 50 simvol limiti deyil, boş sətirdir. Mövzu qısa xülasə verir, gövdə isə səbəbi izah edir. Git-in göstərdiyi görünüşlərin demək olar ki, hamısında yalnız mövzu sətri görünür.
- 000- kimi nömrə prefiksi həqiqətən faydalı etiket ola bilər. Amma bu, sadəcə göstəricidir, struktur deyil. Heç bir rəqəm commitin niyə mövcud olduğunu izah edə bilməz.
Kommit tarixçənizi dörd əmrlə yoxlayın
Dörd əmr reponun tarixçəsi haqqında demək olar hər şeyi deyir: neçə kommitdə gövdə var, mövzu sətirləri 50/72 qaydasına necə düşür, ən pisi nə qədər pisdir və mövzularınız hansı sözlə başlayır. Onları ən az fəxr etdiyiniz repoda işlədin.
1. Ümumiyyətlə neçə kommitdə gövdə var?
echo "$(git log -z --format='%b' | tr -d '\n' | tr '\0' '\n' | grep -c .) of $(git rev-list --count HEAD)"2. Mövzu sətirləri 50/72-yə necə düşür?
git log --format='%s' | awk '{n=length}
n<=50 {a++} n>50 && n<=72 {b++} n>72 {c++}
END {printf " <=50 : %d\n 51-72: %d\n >72 : %d\n", a, b, c}'3. Ən pisi nə qədər pisdir?
git log --format='%s' | awk '{ if (length > m) m = length } END { print m " characters" }'4. Mövzularınız hansı sözlə başlayır?
git log --format='%s' | awk '{print $1}' | sort | uniq -c | sort -rn | head -5Bu dörd əmr bu saytın reposu üçün, 24 kommit dərinliyində, bunu çap etdi:
0 of 24
<=50 : 13
51-72: 0
>72 : 11
2550 characters
4 Updated
3 Integrated
2 Made
2 Fixed
2 CreatedDörd nəticə, ağrı dərəcəsinə görə.
Heç bir kommitdə gövdə yoxdur. Nə qısası, nə pisi. Sıfır. Bu layihə haqqında yazdığım hər izah mövzu sətrində yaşayır - git-in xülasə üçün ayırdığı sahədə.
Ortada heç nə yoxdur. On üç mövzu 50 simvola sığır, on biri 72-ni keçir. Düşünülmüş xülasənin adətən düşdüyü 51-72 aralığı boşdur. Bu boşluq əsas göstəricidir: boş orta o deməkdir ki, heç kim mesajı ölçüyə salmaq üçün redaktə etmir. Hər kommit ya iki saniyəyə yazılmış qaralama, ya da gövdə əvəzinə yazılmış esseydir.
Ən pisi 2550 simvoldur. Miqyas üçün: git log --oneline hər kommitə bir sətir çap edir. İyirmi dörd kommit iyirmi dörd sətir olmalıdır. 120 sütunluq terminalda mənimki 129 sətir tutur və bunun 22-si tək bir kommitin payına düşür:
git log --oneline | awk '{ rows += int(length/120)+1 } END { print rows " rows for " NR " commits" }'
# 129 rows for 24 commitsEkrandan kənara çıxan "hər kommitə bir sətir" görünüşü artıq görünüş olmaqdan çıxıb.
24 kommitdə üç feil forması. On doqquz mövzu keçmiş zamandadır (Updated, Fixed, Integrated), ikisi əmr formasındadır (Create projects page), ikisi isə indiki zamanın üçüncü şəxsindədir (Replaces, Moves). Mən üçünü seçmədim; üç dəfə sürüşdüm və heç vaxt fərq etmədim, çünki iş axınımda heç nə mənə bu siyahını göstərmirdi.
Sonuncu bənd hamısının dürüst kök səbəbidir. Bunların heç biri qaydaları bilmədiyim üçün baş vermədi. Öz tarixçəmə bir dəfə də siyahı kimi baxmadığım üçün baş verdi. Audit qırx saniyə çəkir, mən isə onu iyirmi dörd kommit ərzində bir dəfə də işlətməmişdim. Bu, 407 sətirlik agent iş jurnalı oxunmaz olanda qarşılaşdığım eyni uğursuzluqdur: heç kimin geri oxumadığı qeyd səssizcə doğru olmaqdan çıxır.
İşlətməyə dəyən daha iki əmr
Reponuzda birdən çox iştirakçı varsa, bunları da əlavə edin:
# heç nə deməyən mövzular - klassik doldurucu feillər, tək və ya demək olar tək
git log --format='%s' | grep -icE '^(wip|update|fix|misc|stuff|changes|minor|cleanup)s?\.?$'
# kim gövdə yazır, kim yazmır
git log --format='%an' | sort | uniq -c | sort -rnƏsas qayda boş sətirdir
Git kommit mesajı boş sətirlə ayrılan iki hissədən ibarətdir: dəyişikliyi xülasə edən mövzu və onu izah edən gövdə. Qalan hər şey - 50 simvol hədəfi, 72 simvol limiti, əmr forması - bu bölgüyə xidmət etmək üçün mövcuddur. Bölgünü düzgün qurun, qalanı əsasən öz-özünə gələcək.
Bu qədər az kommitdə gövdə olmasının səbəbi tənbəllik deyil. Səbəb odur ki, git commit -m "..." fiziki olaraq gövdə yaza bilmir. -m bayrağı mesajı götürüb bütünlüklə mövzuya qoyur, yəni -m vərdişi heç vaxt gövdə yazmamaq vərdişidir. git commit sənədi bunu açıq yazır və iki çıxış yolu var:
# redaktoru açın: mövzu, boş sətir, sonra gövdə
git commit
# ya da bir əmrdə qalın: ikinci -m gövdəni başladır
git commit -m "Open content images full size in an overlay" \
-m "Galleries rendered at layout width, so a dashboard screenshot was unreadable on a phone."Mövzu niyə bu qədər ağırlıq daşıyır
Git-in verdiyi demək olar hər görünüş mövzunu göstərir və gövdəni atır. git log --oneline, git shortlog, git rebase -i içindəki siyahı, git log --graph içindəki birsətirlik xülasələr, GitHub və GitLab-dakı kommit siyahısı. Gövdəniz git show işlədəcək bir nəfər üçün yazılır; mövzunuz isə qalan hamı üçün, həmişəlik.
50 və 72 buradan gəlir. Bu cütlük adətən Tim Pope-un 2008-ci ildəki kommit mesajları haqqında qeydinə aid edilir və çoxlarına Chris Beams-in kommit mesajı yazmaq bələdçisi vasitəsilə çatıb: 50 simvolu hədəfləyin, 72-ni tavan sayın. Hər iki rəqəmin arxasında konkret səbəb var.
- 72 GitHub-ın təslim olduğu yerdir. Daha uzun başlıqlar kommit siyahısında kəsilir və quyruq klikləməli olduğunuz üç nöqtənin arxasında gizlənir.
- 72 həm də terminala sığır.
git logmesajı düz dörd boşluq içəri çəkir.git log -1 | cat -Aişlədin və onları sayın. 72 simvolluq sətir bu boşluqla birlikdə hələ də 80 sütuna ehtiyatla sığır. - 50 limit deyil, məcburedici funksiyadır. Xülasə 50 simvola sığmırsa, bu adətən kommitin iki iş gördüyünə işarədir.
Əmr forması və mübahisəni bitirən cümlə
Mövzunu əmr kimi yazın: Add, Fix, Move, Remove. Added yox, Adds da yox. Mübahisəni bir cümlə bitirir:
If applied, this commit will _____.
If applied, this commit will add the contact form düzgün oxunur. If applied, this commit will added the contact form isə yox. Git öz mesajlarını da belə yazır - Merge branch 'main', Revert "Add the contact form" - ona görə əmr formasındakı mövzular git-in sizin üçün yaratdıqlarının yanında uyğun oturur.
Mənim iyirmi dörd mövzumdan on doqquzu bu yoxlamadan keçmir.
Nəyi deyil, niyəni izah edin
Diff onsuz da hər kəsə nəyin dəyişdiyini göstərir. O, niyəni, əvvəlcə nə sınadığınızı və qəsdən nəyə toxunmadığınızı göstərə bilmir. Bu, gövdənin işidir və heç bir alətin sonradan bərpa edə bilmədiyi hissədir.
Yazmağa dəyən gövdə adətən üç şeyə cavab verir: əvvəl vəziyyət necə idi, bu kommit ona nə edir və nədən imtina etdiniz. Kommit bir baq düzəldirsə, gövdə həmin baqın istifadəçiyə real olaraq nə etdiyini deməlidir - "parser ən azı bir token olduğunu güman edirdi, ona görə boş fayl buildi çökdürürdü" - çünki on səkkiz ay sonra bu cümlə növbəti oxucu ilə bütün problemi sıfırdan yenidən çıxarmaq arasında duran yeganə şey olacaq.
Conventional Commits: nə verir və nəyə başa gəlir
Conventional Commits ən geniş yayılmış kommit qaydasıdır və spesifikasiyanın 1.0.0 versiyası bir şablona sığır:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]Yalnız iki tip məcburidir: düzəliş üçün fix və yeni imkan üçün feat, bunlar semantik versiyalamanın PATCH və MINOR səviyyələrinə uyğun gəlir. Spesifikasiya başqalarına da icazə verir, geniş işlənən dəst isə build, chore, ci, docs, style, refactor, perf, test və revert-dir. Sındırıcı dəyişiklik ya BREAKING CHANGE: altlığı ilə, ya da feat(api)!: drop the v1 endpoint kimi iki nöqtədən əvvəl nida işarəsi ilə göstərilir. Altlıqlar git-in trailer formatına tabedir - defisli token, ayırıcı, dəyər - ona görə Reviewed-by: Ada və Refs: #219 git-in öz trailer-ləri kimi oxunur.
Praktikada:
fix(auth): reject expired refresh tokens
The refresh endpoint compared the expiry to the token issue time
instead of the current time, so an expired token minted a fresh
access token indefinitely.
Refs: #412
BREAKING CHANGE: refresh responses now return 401 instead of 200
with an error body.Əslində nə əldə edirsiniz
Formatın mənası onun maşınla oxunan olmasıdır. Bu üç konkret şey verir:
- Yazmadığınız changelog. Alətlər kommitləri tipə görə qruplaşdırır və buraxılış qeydlərini tarixçənin özündən düzəldir.
- Qərar vermədiyiniz versiya artımı.
fixpatch-i,featminor-u, sındırıcı dəyişiklik isə major-u avtomatik qaldırır. - Filtrləyə bildiyiniz tarixçə.
git log --grep '^feat'real cavabı olan real sualdır.
Nəyə başa gəlir
Dürüst əks tərəf odur ki, hər üç fayda formatı istehlak edən bir alət tələb edir. Heç nə sizin changelog-unuzu yaratmırsa və heç nə versiyanı qaldırmırsa, Conventional Commits gəlirsiz adlandırma mərasimidir. Üç uğursuzluq ssenarisi daim təkrarlanır:
chore:zibilxanaya çevrilir. Açıq-aydın nə imkan, nə də düzəliş olan hər şey oraya düşür və tip məlumat daşımaqdan çıxır.- Hər kommitdə uydurulan scope səs-küydür. Scope yalnız sabit, razılaşdırılmış siyahıdan gələndə faydalıdır. Sərbəst scope-lar eyni qovluq üçün
feat(ui),feat(frontend)vəfeat(components)verir. - Tip səbəb deyil.
fix(auth):kateqoriyanı bildirir. O, hələ də baqın niyə mövcud olduğunu demir. Bunu gövdə edir, prefiks isə izahın artıq verildiyi hissini yarada bilər.
Seçim
Conventional Commits | Sıra prefiksi | Qaydasız | |
|---|---|---|---|
Avtomatik changelog | Bəli | Xeyr | Xeyr |
Avtomatik versiya artımı | Bəli | Xeyr | Xeyr |
Niyyətə görə filtr | Bəli, tipə görə | Xeyr | Xeyr |
Repodan kənarda daşınan etiket | Zəif | Güclü | Yoxdur |
Qurulma xərci | Alət və hook | Sıfır | Sıfır |
Nəzərə alınmayanda | Səslə, CI buraxmır | Səssiz, boşluq görünür | Bilinmədən |
Əksəriyyət üçün ilk sətir həll edir. Aşağıda nəsə formatı istehlak edirsə, Conventional Commits götürün. Əks halda tutacağınız bir qayda seçin və gücü gövdəyə sərf edin.
000 - qaydası, dürüst qiymətləndirmə
Mənim öz qaydam sıfırla doldurulmuş sıra nömrəsidir: 000 - Initialized app, sonra 001, 002, bu gün isə 023. O, heç bir standartda yoxdur. Nə Conventional Commits-də, nə git-in öz SubmittingPatches sənədində var, və mən onu adı olan bir qayda kimi heç yerdə sənədləşmiş tapmadım. Bu, ev üslubudur və ev üslubunun nəyi bacarıb-bacarmadığını aydın demək lazımdır.
Mənə həqiqətən nə verir
Tarixçənin yenidən yazılmasına dözən etiket. Qısa hash-lər dözmür. Budağı rebase edin - bütün hash-lər dəyişir; iki kommiti squash edin - biri mövcud olmaqdan çıxır. 013 müştəriyə yazılan mesajda, tapşırıq təsvirində və üç ay əvvəl yazılmış qeyddə hələ də eyni dəyişikliyi bildirir. Repodan kənara daşınan bu xüsusiyyət ən güclü arqumentdir və o, kiçik deyil.
Görünən boşluq. Nömrə çatmırsa, nəsə squash olunub, atılıb və ya heç göndərilməyib. Çatmayan hash görünmür; çatmayan nömrə ardıcıllıqdakı deşikdir.
Bölünmüş dəyişikliyi işarələmək yolu. Mənim iki kommitim 012 və 013-dür, eyni Sanity inteqrasiyası iki yerə bölünüb, ikinci mövzu isə Part 2: ilə başlayır. Məhz həmin inteqrasiya bu gün bu saytdakı keysləri render edir. Nömrələr əlaqəni bir baxışda oxunaqlı etdi. Conventional Commits-də bunun qarşılığı yoxdur - iki feat(sanity): kommiti siyahıda əlaqəsiz görünür.
Düzgün yerdə bir az sürtünmə. Növbəti nömrəni seçmək əvvəlkinə baxmaq deməkdir, bu isə loga baxmaq deməkdir. Bu, əksəriyyətin öz tarixçəsinə ayırdığından çox diqqətdir.
Mənə nə vermir
Bu göstəricidir, struktur deyil. O, sıralayır və adlandırır; səbəbi saxlaya bilmir. Və bu, neytral məhdudiyyət deyil - məncə, bu yazının əvvəlindəki audit nəticəsinin birbaşa səbəbi elə odur.
Nömrələnmiş prefiks mövzu sətrini forma xanasına çevirir. Nömrə var, ayırıcı var və təsvirin gedəcəyi yer var. Həmin yerin dibi yoxdur, ona görə şəkil overlay işi haqqında beş abzas deyəsi olanda, hər beşini həmin yerə yazdım. Kommit 2550 simvol oldu və git log --oneline içində qarşısında nömrə olan iyirmi iki sətir nəsr kimi oxunur.
Yeri gəlmişkən, Conventional Commits məni bundan xilas etməzdi. feat(images): ... və ardınca 2500 simvol tam eyni dərəcədə sınıqdır. Mövzunun əvvəlindəki qayda heç vaxt problem olmayıb. Problem çatışmayan boş sətir idi.
Beləliklə, nömrə qalır. O, yerini qazanıb və onu feat: ilə əvəz etmək mənə etiketi itirdirib, işlətmədiyim avtomatlaşdırmanı alardı. Dəyişən odur ki, ondan sonra nə gəlir.
Keçdiyim şablon
Düzəliş nömrəni saxlayır, mövzunu 72 simvolla məhdudlaşdırır və hər izahı boş sətrin altına köçürür. Budur tarixçəmdəki ən pis kommit, əvvəl və sonra.
Əvvəl - 2550 simvolun hamısı mövzu sətrində:
016 - Made content images on the project and blog detail routes open full size in an overlay, because a screenshot of a dashboard rendered at card width is unreadable on a phone, and the previous hand-rolled overlay had no focus trap, so it was replaced with Base UI's modal Dialog which supplies Escape, focus movement, the trap and focus return, and the thumbnail stays at the call site so it is still server-rendered and present in the initial HTML, and images inside a Link are excluded because a button inside an anchor is invalid...Sonra:
016 - Open content images full size in an overlay
Case study galleries and in-post figures rendered at their layout
width, so a screenshot of a dashboard was unreadable on a phone.
Wraps content images in ImageZoom, which resolves its labels on the
server and hands them to a Base UI modal Dialog. That supplies
Escape, focus movement, the focus trap and focus return, which the
previous hand-rolled overlay did not have.
The thumbnail stays at the call site and stays server-rendered, so
it is still in the initial HTML.
Excludes images inside a Link: a button inside an anchor is invalid
HTML, and listing covers are teasers rather than content.Məlumat eynidir. Birinci versiya kommit siyahısı göstərən hər alətdə oxunmazdır. İkincisi hər kəsin gözlə tuta biləcəyi 48 simvolluq xülasədir, bütün mühakimə isə git show içində bir düymə uzaqlıqdadır.
Bunu standart davranışa çevirmək
Üç dəyişiklik, və həqiqətən vacib olan yalnız birincisidir.
-m-ə uzanmağı dayandırın. Git-ə şablon göstərin və sadə git commit işlədin ki, redaktor artıq hazır formayla açılsın:
git config --global commit.template ~/.gitmessage ~/.gitmessage, burada hər sətir git-in yadda saxlamadan əvvəl kəsdiyi şərhdir:
# NNN - Subject in the imperative, 72 characters maximum
#
# Before: what the situation was
# Now: what this commit does about it
# Not: what was deliberately left alone
#
# Refs: #issueUzunları hook tutsun. commit-msg hook-u səkkiz sətirdir və bağlı düşür, bütün məsələ də budur: heç nəyin məcbur etmədiyi qayda sadəcə üstünlükdür. Git-in hook sənədi qalanlarını sadalayır:
#!/bin/sh
# .git/hooks/commit-msg - reject an over-long subject
subject=$(head -n 1 "$1")
if [ ${#subject} -gt 72 ]; then
echo "Subject is ${#subject} characters. The limit is 72." >&2
echo "Move the explanation below a blank line." >&2
exit 1
fichmod +x .git/hooks/commit-msg ilə icra edilə bilən edin. Hook-lar standart olaraq kommit olunmur, ona görə ya onu repoda saxlayıb core.hooksPath ilə həmin qovluğu göstərin, ya da hər klondan sonra yenidən qurmağa hazır olun.
Hələ düzəldilə biləni düzəldin. Ən son mesaj bir əmr uzaqlıqdadır:
git commit --amendDaha köhnələr interaktiv rebase tələb edir, redaktə etmək istədiyiniz sətirlərdə pick sözünü reword ilə əvəz edin:
git rebase -i HEAD~5Hər ikisi tarixçəni yenidən yazır və hash-ləri dəyişir, ona görə paylaşılan budaqda bu, force-push-dan əvvəl razılaşma tələb edir. Öz iyirmi dördümü yenidən yazmıram - audit olduğu kimi qalanda daha faydalıdır. Onu yazdığınız yox, miras aldığınız kod bazasında işlətmək ayrı işdir və mən bunu texniki konsaltinq çərçivəsində götürürəm.
Nə əldə edirsiniz
- Siyahı kimi oxuna bilən tarixçə. İyirmi dörd kommit iyirmi dörd sətir tutmalıdır və bundan sonra tutur.
- Yaşayan səbəblər. Gövdə pull request-i, söhbət yazışmasını və kodun yerləşdiyi platformanın özünü yaşadır.
- Hər yerə sığan xülasə. 72 simvoldan az olmaq GitHub-da üç nöqtə, terminalda isə sətir keçidi olmaması deməkdir.
- Özünü tətbiq edən qayda. Hook kommiti buraxmır. README-dəki tövsiyə buraxır.
Bunların heç biri yeni alət tələb etmədi və məsələ nömrələmənin feat:-ə qarşı olması da deyil. Hər ikisi prefiksdir, prefiks isə heç vaxt çatışmayan hissə olmayıb. Çatışmayan bir boş sətir və onun altındakı abzas idi.
Rəqəm commitin harada olduğunu göstərir. Yalnız gövdə onun niyə mövcud olduğunu izah edir.
Ogtay Iskandarov
Dizayner və fullstack tərtibatçı, Bakıda tək nəfərlik klauzzdcode studiyasını aparıram. 2023-cü ildən frilansdayam: məhsulları Figma-dan proda qədər özüm çıxarıram, prodla təmasdan sağ çıxanları isə yazıya salıram.