photo by Chad Horwedel
Git 世界的 #10YearChallenge
即然講到 #10YearChallenge
,怎麼可以忘記在電腦世界的檔案時光機 Git 呢!讓我們來看看 10 年前的 Git 長什麼樣子吧!
要怎麼回到 10 年前?
想要知道 Git 長什麼樣子,首先當然要先去 clone 一份 Git 的原始碼:
$ git clone [email protected]:git/git.git
是的,Git 當然本身也是用 Git 在做版控的!接下來,要從這份原始檔中找到離目前 10 年前的 Commit 的 SHA1 值,所以可以進到剛才 clone 下來的專案並且執行:
$ cd git
$ git rev-list master -n 1 --before="2009-01-18"
這個指令的 -n 1
表示只要秀出一個結果,而 --before
應該就很明顯了,這整串指令可以讓你找出在 10 年前的今天之前的 Commit,而且只要找一個就好了。指令執行後我得到一個 SHA1 值 a83c88525ed6d8d940f8cf7f21e92b189f7844e3
,如果 --before
接的的時間不同,可能會找到跟我不一樣的 SHA1 值。
即然找到 SHA1 值,接著就可以用 ルーラ 咒文.. 不是,是 git checkout
指令飛過去了:
$ git checkout a83c88525ed6d8d940f8cf7f21e92b189f7844e3
如果覺得寫成兩行有點麻煩,也可寫成一行:
$ git checkout `git rev-list master -n 1 --before="2009-01-18"`
所以,10 年前的 Git 長什麼樣子?
即然都取得 Git 的原始碼了,就可以把它 build 起來看看(不需要安裝,就在原始碼的目錄裡 build 起來就好):
$ make configure
$ ./configure
$ make
make 成功的話,應該就可以在該目錄產生許多 git-
開頭的執行檔(如果 make 失敗可試著把錯誤訊息丟去 stackoverflow 找看看解法)
版本
- 2009 年
$ git --version
git version 1.6.1.203.ga83c8
- 2019 年
$ git --version
git version 2.19.1
版號從 1 字頭跳到 2 字頭,跳了一個 Major 版號,是說都 10 年了,跳個 Major 版本應該也不意外了。
原始碼行數
- 2009 年:
$ cloc *
github.com/AlDanial/cloc v 1.80 T=1.12 s (785.9 files/s, 272731.4 lines/s)
--------------------------------------------------------------------------------
Language files blank comment code
--------------------------------------------------------------------------------
C 241 12701 11220 82408
Bourne Shell 416 12474 5956 73787
Perl 39 5598 4755 35831
PO File 17 5420 5772 15236
Tcl/Tk 38 1422 322 9433
Gencat NLS 13 0 0 5178
C/C++ Header 82 990 1206 3814
Python 5 670 272 2939
make 9 293 263 1881
Lisp 3 241 206 1808
Bourne Again Shell 1 105 65 1626
ASP.NET 8 114 0 799
CSS 2 142 15 655
m4 1 30 7 574
Assembly 2 51 158 198
XSLT 3 5 4 47
JSON 1 0 0 39
JavaScript 1 2 2 30
YAML 1 0 0 21
DOS Batch 1 0 0 1
--------------------------------------------------------------------------------
SUM: 884 40258 30223 236305
--------------------------------------------------------------------------------
整個專案的程式碼行數有 23 萬行,大部份是 C、Shell Script 以及 Perl,佔了整個專案八成以上的行數。
- 2019 年:
$ cloc *
github.com/AlDanial/cloc v 1.80 T=2.91 s (667.0 files/s, 303302.0 lines/s)
-----------------------------------------------------------------------------------
Language files blank comment code
-----------------------------------------------------------------------------------
C 443 31960 27293 193716
Bourne Shell 1030 31560 12338 190348
PO File 48 58088 63656 166792
Perl 80 5251 4956 29710
C/C++ Header 209 4239 10230 16966
Tcl/Tk 40 1537 409 10444
Python 7 1603 1581 5985
make 24 715 782 3565
Bourne Again Shell 1 241 332 2489
m4 2 123 14 1161
ASP.NET 9 141 0 942
CSS 2 169 30 783
JavaScript 7 203 649 761
Go 4 53 84 421
sed 1 22 158 189
zsh 1 37 17 189
PHP 2 44 82 123
XSLT 8 19 33 98
Assembly 1 26 115 83
Markdown 2 14 0 64
diff 18 0 36 64
C Shell 1 18 63 45
Ruby 1 4 0 24
Windows Resource File 1 1 0 21
Lisp 2 0 0 12
-----------------------------------------------------------------------------------
SUM: 1944 136068 122858 624995
-----------------------------------------------------------------------------------
看得出來整個專案的主力還是 C 語言跟 Shell Script,程式碼行數大概是 2 倍的成長,但 Perl 的行數變少了!不知道是不是因為 Perl 不太好寫的原因…
附帶一提,Git 在第一個版本的時候,是全部用 C 語言寫的,而且只有 848 行程式碼而已喔:
$ cloc *
github.com/AlDanial/cloc v 1.80 T=0.02 s (625.0 files/s, 67245.9 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 8 115 59 769
C/C++ Header 1 17 23 53
make 1 14 0 26
-------------------------------------------------------------------------------
SUM: 10 146 82 848
-------------------------------------------------------------------------------
Git 指令數量
想要知道 Git 內建有哪些指令的話,可使用 git help -a
來翻看看:
- 2009 年
add fast-import merge-resolve rev-parse
add--interactive fetch merge-resolve.sh revert
add--interactive.perl fetch--tool merge-subtree rm
am fetch-pack merge-tree send-email
am.sh filter-branch mergetool send-email.perl
annotate filter-branch.sh mergetool.sh send-pack
apply fmt-merge-msg mktag sh-setup
archimport for-each-ref mktree sh-setup.sh
archimport.perl format-patch mv shell
archive fsck name-rev shortlog
bisect fsck-objects pack-objects show
bisect.sh gc pack-redundant show-branch
blame get-tar-commit-id pack-refs show-index
branch grep parse-remote show-ref
bundle hash-object parse-remote.sh stage
cat-file help patch-id stash
check-attr http-fetch peek-remote stash.sh
check-ref-format http-push prune status
checkout imap-send prune-packed stripspace
checkout-index index-pack pull submodule
cherry init pull.sh submodule.sh
cherry-pick init-db push svn
clean instaweb quiltimport svn.perl
clone instaweb.sh quiltimport.sh symbolic-ref
commit log read-tree tag
commit-tree lost-found rebase tar-tree
config lost-found.sh rebase--interactive unpack-file
count-objects ls-files rebase--interactive.sh unpack-objects
cvsexportcommit ls-remote rebase.sh update-index
cvsexportcommit.perl ls-tree receive-pack update-ref
cvsimport mailinfo reflog update-server-info
cvsimport.perl mailsplit relink upload-archive
cvsserver merge relink.perl upload-pack
cvsserver.perl merge-base remote var
daemon merge-file repack verify-pack
describe merge-index repack.sh verify-tag
diff merge-octopus repo-config web--browse
diff-files merge-octopus.sh request-pull web--browse.sh
diff-index merge-one-file request-pull.sh whatchanged
diff-tree merge-one-file.sh rerere write-tree
export merge-ours reset
fast-export merge-recursive rev-list
帳面上看起來有 166 個,但實際上差不多只有 140 個左右。
- 2019
add diff merge-octopus reset
add--interactive diff-files merge-one-file rev-list
am diff-index merge-ours rev-parse
annotate diff-tree merge-recursive revert
apply difftool merge-resolve rm
archimport difftool--helper merge-subtree send-email
archive fast-export merge-tree send-pack
bisect fast-import mergetool serve
bisect--helper fetch mktag sh-i18n--envsubst
blame fetch-pack mktree shell
branch filter-branch mv shortlog
bundle fmt-merge-msg name-rev show
cat-file for-each-ref notes show-branch
check-attr format-patch p4 show-index
check-ignore fsck pack-objects show-ref
check-mailmap fsck-objects pack-redundant stage
check-ref-format gc pack-refs stash
checkout get-tar-commit-id patch-id status
checkout-index grep prune stripspace
cherry gui prune-packed submodule
cherry-pick gui--askpass pull submodule--helper
citool hash-object push subtree
clean help quiltimport svn
clone http-backend range-diff symbolic-ref
column http-fetch read-tree tag
commit http-push rebase unpack-file
commit-graph index-pack rebase--helper unpack-objects
commit-tree init receive-pack update-index
config init-db reflog update-ref
count-objects instaweb remote update-server-info
credential interpret-trailers remote-ext upload-archive
credential-cache log remote-fd upload-pack
credential-cache--daemon ls-files remote-ftp var
credential-netrc ls-remote remote-ftps verify-commit
credential-osxkeychain ls-tree remote-http verify-pack
credential-store mailinfo remote-https verify-tag
cvsexportcommit mailsplit remote-testsvn web--browse
cvsimport merge repack whatchanged
cvsserver merge-base replace worktree
daemon merge-file request-pull write-tree
describe merge-index rerere
指令數量變成 163 個。
兩邊的指令集相減一下,2019 年比 2009 年多的指令有這些:
bisect--helper check-ignore check-mailmap citool
column commit-graph credential credential-cache
credential-cache--daemon credential-netrc credential-osxkeychain credential-store
difftool difftool--helper gui gui--askpass
http-backend interpret-trailers notes p4
range-diff rebase--helper remote-ext remote-fd
remote-ftp remote-ftps remote-http remote-https
remote-testsvn replace serve sh-i18n--envsubst
submodule--helper subtree verify-commit worktree
這些新增的指令,老實說我比較常用的也只有 worktree
而已。
關於 ルーラ 咒文
勇者鬥惡龍的 ルーラ 咒文,是國中時候(就是中二病的那個時期)最想學會的咒文!扣掉小叮噹的任意門跟孫悟空的瞬間移動之外,就是這個最方便了!
在 Git 的世界裡,只要能花點時間了解運作原理,每個 Commit 就跟每個城鎮的紀錄點一樣,使用 ルーラ 咒文就能想去哪裡就去哪裡,完全不會迷路(有看我表演過的人就會知道我在說什麼了)。如果基本功沒練熟,即使知道紀錄點在哪、也知道怎麼使用咒文,也是會撞天井(就是天花板)會撞得滿頭包的喔。
共勉之!
(不好意思,宅宅舉的例子都是宅宅的例子 orz)
Comments