Git界の #10YearChallenge
photo by Chad Horwedel
少し前にSNSで話題になっていた#10YearChallenge
。この言葉を見て思った。…ちょっと、プログラミング界隈のタイムマシンことGitの存在を忘れてもらっちゃ困りますぜ!と。というわけで、#10YearChallenge
にGitも挑戦。10年前のGitがどんな様子だったか見に行ってみよう!
どうやって10年前に戻るの?
え、どうやって10年前に戻るのかって?Gitがどんなだったか知りたければ、もちろんまずはGitのソースコードをcloneすることから始めよう:
$ git clone git@github.com:git/git.git
見ておわかりのように、Git自体もGitによってバージョン管理されている!さて、次にこのソースコードの中から10年前のコミットのSHA1ハッシュ値を探し出してこなければ。というわけで、今しがたcloneしてきたプロジェクトを開いて次のコマンドを実行:
$ cd git
$ git rev-list master -n 1 --before="2009-01-18"
このコマンドの-n 1
というのは、結果を一つだけ表示するように指定している。--before
の部分で時間を指定。今回は、10年前の今日以前の日付になされたコミットの中から(※訳者注:この日付は原文の中国語版の記事が書かれた日付に基づいています)、しかも一つだけ探しだしてくればいいわけだ。コマンド実行後に得られたSHA1ハッシュ値はa83c88525ed6d8d940f8cf7f21e92b189f7844e3
だった。もし--before
に続く時間を変えると得られるSHA1ハッシュ値も違ってくるので注意が必要だ。
さて、SHA1ハッシュ値が見つかったので続いてはルーラを…じゃない、じゃない。git checkout
コマンドで過去へ遡ってみることにしよう:
$ git checkout a83c88525ed6d8d940f8cf7f21e92b189f7844e3
ちなみに、もし2行かくのが面倒くさければ、このように1行に短縮することも出来る:
$ git checkout `git rev-list master -n 1 --before="2009-01-18"`
10年前のGitはどんな感じだった?
Gitのソースコードが取得出来たのであれば、buildしてみよう!(インストールは必要なし、ソースコードのディレクトリからbuildすればOKだ):
$ 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になっている、とは言っても10年も経っているのでメジャーが1から2になっていても何ら不思議なことはないのだけれど。
ソースコード行数
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で、全体の8割を占めている。
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バージョン1は全て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の世界では、時間をかけてその仕組みを理解しさえすれば、コミットというのはセーブポイントと同じようなもので、ルーラのように行きたい場所に行けるようになり、道に迷うこともなくなる。ただし、基本的なスキルをきちんと身につけていないと、いくらセーブポイントがどこか分かっていても、いくらどうやって呪文を使えばいいかわかっていたとしても、天井に頭をぶつけて頭をこぶだらけにしてしまうだけなので、是非しっかりと基本を身につけておこう!
(オタクなのでオタクっぽい例えしか出てこなくて、すみません orz)