2014/12/27

私の git の参考文献とか使い方とかまとめ 2014

git どうやって勉強したのさー、って質問が。
参考になるかはともかく私の最近の git の使い方についてまとめてみます。
このコマンドはどういう挙動をします、って話ではなくて、どんな時に使う、くらいのまとめです。
調べるためのキーワード提供にでもなれば。


参考文献とか考えとか

  • staging とか workspace とか commit とか : どこだっけ。ちょっと覚えてない。
  • rebase とか –no-ff の知識 : こわくない git かな。 基本的に git の話するときはこれを勧めてます。
  • tips とか : ここ とか。必要になったら調べる感じ。
  • branching model : 過去のログを見るとここを参考にしてたみたい
  • branching model : 複数人数で git を使う時の自分の中ルールだと
    • master には直接 commit しない
    • origin/master への push -f は最終手段
    • merge は master に対して –no-ff
    • conflict の解消は branch での rebase で解決する
    • github を使ってるなら merge は pull request で、 conflict したら branch で rebase 
  • commit message とかの話 : ChangeLog を支える英語


基本的に使うコマンド

  • git init
    • リポジトリ作る。
  • git ( add | mv | rm )
    • ファイルの追加とか移動とか削除とか。
  • git st
    • status を見る。面倒なので alias かけてます。
  • git commit
    • コミット。
  • git log
    • ログを見る。2.0 くらいから特に設定しなくても色が付くようになってうれしい。
  • git diff (–cached)
    • diff を見る。
    • diff で commit と workspace 間の diff。 add してなかったらこっち。
    • diff –cached で commit と staging 間の diff。 add した後に diff りたかったらこっち。
  • git fetch
    • remote から変更を取ってくる。
    • commit してない変更がある時とか、ローカルブランチで作業してる時に変更が欲しかったら fetch
  • git pull
    • remote から変更を取ってくる + 変更を反映する
    • master で変更を取ってきたいなら pull で良いかな、くらいの使い方
  • git clone
    • リポジトリを clone する
    • github は https:// を clone すると毎回 password 聞いてくるので git:// で clone すると楽
  • git merge (–no-ff)
    • branch を merge する
    • 私は master には直接 commit せずに –no-ff する主義。
  • git branch (-a | -d | -D )
    • ブランチを見たり作ったり
    • -a で remote も含め全部。
    • -d で削除。 -D で強制削除。
  • git co ( -b | -f )
    • checkout する。面倒なので alias かけてる
    • 最近 branch するのが面倒なので -b を良く使う気がする
    • 作業前の状態にしたいやー、って時は -f を使う。
    • stash でも良いけれど本当にいらないと思うときはこっち。
  • git reset
    • add したやつを戻す。
    • soft reset, hard reset がある
  • git rebase -i
    • rebase は -i を良く使うかも
    • master から派生した branch にいる時は rebase -i master が楽
    • conflict したら –abort 諦めるくらいの軽さで commit の入れ替えとかたまにやる。
    • 最近は commit –amend するより commit して rebase -i で fixup とかする
    • fixup と rewind で –amend みたいなことができるし良いかなーといった感じ
  • git remote ( add | rm )
    • そんなに使わない
    • clone すると origin があるので基本はそれを使ってる
    • fork したリポジトリの upstream を設定する時くらい


あると便利

  • git grep
    • リポジトリ内を grep する
  • git ls-files
    • リポジトリに入ってるファイルの一覧
  • git remote prune origin
    • remote に無い branch を local でも消してくれる
    • branch -a がうるさく無くなるのでちょっと快適
  • git reset –hard
    • 最終兵器。
    • 間違って master に commit した時に checkout -b して reset –hard HEAD^ とか便利
  • git reflog
    • rebase, merge にミスった時はコレ
    • reflog 漁って git reset –hard で大体解決する
    • ので gc は設定で切ってたりします。コマンド打つと勝手に gc して止まるのも何だし。
  • git stash ( pop | apply |save )
    • workspace の変更を一時保存
    • 軽量 commit みたいなものだけれど最近は commit + rebase してしまうかも
    • この実装でいけるか怪しいけれど一応は保存しておきたい、くらいの時に save するかなー、くらい
  • git bisect
    • エンバグした時に便利
    • 動いてた時と動いて無い時を指定して、動かなくなった commit を特定するやつ
    • これをまともに使うためにも master は必ず動く状態の commit のみで構成したい理由はコレ
    • コンパイル通らない、とかだと bisect できない
  • git cherry-pick
    • 特定の commit を拾ってくるやつ
    • master に特定の commit があるなら rebase で拾うけれど
    • 欲しい commit が他 branch でそれ以外の commit を拾いたく無い時とかに使う
  • git archive
    • repository を zip とかにできる
    • なんか提出する時とかに使ってた記憶。そんなに使わないけれど特定の人達には需要あるかも

2014/12/14

ghc 読み会に参加してみた

コンパイラの講義で行なわれた ghc 読み会に紛れ込んできました。2014/12/06と07。

まずは ghc の内部構造の話から。
ここ を参考にしながら ghc がどのような流れでバイナリを吐くのか、みたいな話とか。
まずは Core に変換されて、STG に変換したあと LLVM なり gcc なりのバックエンドで実行コードを吐く、みたいな流れみたいです。
Core は Haskell でついてる型からどうやって Primitive 型に変換するか、みたいなのも処理する様子。
あと型変数とかも処理するので、関数に型を渡したりもできる言語っぽいです。
ほとんど Agda みたいに見える。
case で実行するので、 case を使う場所によって遅延評価にしたり正則評価にしたり変えられるみたい。
Core の定義そのものはシンプルっ。Exprは6種類しか無いとか。
ただ ghc 自体は 200k 行とかあって、シンプルな言語だとしても処理系側でカバーしてるだけなのかなー、とか。Core しかり Haskell しかり。
あとは Haskell はグラフだぜー、とか要素いろいろ。良い資料っぽさげ。


次に実際にデバッガで追っていこう、ということに。
Vagrant で box 作ってその中で実行したのでログとか。
  • $ vagrant init chef/ubuntu-14.04
  • $ vim Vagrantfile
    • メモリとか CPU 割り当てとか編集
  • $ vagrant up
  • $ vagrant ssh
  • $ sudo apt-get update
  • $ sudo apt-get install git cabal-install vim
  • $ sudo apt-get build-dep -y ghc
  • $ vim ~/.bashrc
    • export PATH=$HOME/.cabal/bin:$PATH
  • $ source .bashrc
  • $ cabal update
  • $ cabal install cabal-install
  • $ cabal install happy alex
  • $ git clone git://github.com/ghc/ghc.git
  • $ cd ghc
  • $ ./sync-all -r git://github.com/ghc get
  • $ perl boot
  • $ ./configure --with-ghc=/usr/bin/ghc
  • $ vi mk/buil.mk
    • buildFlavor を devel2 に
    • GhcDebugged = YES を末尾に
  • $ make MAKE="make -j" -j
    • 1時間くらい。付けなかったら3時間とかかった
  • $ sudo make install
  • $ ghci -fobject-code -cpp -DSTAGE=2 -I. -I./stage2 -I./stage2/build -illvmGen:prelude:cbits:specialise:stranal:coreSyn:stgSyn:basicTypes:main:stage2:iface:simplCore:simplStg:cmm:types:codeGen:typecheck:profiling:parser:rename:utils:nativeGen:hsSyn:deSugar:ghci:vectorise:stage2/build: main/DriverPipeline.hs
    • すると .o ができる
    • DriverPipeline は読みたいので DriverPipeline.hi を消して
  • $ ghci -cpp -DSTAGE=2 -I. -I./stage2 -I./stage2/build -illvmGen:prelude:cbits:specialise:stranal:coreSyn:stgSyn:basicTypes:main:stage2:iface:simplCore:simplStg:cmm:types:codeGen:typecheck:profiling:parser:rename:utils:nativeGen:hsSyn:deSugar:ghci:vectorise:stage2/build: main/DriverPipeline.hs
    • で b compileFile できる
  • $ s <- SysTools.initSysTools (Just "/usr/local/lib/ghc-7.9.20141205")
  • $ env <- HscMain.newHscEnv $ DynFlags.defaultDynFlags s
  • $ DriverPipeline.compileFile env (DriverPhases.Hsc DriverPhases.HsSrcFile) ("/home/vagrant/hoge.hs", Nothing)

とりあえず compileFile って関数があるので呼んでみよう、というログが上のもの。
ghc の main を直接 ghci で実行すると、「今呼んだらもう遅い」みたいな abort で落ちたので main 以外を実行しようとして見つけたのが compileFile 。
stage 2 の ghc の library とかを使って ghc の DriverPipeline.hs なるソースを読もうとしたログ。

読もうとした時に問題発生。
そもそも Haskell ってどうデバッグしたり追っていくものなのだろう、という疑問。
調べると ghci が出るんだけれど、 ghci の trace って読むために使うものだろうか。
とりあえずそれ以外の選択肢は無かったので ghci で実行してた。

実行することはできたのだけれど問題がいくつかあって
  • -I の指定順とか結構謎。オプションの順番変えると動かないとかあったり。
  • .o がある .hs を ghci で読み込むと、そのファイルの関数に break point が付けられない
  • けど -boot file は .o が無いと参照できないので .o を作らないといけないソースもある
  • 実行するためには HscEnv とかが必要なのだけれどそれを作るのが大変
とか。追おうにも追いづらい。
test から見ようにもテスト単位がユニットごとじゃなくて全体用のテストのみで単体の動作を追うのも無理。
Haskeller の人達ってどうやってデバッグ やソースコードリーディングしているのだろう。
あと、小さい単位に分けたりしなくても大丈夫なのだろうか。テストとか。HscEnv とか。(値が20個とかある型だった)
型チェックとかでどうにかしてるのかなー。その辺りの情報が謎。
ghc の Travis とか見たら結構 build コケてたりしていて実際どうやってるのか不安。

最後には Parser や Lexer をソースから読むことに。
Alex とか Happy とか使いつつ。
Parser も実際に動かすことはできなくて、 Haskeller はどうやってデバッグしてるんだろうか、というところでタイムアップ。

結局 Haskeller はどんな風にデバッグしたりソース読んだりテストしたりするのだろう、という疑問が募っておしまい、という感じ。
Core の構造とかを知ることができたのが収穫かなー、といったところ。