
本文作者用幽默又真實的文字總結了開發者日常工作中遇到的那些事兒。
眾所周知啊??,很多公司的度量系統可以展示你提交了多少次commit,以及每一次提交包含多少行代碼。
搞得部分兄弟一天可勁 add commit push。他那一個變更發上線,你打開Git Log,好家伙那一大串都是他。加加減減縫縫補補,最后一共改了20行代碼,硬是刷出了200行的功德。
-
AoneBuild Merge feautre/777_平臺賦能牛逼新特性 to master
-
-
-
-
-
-
-
典!典中典!
仿佛能看到他信心滿滿,直接發預發!一刷新, 哦豁,白屏!
哦忘了傳這個了,fix,push,部署,玩手機,抬頭一刷新,哦豁,白屏!

下次 OC 再搞脫口秀我提個節目!隨機找幾個這種上去對著這種 git log 現場即興模仿表演。
他們歡快而自信的時候,以及受痛苦和絕望所折磨的時候,生活中的痛苦和壓迫會像血汗一樣,一行行地全寫在了他們的Git Log里。
你們好不好奇, 一個代碼庫幾百個文件,為啥能用一兩個G?小小一個系統,下個代碼都十幾分鐘?
完全沒有意義的Git 提交歷史,極速膨脹的代碼庫大小,混亂的分支關系。正在壓死你的代碼庫和項目!
每一個程序員,在遇到一個可愛而熱心的代碼倉看門大爺前,都會隨意的對待自己的commit,因為大家都這么做。沒見過怎么best practice,所以就doesn't matter。
求求你們了!好好寫你的Git commit message!squash你的 fixfixfix!刪刪你已經沒用的分支!重構拆掉哪些超大文件和幾萬行的類!
讓Git Log能做到寫清楚你到底改了啥!而不是你的草紙!
阿里很多資深Coder都是野生哆啦A夢,技能樹包括但不限于:
-
手里維護的代碼庫,托前人的福,一堆方法 JsonObject 出入參,他能如特工,手持密碼本相互通信。
-
系統日志print全是不帶id的sout,也能靠口袋里的見都沒見過的神奇道具和監控線條里波紋感應定位故障源頭。
-
一個代碼文件3萬行,硬是一眼掃找出在哪兒再加個if else能5分鐘hotfix一下線上Bug。
"線上bug!
很急,來不及加單測了,幫忙過一下!
"
-
對代碼系統機魂, 了如指掌,深諳取悅機魂之道。知道一些外人看來十分玄妙的獨特邏輯。掌握很多,“又不是不能用,只是你不會用,要這么這么就能用”的高級黑盒功能。
雖然兄弟們這么用Git “又不是不能用”,但是要我說 “那是你不會用”,“要這么這么用”
到這里,聰明的小朋友就要問了。為啥幾百個文件,為啥能用一兩個G呢?
眾所周知,Git 主要數據結構是一顆樹,在你的.git文件夾里,結構是這樣的。
其中的 heads,本地分支,remotes,遠程分支(用git fetch更新), tags 不可變的版本指針,他們都是指向一個commit的指針。
比如 這里, master,就是一個commit id。
你可能注意到了,分支似乎不是一個分支一個文件的。而是按/分割,當成文件夾存儲的。
比如feature是不是個分支?其實不是,假設 我新建一個名為 feature/newaCTO的分支,會在feature文件夾里建一個newaCTO, 而不是直接新建一個feature/newaCTO。
小zips, linux文件系統中,文件與文件夾是不能重名的。
所以, 一旦誰建了一個叫做feature的分支。那么,在第一個小聰明刪掉他之前。就沒人能拉出任何feature/*的分支了。
分支是指向commit的指針,那讓我們更近一步, commit是啥呢?
這是一個merge 節點。和普通的commit節點不同,merge節點有兩個parent。
除此之外,有author和committer, author是作者,committer是提交人。在本地開發中,這兩者基本上是一樣的。注意,這里使用的,是gitConfig中的name 和 email。
這里parent指向的是另一個commit, 典型的樹狀數據結構。
可以看到展示了一個列表,與GIt Log中展示不同, Tree里其實包含了完整的文件樹。樹的末端,指向一個文件的oid。
2、type: 類型,tree說明是文件夾,blob則是文件,大部分情況下就是代碼,也可能是圖片或其他文件。
但是,Git不是文件存儲系統,大文件建議使用Git LFS技術,上傳OSS,Git僅管理文件鏈接。
3、revision(oid):每當你提交commit時,你在這個commit中改動的文件,git會把文件的二進制數據加個信息頭,然后算個hash,從而產生一個新的oid。然后這個commit會指向他。
所以,每當你commit,就算提交一行的改動。就會存整個文件!(把代碼文件,把類拆小點吧!不小心摸一下觸摸板,代碼就不知道去哪兒找了!)
然后你在每一改個兩行,就來個commit,存儲膨脹能不快么!
就不談沒維護好 gitIgonre,胡亂git add .把編譯文件,摸魚刷的leetcode代碼或者其他奇奇怪怪的東西提交到Git中的情況了。
你可能會問,我這的文件已經都刪掉了,為啥.git還有這么大?你們是不是有Bug?
因為Git會保存你歷史的所有版本!除非沒有一個任何一個commit指向這個blob,才會成為游離節點,在Git Gc的時候被處理掉。
你在Git pc的時候會執行repack,repack會壓縮一部分到增量,不過一般沒人這么做,所以一般都是存了完整的離散文件。
git gc是個好課題,存儲未來可能可以智能化的全自動gc,但是現在還不行。
因此!沒事刪刪分支!不小心提上來的大東西,得把對應的commit squash掉!
本地也可以允許git gc清理掉游離節點釋放空間。
我們并不是說要squash到一個變更一個commit,或者一個feature分支就一個commit。就像游戲存檔一樣。你可以在關中頻繁存檔,但是一大關打完了,你可以存一個然后把關中的存檔都刪了。 只留關鍵節點,這樣萬一你后悔選了這條命運線,可以讀檔重來。
這也是為什么那些大庫需要嚴格執行主干開發的原因。要是我們公司幾萬研發都用一個大庫,還都是用Git記日記的憨批, 我覺得我們會被迫在存儲技術上卷死OSS。壞了,順手把多版本云盤做成主營業務了。以后新人來了先發一塊移動硬盤好了, 微服務那么多系統,下代碼不得先下個半個月?
一是git log和commit message是很重要的信息來源,要保持整潔,用的正確,這個比發布文檔還清晰。
二是代碼存儲膨脹問題是很現實的, 隨著系統發展,代碼庫一個G你還能下下,再大點咋辦呢。
雖然我們存代碼不收費,說到這兒dataworks的兄弟們可能有同感, 不要錢就使勁造,狠角色拿git當oss用的都有幾個。。
主要影響的,還是可見的未來,不治理的話,clone代碼越來越慢。
1、Code Owner要建立 代碼庫統一的commit messgae 格式規范,例如 Feature(commit): write an article to introduce git
2、打完Boss,單測通過,squash掉你之前上廁所或者測試時候的commit!化零為整但也不要矯枉過正!團隊應該根據自己業務情況探索合適commit的大小和規范。
3、重構掉“巨石類”!他們早就不夠內聚了!把能拆掉功能拆出來吧!我先替管存代碼的那個亙古和其他用這個類的開發先感謝你!
5、及時維護GitIgonre!誤提交的文件一定要清理掉!
6、用心維護主干分支的Git Log!讓改動清晰可見!
7、刪掉沒用的分支!Later Equals Never!當機立斷舍離!
8、Readme要持續更新!怎么啟動,格式規范都可以寫在readme里!
1、不要建 feature,release這兩個分支,雖然git沒有保留關鍵字,但是后人發現為啥建不出來分支的時候肯定會問候你的。
2、不要多分支并行開發的時候merge 來 merge去, git會臟合并! 保持提交歷史干凈簡單!業務太復雜不行咱就上主干開發!不要每次代碼合并不符合預期就跑去找管代碼的同學說Git丟代碼,這種偵探服務的難度挺大的,在我建議按次收費!
作者|李子昂(雪蛋)