---
title: "Git 世界的 #10YearChallenge - Git 短文 | 高見龍"
description: "即然講到 #10YearChallenge，怎麼可以忘記在電腦世界的檔案時光機 Git 呢！讓我們來看看 10 年前的 Git 長什麼樣子吧！"
canonical: "https://gitbook.tw/posts/2019-01-18-10-year-challenge-in-git"
image: "https://gitbook.tw/assets/images/tw/posts/10-year-challenge-in-git/cover.jpg"
---

即然講到 `#10YearChallenge`，怎麼可以忘記在電腦世界的檔案時光機 Git 呢！讓我們來看看 10 年前的 Git 長什麼樣子吧！

## 要怎麼回到 10 年前？

想要知道 Git 長什麼樣子，首先當然要先去 clone 一份 Git 的原始碼：

```
$ git clone git@github.com: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）

```json
{
      "@context": "http://schema.org",
      "@type": "Organization",
      "url": "https://gitbook.tw",
      "logo": "https://gitbook.tw/assets/images/tw/etc/og-image-gitbook.jpg?v=8eb3685e"
    }
```
