मेरा पसंदीदा Git commit (2019)
(dhwthompson.com)- GOV.UK पर काम के दौरान Dan Carley का “Convert template to US-ASCII to fix error” commit दिखाता है कि छोटा code change भी विस्तृत commit message के जरिए codebase का दीर्घकालिक documentation बन सकता है
- अच्छा message यह दर्ज करता है कि क्या बदला, उससे ज्यादा यह कि क्यों बदला; इस उदाहरण में
bundle exec rakeचलाने पर आएinvalid byte sequence in US-ASCIIerror और उसे reproduce करने की शर्तों को विस्तार से रिकॉर्ड किया गया है - error string और जांच की प्रक्रिया साथ में दर्ज होने से, बाद में वही समस्या मिलने पर कोई व्यक्ति
git log --grepया GitHub commit search से पुराना समाधान रिकॉर्ड खोज सकता है - message में
find -exec,file --mime,iconvजैसे Unix tools के इस्तेमाल की प्रक्रिया भी शामिल है, जिससे reviewer और बाद के reader समस्या सुलझाने का flow follow कर सकते हैं - हर commit इतना लंबा होना जरूरी नहीं, लेकिन context, जांच की प्रक्रिया और भावनाएं तक दर्ज करने वाला message टीम की codebase की साझा समझ और भरोसा बनाने में मदद करता है
छोटे बदलाव को दीर्घकालिक documentation बनाने वाला commit
- Git commit message, अगर अच्छी तरह लिखा जाए, तो codebase के पूरे जीवनकाल तक टिकने वाला मजबूत documentation tool बन सकता है
- उदाहरण के तौर पर लिया गया commit Government Digital Service में GOV.UK पर काम करने के समय का बदलाव है
- लेखक Dan Carley हैं, और title है “Convert template to US-ASCII to fix error”
- GDS के खुले development तरीके की वजह से ऐसे internal संगठनात्मक उदाहरण भी बाहर साझा किए जा सकते हैं
लंबाई से ज्यादा जरूरी context
- इस commit में code change की मात्रा की तुलना में message लंबा है, लेकिन इसकी मुख्य value लंबाई में नहीं बल्कि उपयोगी context में है
- यही बदलाव कहीं और
change whitespace,fix bugकी तरह छोटा लिखा गया हो सकता था - Dan ने आसपास के colleagues और बाद के readers को समस्या की वजह और समाधान की प्रक्रिया समझाने के लिए detailed record छोड़ा
क्या बदला से ज्यादा, क्यों बदला
- अच्छा commit message सिर्फ बदली हुई चीजों को नहीं, बल्कि क्यों बदला गया यह भी समझाता है
- यह commit दर्ज करता है कि feature branch में
/etc/nginx/router_routes.confके content से match करने वाला test जोड़ने के बाद, चलाने के तरीके के हिसाब से result अलग थाbundle exec rake specयाbundle exec rspec modules/router/specसे चलाने पर सब ठीक चलता थाbundle exec rakeसे चलाने पर हरshouldblock fail होता था- error था
ArgumentError: invalid byte sequence in US-ASCII
- ऐसी explanation न होती तो किस tool में किस तरह का parsing error आया, इसका अंदाजा लगाना पड़ सकता था
- मूल काम का context लोग भूल सकते हैं, team बदल सकते हैं, या organization छोड़ने पर आसानी से गायब हो सकता है
खोजा जा सकने वाला error record
- commit message की शुरुआत में बदलाव की वजह बना error message जस का तस मौजूद है
- वही error मिलने पर कोई व्यक्ति codebase में पुराने record को इन तरीकों से खोज सकता है
git log --grep "invalid byte sequence"- GitHub commit search
- search results में दिखा कि कई लोगों ने इस error को खोजा था, और यह भी पता चल सका कि पहले किसने समस्या का सामना किया और क्या action लिया
समस्या सुलझाने की प्रक्रिया को कहानी की तरह दर्ज करना
- message इस तरह structured है कि समस्या कैसे दिखी, किस क्रम में जांच की गई, और आखिरकार कैसे ठीक की गई—यह follow किया जा सके
- उदाहरण के लिए इसमें शामिल है कि
.with_content(//)matcher हटाने पर error गायब हो गया, spec file में कोई अजीब character नहीं था, और उसी interpreter में Puppet को require करने पर इसे reproduce किया जा सकता था - commit message किसी खास file, function या code की एक line को नहीं, बल्कि बदलाव को ही document करता है, इसलिए codebase ने जो यात्रा तय की है उसे record करने के लिए यह अच्छी जगह है
टीम के ज्ञान को बढ़ाने वाला side effect
- Dan ने जांच के हर step में चलाए गए commands record किए, और यह टीम के भीतर knowledge को हल्के-फुल्के तरीके से फैलाने का तरीका बन सकता है
- reader सिर्फ commit message से भी Unix tools का इस्तेमाल सीख सकता है
findमें-execargument देकर मिली हर file पर command चला सकते हैं- command के अंत में
\+लगाने से हर file पर अलग-अलग चलाने के बजाय कई filenames को एक हीfilecommand में pass किया जाता है file --mimefile का MIME type बताता हैiconvनाम का tool मौजूद है
- बदलाव review करने वाले व्यक्ति के साथ-साथ बाद में इस commit को खोजने वाले व्यक्ति को भी वही जानकारी मिलती है
- पर्याप्त समय और commits जमा होने पर ऐसे messages टीम के लिए knowledge amplification device बन सकते हैं
सहानुभूति और भरोसा बनाने वाला record
- commit के अंत में “Now the tests work! One hour of my life I won't get back..” वाक्य है
- यह वाक्य एक घंटे तक चतुर bug को track करने वाले developer की झुंझलाहट और उसे सुलझाने की संतुष्टि बताता है
- short-term hacking या prototype code के production में जाकर जड़ें जमा लेने के मामलों में भी, ऐसे messages याद दिलाते हैं कि हर बदलाव के पीछे उस समय उपलब्ध जानकारी में सबसे अच्छा decision लेने वाला कोई व्यक्ति था
हर commit का लंबा होना जरूरी नहीं
- यह उदाहरण extreme है, और खासकर इस आकार के हर commit से इसी level की detail की उम्मीद करने की जरूरत नहीं
- फिर भी यह बदलाव के पीछे का context समझाने, दूसरों को सीखने देने, और टीम के codebase के बारे में shared mental model में योगदान देने का अच्छा उदाहरण है
- अच्छे commit messages और changes को structure करने वाले tools में रुचि हो तो ये resources देखे जा सकते हैं
- Telling stories through your commits by Joel Chippindale
- A branch in time by Tekin Süleyman
1 टिप्पणियां
Hacker News की राय
अच्छा हो या बुरा, GitHub के co-founder और Pro Git जैसी Git किताब लिखने वाले व्यक्ति के नज़रिए से, Git commit messages code documentation का एक अनोखा रास्ता हैं, लेकिन बेहद अप्रभावी हैं
मुख्य समस्या यह है कि Git, GitHub वगैरह ज़्यादातर tools आम तौर पर सिर्फ पहली लाइन दिखाते हैं। उदाहरण वाला commit भी “US-ASCII error” जैसी सामान्य एक लाइन ही दिखाता है, और लेख में जिस बाकी सामग्री की तारीफ़ की गई है उसे आधुनिक tools में लगभग कोई नहीं देखता
Git ने commit messages को project के सभी लोगों द्वारा पढ़े जाने वाले email body के रूप में design किया था, लेकिन आजकल वे अधिकतर वह भूमिका नहीं निभाते। जब तक mailing list पर patch series के रूप में चर्चा न हो, title के पहले 50 characters के अलावा लगभग कुछ नहीं पढ़ा जाता
git blameमें-w -C -C -Cहै या दो-Cहैं, यह ढूंढकर संबंधित message trace करने पर भी सिर्फ पहली लाइन दिखती है, और आखिर में लंबे message को देखने के लिए SHA ढूंढकरgit showकरना पड़ता है। अच्छी तरह लिखे जाने पर भी information को फिर से ढूंढना बहुत मुश्किल है—Git को लेकर मेरी सबसे बड़ी शिकायतों में से एक यही हैGit project का इतिहास देखें तो commit messages लगभग हर बार शानदार होते हैं, लेकिन किसी एक file पर
blameचलाने पर भी function implementation का context follow करना बहुत मुश्किल है। Jeff King ने पिछले 10 सालों में जो documentation छोड़ी है वह genius level की है, लेकिन भयावह बात यह है कि लगभग कोई उसका आनंद नहीं ले पातासही समाधान क्या है, नहीं पता, लेकिन ज़्यादातर communities में commit messages के रूप में बेहतरीन documentation लिखना दुखद रूप से लगभग समय की बर्बादी जैसा है। क्योंकि उसे ढूंढना बहुत मुश्किल है
git blame,git log,git showहमेशा इस्तेमाल करता हूं, file history follow करना आसान है औरgit log -Gसे add/delete होने का समय ढूंढने में कुछ सेकंड ही काफी होते हैंमुश्किल तब होती है जब commit तो मिल जाता है, लेकिन message बस “bleh” या “add a thing” होता है। developer ने सिर्फ 60 सेकंड लगाकर यह लिख दिया होता कि ऐसा क्यों किया, तो बात बन जाती
इसके उलट, जब किसी बदलाव के क्यों किए जाने की विस्तार से व्याख्या करता commit message मिलता है तो सच में खुशी होती है। एक अच्छा commit message घंटों, दिनों का काम बचा देता है
GitHub भी खराब commit messages की समस्या में योगदान देता है। किस्मत अच्छी हो तो PR description में details मिल जाती हैं, लेकिन वह commit log के ठीक बगल में नहीं होती; और अधिकतर PR Jira link पर, Jira Slack conversation link पर, और Slack Google Docs link पर ले जाता है
industry documentation में वाकई खराब है, लेकिन Jeff King जैसे लोग सही लड़ाई लड़ रहे हैं। आखिरकार मुझे लगता है कि यह technical समस्या नहीं, लोगों की समस्या है। documentation लिखने का तुरंत reward नहीं मिलता, इसलिए यह extra काम जैसा लगता है, और reward कई दिन, कई हफ्ते या कई महीने बाद ही दिखता है
कृपया अच्छे commit messages लिखें। सिर्फ 1 मिनट लगाकर यह लिख दें कि क्यों किया, तो हर commit कोई कमबख्त Chesterton’s fence puzzle नहीं बनता। उसे आसानी से मिल सकने वाले commit message में रख देंगे तो आपका भविष्य वाला खुद और मैं आपका शुक्रिया अदा करेंगे
साथ ही, मैं इस दावे से भी सहमत नहीं हूं कि commit messages ढूंढना मुश्किल है। code की किसी line, function, file का इतिहास follow करने में मुझे लगभग कोई दिक्कत नहीं होती, और commit message दोबारा न भी पढ़ा जाए तो भी लिखते समय उसका मूल्य होता है। अच्छा message लिखने से मैं verify करता हूं कि मैंने सच में वही code लिखा है जो मेरा इरादा था, और code reviewer के लिए भी यह valuable है
git blameoptions ढूंढना मुश्किल है, यह बात भी मज़ाक जैसी लगती है। अच्छा IDE हर line पर blame info लगाता है, एक button से diff दिखाता है, और उस diff में context lines या deleted lines पर recursively blame कर पाने देना चाहिए। Tig जैसे tools ठीक यही करते हैंयह मानता हूं कि GitHub commit messages देखना मुश्किल बना देता है
commit से जुड़ी documentation मज़े के लिए नहीं लिखी जाती। यह बाद में शायद मौजूद न रहने वाले व्यक्ति द्वारा भेजे patch को accept करने का risk घटाती है, और संबंधित सोच को उजागर करती है ताकि दूसरे लोग उस पर काम कर सकें। सोच छिपाने से code पर exclusive ownership जमा होती है, और आम तौर पर यह अच्छी बात नहीं होती। commit messages proof of work की भूमिका भी निभाते हैं, और patches बहुत ज़्यादा होने पर महत्वपूर्ण हो सकते हैं। commercial projects में इसका कुछ महत्व कम हो सकता है
ऐसी documentation रखने की जगह सच में कहीं और नहीं है। code comments में यह फिट नहीं बैठती। लेकिन अब developers की ऐसी generation बन गई है जो सोचती है कि Git ही GitHub है, और Git का एकमात्र उद्देश्य changes को GitHub पर upload करना है
Git अच्छा नहीं है, लेकिन बाकी चीज़ों से बहुत कम खराब है। हमें मूल बातों पर लौटकर version control का वास्तविक उद्देश्य समझना चाहिए
इसलिए हो सकता है कि यह मौजूदा community के लिए बहुत मददगार न हो, लेकिन कुछ साल बाद debugging करने वाले व्यक्ति के काम आता है
कुल मिलाकर मंशा से सहमत हूं, लेकिन बेहतर होगा कि शुरुआत में और ज़्यादा ठोस BLUF रखा जाए। जैसे “Fix test issues caused by non-breaking space character \xa0” लिखना
इससे तुरंत समझ आ जाता है कि समस्या क्या है, और अगर कोई और जानना चाहे तो नीचे पढ़ने की आज़ादी भी रहती है
इसलिए रिकॉर्ड में खोजने के लिए एक अच्छी पहली लाइन वाला मैसेज ही काफ़ी है। बग की जड़ तक पहुंचने के लिए नर्निया तक जाकर लौटने की छोटी कहानी ज़्यादा प्रासंगिक नहीं लगती। हां, PR description या commit के extended message में भड़ास निकालने के तौर पर लिखने से मुझे एतराज़ नहीं
बेहतरीन commit message लिखने का गर्व मैंने महसूस किया है, लेकिन दूसरों को उससे मिलने वाली value को लेकर उतना आश्वस्त नहीं हूं। जब कोई अजीब error message मिलता है, या नया feature जोड़ना होता है, या लगभग किसी भी स्थिति में, मुझे लगता है कि ज़्यादातर लोग commit messages में search नहीं करते
थोड़ा दुख की बात है, लेकिन मुझे यह शक बढ़ता जा रहा है कि खूबसूरत commit messages में programmer की vanity जैसा पहलू काफ़ी होता है। उनकी तारीफ़ ज़्यादातर खुद लेखक ही करता है, और बाकी लोग बिना नोटिस किए आगे बढ़ जाते हैं
कभी-कभी ऐसी aesthetic सजावट की जगह हो सकती है, लेकिन मुझे यक़ीन नहीं कि उसकी practical value बहुत बड़ी है। अब अगर कोई और “fix whitespace issue” commit करे तो मैं ज़्यादा परेशान नहीं होता, और शायद इससे मैं बेहतर colleague बन गया हूं
Git या Linux जैसे projects में बात अलग हो सकती है, जहां बहुत बड़ी distributed team और अनगिनत commits होते हैं। जिन projects से मैं परिचित हूं, उनमें contributors 1 से 100 के बीच होते हैं और ज़्यादातर एक ही organization से होते हैं
जब Google या Stack Overflow से जवाब नहीं मिलता, तो GitHub पर भी देखता हूं कि मिलता-जुलता कुछ PR या commit message में है या नहीं। जिन private repositories तक मेरी पहुंच है, उन्हें मिलाकर मुझे अनगिनत बार मदद मिली है। अच्छे commit messages vanity से आगे जाकर निश्चित रूप से valuable होते हैं। अगर बहुत से developers उन्हें नहीं देखते, तो यह उनका नुकसान है, और उम्मीद है अनुभव बढ़ने पर वे कभी समझेंगे। junior developer को search करना सिखाना या उन्हें मूल लेख भेजना भी अच्छा है
उसके बाद से मैं कोशिश करता हूं कि commit message कम-से-कम भविष्य वाले मुझे यह याद दिला सके कि बदलाव की ज़रूरत क्यों पड़ी थी
git blameनहीं करते, तो आप गलत कर रहे हैंकई बार ऐसा हुआ है कि किसी साफ़ bug को ठीक करने जा रहा था, लेकिन commit से ठीक पहले पिछले commit को देखा तो पता चला कि वह “bug” जानबूझकर डाला गया था, और linked JIRA task में अच्छी तरह समझाया गया था कि मेरा साफ़-साफ़ लगने वाला बदलाव 2 साल पुराना bug फिर से क्यों बना देगा
git blamefeature से मैं अक्सर समझता हूं कि क्या हुआ था। अच्छा commit message मिल जाए तो आभार महसूस होता हैcommit message की पहली line सबसे महत्वपूर्ण है, क्योंकि वह
git logको Chesterton’s fence से निपटने लायक बनाती है। इस मामले में लेखक ने निशाना चूक दिया लगता हैपहली line में क्या किया गया, नहीं बल्कि क्यों किया गया, यह डालना मुख्य बात है। क्या बदला है, यह जानने में रुचि रखने वाला व्यक्ति code या diff देख सकता है
उदाहरण के लिए “nginx .conf files must be in us-ascii” लिखें, फिर “changed blahblah.erb to remove nonbreaking space character” रखें, और उसके बाद बाकी काफ़ी अच्छा commit message जारी रखें
इसे news article की तरह सोचना चाहिए। मानकर चलें कि reader किसी भी point पर पढ़ना बंद कर सकता है, और लिखना ऐसे चाहिए कि महत्व घटता जाए और details बढ़ती जाएं
news article भी title में why नहीं, what बताता है
इस मामले में original की पहली line बिल्कुल सही है।
git logदेखते हुए आप मान सकते हैं कि इस commit ने tests के functional behavior को शायद नहीं बदला, और आगे बढ़ सकते हैं“nginx .conf files must be in us-ascii” bug या PR title के लिए अच्छा हो सकता है, लेकिन कई commits अलग-अलग कामों से जुड़े हो सकते हैं, और असल में क्या हुआ यह नहीं बताता। फाइलों को US-ASCII में convert किया जा रहा है, कोई conversion tool बनाया जा रहा है, documentation update हो रही है, tests बनाए जा रहे हैं, या इनमें से कोई combination है—यह पता नहीं चलता। why के बजाय what से शुरू करने पर यह confusion कम होता है
“The files must be in us-ascii” हो या “Changed the files to us-ascii”, इससे बहुत फ़र्क नहीं पड़ता। दोनों साफ़ बताते हैं कि files US-ASCII में बदली गई हैं
इस तरह की documentation approach की कमी यह है कि एक बार लिखा गया commit message असल में बदला नहीं जा सकता
बेशक
rebaseसे यह संभव है, लेकिन जो चीज़ 1 साल पहले लिखी गई थी और पहले हीmainमें merge हो चुकी है, क्या उसे सचमुच बदलकर सबकी feature branches को दर्द देना चाहेंगे.mdfile, Wiki, Confluence में रखे docs से तुलना करें तो, मैं किसी colleague की लिखी चीज़ बेहतर कर सकता हूँ, और दूसरा colleague मेरी लिखी चीज़ बेहतर कर सकता हैइस मामले में bug ठीक हो गया है और शायद दोबारा न आए. लेकिन किसी खास component को commit करते समय उसकी design समझाने का temptation होता है, और अब मैं उससे बचता हूँ. business requirements बदलने आदि से अगर बाद में वह component बदल जाए तो क्या होगा. क्या commit docs सिर्फ diff ही समझाएँगे. तब नए team member को system समझने के लिए कई commit messages पढ़कर दिमाग में merge करने होंगे
.mdfile या Wiki, Confluence से तुलना करना bicycle और goose की तुलना करने जैसा हैcomponent बनाते समय की considerations या trade-offs, या यह तथ्य कि वे थे ही नहीं, अक्सर original defect, बाद के evolution और use case changes से पैदा defects को समझने में उपयोगी होते हैं
नए team member को system समझना हो तो अलग से “current” document maintain किया जा सकता है. उस document को implementation trade-offs या यह बात कि draft time pressure में लिखा गया था, सब cover करने की जरूरत नहीं
commits squash करने से feature addition की कहानी के रूप में record बेहतर हो जाता है, merge वास्तविक code changes का immutable log बचाए रखता है, और rebase दोनों थोड़ा-थोड़ा करता है
दोनों न रख पाने की कोई वजह नहीं है. हम computer program करने वाले लोग हैं, इसलिए जैसा चाहें वैसा बना सकते हैं
अगर मैं Git को नए सिरे से लिखता, तो commit को दो हिस्सों में बाँटता. change history को Git की तरह Merkle DAG जैसी structure में immutable रखता, और commit messages को अलग associated data store में रखकर workflow समझाने वाला reasonable और editable log बनाता. feature tags के basis पर commits को group करने, typos ठीक करने, messages मनचाहे तरीके से बदलने देता, लेकिन नीचे का diff log, यानी “code में सच में क्या बदला”, वैसा ही preserve रहता
git notesसे add किया जा सकता है. हालांकि message अगर इतना लंबा हो तो किसी के notice करने की संभावना कम लगती हैएक बात से सहमत नहीं हूँ. वह हिस्सा कि “हर commit, खासकर इस size के commit, में इस level की detail की उम्मीद नहीं करता”
मेरे अनुभव में उल्टा, छोटी और harmless दिखने वाली चीज़ों को अक्सर relatively लंबी explanation चाहिए होती है
कल मैंने
gh pr listमें--limit=999जोड़ने की वजह तीन paragraphs में लिखी. क्योंकि यह confusing है.--jqargument के अंदर पहले सेlimit(है, और अगर मान लें कि total PRs infinite हैं, तो value जितनी ज्यादा होगी, final result असल में उतना कम होगामैंने code comment भी लिखा, और शायद लिखने से ज्यादा समय सोचने और refine करने में लगाया होगा. जब कोई इशारा करे कि यह काम बस अंधाधुंध code लिखना है, तो अगला example यही याद रहे
“This was a non-ascii whitespace character that caused
ArgumentError: invalid byte sequence in US-ASCIIwhen runningbundle exec rake” इतना काफी है. बाद में similar problem खोजने के keywords हैं, root cause मौजूद है, और यह इतना लंबा भी नहीं कि लोग skip कर देंमुझे नहीं लगता यह शानदार Git commit है
इतने text के मुकाबले first line “Convert template to US-ASCII to fix error” बेहतर हो सकती थी. कौन सा whitespace character error कर रहा था और error क्या था, बस कुछ शब्द और जोड़ने की जरूरत थी. वह explanation और diff मिलकर जरूरी context के लिए काफी हैं
ईमानदारी से कहूँ तो बाकी लगभग बेकार है. नुकसान नहीं करता, लेकिन value भी ज्यादा नहीं. author ने इस bug को track करने की अपनी journey document की है, लेकिन कौन परवाह करेगा
article में उन लोगों के कई commits दिखाने वाला search result link भी है जिन्होंने उस fix से सीखा
वह commit message knowledge का खजाना है
अच्छे commit messages देखने हों तो Linux kernel की Git history देखें. वहाँ यह standard है
पहली line हमेशा change से प्रभावित subsystem का ज़िक्र करती है, फिर imperative one-line summary होती है. उसके बाद तीन सवालों के जवाब जितना हो सके detail में दिए जाते हैं
Example इस तरह लिखा जा सकता है: “current code X करता है. test case T चलाने पर unexpected behavior U observe हुआ. यह reason R की वजह से है. F करके fix करते हैं”
हाल ही में एक contributor ने मेरे Git message approach के बारे में कहा कि मेरी requirements “अनोखी” हैं। शायद Linux kernel background झलक गया होगा, लेकिन मेरे सभी commit messages यहां दिखाए गए जैसे ही होते हैं
अगर बात मौजूदा code के बारे में है, तो comments code के साथ होने चाहिए। process से जुड़ी बातें, जैसे हटाया गया code या वह code जो काम नहीं कर रहा था, commit में होनी चाहिए
सबसे अहम बात यह है कि commit message सुविधा के लिए issue को refer कर सकता है, लेकिन मुख्य details को ज़रूर दोहराना चाहिए। GitHub अस्थायी है, लेकिन Git messages नहीं
context से भरे commit messages यहां हैं[1]
यह इतनी आम बात है कि maintainer ने यह लेख लिखा[2]
[1] https://github.com/git/git/commit/d70f554cdf38b0b05cfaa8e8eb...
[2] https://lore.kernel.org/git/xmqqedevo8ps.fsf@gitster.g/