Git Time Machine 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