Gitの更なるまとめ(書きかけ)
関連エントリ
初期化
SN | cmd | 説明/引数例 |
---|---|---|
init | ||
cl | clone {src_repository} [{dst_path}] | https://example.com/path/to/repo.git/ path/to/dir |
addからcommitまで
addの反対がreset
SN | cmd | 説明/引数例 |
---|---|---|
a | add {file/dir_pat} | ., *.txt(このワイルドカードはシェルの機能), file.txt, dir(dir中身全て追加) |
an | add -n {file/dir_pat} | その{file/dir_pat}で何が追加されるか |
au | add -u [{file/dir_pat}] | ciaのciしない版(管理下にあるものの更新) |
ap | add -p [{file/dir_pat}] | 対話的にadd {file/dir_pat}付与でそれ限定 |
aa | add -A [{file/dir_pat}] | 新しく追加・削除・変更された、未管理のファイルを追加 |
r | reset | addしたのを全消し |
r | reset {ver} | HEADとindexを過去{ver}の状態に cimのciしない版 |
rc | rm --cached {filepat} | {filepat}をindexから消す*1 |
rp | reset -p | 対話的にreset |
ci | commit -v | (-vで)変更点を表示しながらコミット |
commit -c ORIG_HEAD | 前の(rsなどで動かされる前のHEADの)コミットメッセージを再利用してci | |
cia | commit -a | auしてci |
cim | commit --amend | rsしてci |
ciam | commit -a --amend | rしてauしてci |
状態の確認
SN | cmd | 説明/引数例 |
---|---|---|
st | status -s -b | -sシンプルに表示 -bブランチも表示 |
dh | diff HEAD | ワークツリーとHEADの差分 |
d | diff | ワークツリーとインデックスの差分 |
dc | diff --cached | インデックスとHEADの差分(次のciする差分) |
lg | log | リポジトリのログ |
ls | ls-files | 管理中のファイル一覧 |
rg | reflog | HEADの遷移 |
リモート
SN | cmd | 説明/引数例 |
---|---|---|
roa | remote add origin {URL} | git@github.com:LeafCage/temp.git |
pu | push -u origin master | 初めてアップロードするときに使う |
ro | remote -v | リモートリポジトリの詳細情報 |
pf | push -f origin {local_blanch:remote_blanch} | pf HEAD~:master masterのコミットを取り消す |
リポジトリをリネーム
SN | cmd | 説明/引数例 |
---|---|---|
mv | mv {src} {dst} | |
rc | rm --cached {src}, add {dst} | すでにリネームしていたとき |
rou | remote set-url origin {URL} | remote originのurlを変更 |
pd | push --delete origin {branch} | リモートブランチを削除 |
pf | push -f origin {:remote_blanch} | リモートブランチを削除 |
まだ考えてない
rs | reset --soft {ver} | ciを取り消し{ver}まで遡る。cimのciしない版に近い。HEAD^ |
---|
統合
SN | cmd | 説明/引数例 |
---|---|---|
m | merge [--no-ff]{branch} | [--no-ff]を付けていないとブランチフラグを動かすだけで統合できるなら新しいリビジョンを作らない |
cp | cherry-pick {ver} | {ver}を取り込む |
rb | rebase {branch} | |
rbc | add ファイル名→ rebase --continue | リベースコンフリクト解消させたことを伝えてrebaseを再会する |
rba | rebase --abort | リベースコンフリクト解消させるのをやめてrebase開始前のworkに戻す |
マージのコンフリクト解消
SN | cmd | 説明/引数例 |
---|---|---|
a | add ファイル名 | コンフリクトを解消したものとして提出 |
com | checkout --merge ファイル名 | コンフリクトを初めからやり直す |
coo | checkout --ours ファイル名 | 自分側を一方的に採用 |
cot | git checkout --theirs ファイル名 | 相手側を一方的に採用 |
gitでブランチをマージした時にコンフリクトを起こしてしまったら | S4U -smile for you-
【派閥別】Gitのコミットを間違えたときの対処法まとめ - 本当は怖い情報科学
*1:r HEAD -- {filepat}でも同じ効果gitでアレを元に戻す108の方法 - TIM Labs
vim処理速度調査(オートロード関数読み込み編2)
※この記事は全面的に誤っていたので修正されました。
そして、修正後の結果は極めて当然の話なので情報的価値がないです。
ふとruntimeを用いてスクリプトを読み込む場合と、autoload関数呼び出し時のスクリプトのautoloadで速度に違いがあるのか気になったので計測してみた。
速度計測にはLeafCage/laptime.vimを使用した。
autoload
let lt = laptime#new() call speed1#nop() call lt.lap() call speed2#nop() call lt.lap() call speed3#nop() call lt.lap() call speed4#nop() call lt.lap() call speed5#nop() call lt.lap() call speed6#nop() call lt.lap() call speed7#nop() call lt.lap() call speed8#nop() call lt.lap() call speed9#nop() call lt.lap() call speed10#nop() call lt.end()
TOTAL LAP 1: 0.003668 0.003668 2: 0.007119 0.003452 3: 0.010381 0.003262 4: 0.013674 0.003293 5: 0.017192 0.003517 6: 0.020612 0.003421 7: 0.025109 0.004497 8: 0.028710 0.003600 9: 0.032110 0.003400 10: 0.037759 0.005649
runtime
let lt = laptime#new() runtime autoload/speed1.vim call lt.lap() runtime autoload/speed2.vim call lt.lap() runtime autoload/speed3.vim call lt.lap() runtime autoload/speed4.vim call lt.lap() runtime autoload/speed5.vim call lt.lap() runtime autoload/speed6.vim call lt.lap() runtime autoload/speed7.vim call lt.lap() runtime autoload/speed8.vim call lt.lap() runtime autoload/speed9.vim call lt.lap() runtime autoload/speed10.vim call lt.end()
TOTAL LAP 1: 0.007248 0.007248 2: 0.013605 0.006357 3: 0.019803 0.006198 4: 0.027628 0.007826 5: 0.034176 0.006548 6: 0.040779 0.006603 7: 0.046969 0.006190 8: 0.053571 0.006602 9: 0.060535 0.006964 10: 0.067262 0.006728
2度読み込みされている分、:runtime のほうが遅かったです
vim処理速度調査(オートロード関数読み込み編)
以下の内容が書かれたファイルをautoload/speed1.vimとして置く。
function! speed1#nop() endfunction
同様に、autoload/speed1.vim、autoload/speed2.vim、...としてautoload/speed10.vimまで同様に置く。
そして、以下のスクリプトを:sourceする。
速度計測にはLeafCage/laptime.vimを使用する。
let lt = laptime#new() call speed1#nop() call lt.lap() call speed2#nop() call lt.lap() call speed3#nop() call lt.lap() call speed4#nop() call lt.lap() call speed5#nop() call lt.lap() call speed6#nop() call lt.lap() call speed7#nop() call lt.lap() call speed8#nop() call lt.lap() call speed9#nop() call lt.lap() call speed10#nop() call lt.end()
結果は以下のとおり
TOTAL LAP 1: 0.003770 0.003770 2: 0.007049 0.003279 3: 0.010308 0.003259 4: 0.013501 0.003194 5: 0.017289 0.003788 6: 0.021382 0.004093 7: 0.024573 0.003191 8: 0.027727 0.003153 9: 0.030940 0.003213 10: 0.034118 0.003179
内容の(ほとんどない)ない10のファイルを読み込むだけで計約0.034秒かかっている。
いったい何が原因なのか?
なぜ(ほとんど)空っぽのファイルをsourceするのにここまで時間がかかっているのか?
Vimはautoload関数が呼ばれるとruntimepathから該当ファイルを探してsourceするが、もしやここで時間がかかっているのかもしれない。
私はneobundle.vimでプラグインを管理しているが、その代償としてruntimepathに複数のパスが設定されている。
私のVim起動直後のruntimepathは以下のとおりであった。
runtimepath=~/vimfiles,~/box/vimfiles/neobundle/vim-fugitive,~/box/vimfiles/neobundle/vimproc,~/box/vimfiles/neobundle/tlib_vim,~/box/vim files/neobundle/vital.vim,~/box/vimfiles/neobundle/vim-openbuf,~/box/vimfiles/neobundle/curses-vim,~/box/vimfiles/neobundle/vim-submode,~/b ox/vimfiles/neobundle/vim-altr,~/box/vimfiles/neobundle/mdv,~/box/vimfiles/neobundle/vimhelpgenerator,~/box/vimfiles/neobundle/laptime.vim, ~/box/vimfiles/neobundle/neocomplcache,~/box/vimfiles/neobundle/neosnippet,~/box/vimfiles/neobundle/vim-operator-user,~/box/vimfiles/neobun dle/vim-textobj-user,~/box/vimfiles/neobundle/textobj-wiw,~/box/vimfiles/neobundle/vim-textobj-indent,~/box/vimfiles/neobundle/vim-textobj- plugins,~/box/vimfiles/neobundle/vim-textobj-xbrackets,~/box/vimfiles/neobundle/vim-textobj-parameter,~/box/vimfiles/neobundle/nerdcommente r,~/box/vimfiles/neobundle/ToggleCase-vim,~/box/vimfiles/neobundle/jasegment.vim,~/box/vimfiles/neobundle/clever-f.vim,~/box/vimfiles/neobu ndle/vim-ambicmd,~/box/vimfiles/neobundle/vim-altercmd,~/box/vim
そこで今度は:set rtp=~/vimfiles
として、runtimepathのパスを一つだけにしてから同じことをやってみた。
TOTAL LAP 1: 0.001546 0.001546 2: 0.002974 0.001428 3: 0.004392 0.001418 4: 0.005837 0.001445 5: 0.007338 0.001501 6: 0.008639 0.001301 7: 0.009950 0.001311 8: 0.011222 0.001271 9: 0.012507 0.001286 10: 0.014164 0.001656
処理時間が目に見えて短くなった(半分以下に)。すなわち時間がかかっている原因は、一つは探索場所が広大だったせいである。
だが、ちょっと待ってほしい。
確かに0.0015秒と短くなったとはいえ、これでもVimの処理の中では時間がかかってるほうである。拙作のプラグインにlaptime.vimというのがあるが、その関数の一つ、s:lt.end()のリストの要素が10個のときと同じくらいの時間がかかっている(これの実行時間は約0.0016秒)。
これはそれなりにリスト処理や文字列処理を含んでいる。つまりruntimepathを1つにして、探索場所を減らした状態でも、それなりの処理を含む1つの関数くらいの時間はかかっているわけである。
ちなみに、call speed1#nop()などの関数はほとんど何の仕事もしていないのであるが、これ自体の処理時間はおよそ0.0001秒である。二度目の関数呼び出しからはsourceの時間がなくなるので、この関数の時間だけしかかからず処理が高速になる。
参考
let s:test = range(101) call filter(s:test, 'v:val != "0"')
↑の処理時間は約0.0019秒前後
let s:test = range(101) call map(s:test, 'v:val. "yen"') call match(s:test, '25yen')
約0.002秒
let s:test = range(101) call map(s:test, 'v:val. "yen"') call filter(s:test, 'v:val != "0yen"')
約0.0039秒前後
vim処理速度調査(関数呼び出しin オートロード変数)
この問題はそれとして、現行の回避策として、以下の4通りの方法がある。
- eval()で評価
- type()で評価
- :silent letで呼び出し
- :silent echoで呼び出し
それぞれの呼び出し速度を比較して、もっとも短く呼び出せる方式を採用することにする。
結果。
eval() 0.003490 0.003302 0.003400 type() 0.003586 0.004332 silent let 0.003543 0.003593 0.003495 silent echo 0.004006 0.004823
明らかにeval()が速かった。見た目的にも一番素直だし、eval()を採用することにする。
Vimプラグインを作るときにはautoload以下のファイルをあまり分割すべきでない
理由はVimの実行速度が遅いから。
おそらく2000行の1つのスクリプトファイルを読み込むよりも、100行の2つのスクリプトを読み込むほうが速度が遅い。なぜなら、該当ファイルを探すのに結構な時間がかかるからである。
(追記:その後、検証して、やはりautoloadスクリプトを1つ探して読み込むのに結構な時間を費やすことが分かった。autoload関数(オートロードスクリプト)の初回読み込みが遅い · Issue #461 · vim-jp/issues)
もちろん、plugin以下の記述は少なくしてその分をautoload以下に移すのは大いに推奨される。
起動時には大量のスクリプトが読まれるので少しでも記述は少なくしておいたほうが起動が早い。
しかしプラグインが実行され、autoload以下が読まれるときに、初回時に必ず読まれる部分は、分割すると、ファイル探索のオーバーヘッドが入る分、遅くなるだけなので出来る限り少数の、出来れば単一のファイルにしておくべきである。
そもそも:sourceするのに時間は余りかからない。さっき言ったとおりファイルを探し出すことのほうがはるかに時間がかかる。
ましてvitalなどのライブラリを使っているプラグインでは、ライブラリの読み込みで余計にファイルを読み込ませているので、そこにさらにスクリプトの分割なんてするとさらなる速度低下を引き起こし、読み込みの遅さが体感レベルに達することになる。
もちろん、一度に読み込むところでないのなら、スクリプトをさらに分割しても問題ない。
Vimプラグインのヘルプドキュメントを自動生成する
この記事はVim Advent Calendar 2012 : ATND 257日目の記事です。
- さらに追加された機能の記事を書きました。
皆さんVimプラグインを作ったことはありますか?
VACではプラグインを書いて公開するまでにやることについての記事がいくつかあります。
- 【Vim Advent Calendar 2012】Vim プラグインを github で公開するまで【1日目】 - C++でゲームプログラミング
- はじめてVimプラグインを書いた話 - metropolis
- はじめてプラグインを作ってみた。それとhelpの書き方など - 反省はしても後悔はしない
- Vim のプラグインを作る時に注意すべきことや便利なプラグイン - C++でゲームプログラミング
プラグインを作ったら、doc/以下にヘルプドキュメントを添付します。
そうすることで、:help
でいつでもドキュメントを参照することが出来ます。
ヘルプを添付しないと神様に叱られてしまいます。
しかしながら、ヘルプを書くのはプラグインを作る中でももっとも苦痛な作業のひとつです*1。
かく言う私もヘルプ不精で、ヘルプを添付せず、ソースの中に使い方を書いたコメントを書くことや、ブログの記事での紹介で済ませてしまっていることが多々あります。
だから作りました。
プラグインのヘルプを自動的に作成するプラグインです。
初期設定
以下の変数を.vimrcなどに定義します。
g:vimhelpgenerator_defaultlanguage
- "ja"を指定すると日本語、"en"を指定すると英語のヘルプを作成する。
g:vimhelpgenerator_version
- "Version :"の項に表示される文字列。空文字で無効。
g:vimhelpgenerator_author
- "Author :"の項に表示される文字列。空文字で無効。
g:vimhelpgenerator_license
- 表示するライセンスを記述したファイルの&runtimepath以下のパスを記述。既定はMIT license(変更再配布OKだけど、どこかに著作者名の記述義務)。ほかにzlib/libpng(ソース形式で配布するなら著作者名の記述義務)、NYSL(著作者名の記述の義務すらなし。)のファイルがvimhelpgenerator/以下に用意されている。空文字や読めないファイル名を指定すると無効。※
g:vimhelpgenerator_contents
- 表示させるコンテンツを指定する辞書。0にしたコンテンツは表示されない。1より上の数を指定することでコンテンツの表示順を並べ替えることが出来る(若い数ほど先に表示される)。
- ※ライセンスというものについて、詳しくは以下の記事参照。
設定例
let g:vimhelpgenerator_version = '' let g:vimhelpgenerator_author = 'Author : LeafCage <leafcage+vim @ gmail.com>' let g:vimhelpgenerator_contents = { \ 'contents': 1, 'introduction': 1, 'usage': 1, 'interface': 1, \ 'variables': 1, 'commands': 1, 'key-mappings': 1, 'functions': 1, \ 'setting': 0, 'todo': 1, 'changelog': 0 \ }
使い方
まずはヘルプを作成したいプラグインのいずれかのファイルを開きます。
次に、:VimHelpGenerator
コマンドを実行します。
ヘルプを作成するプラグインのパスと名前を確認してくるので、間違いなければe
を入力して実行します。
生成されたヘルプが開かれます*2。
フォーマットは日本人プラグイン開発者の多くが使っているものを参考にしました。
(もしも日本語でヘルプを作るのなら、第一行目にマルチバイト文字を含んでください。そうしないと:helptags
したときエラーE670が出ます。)
概要や使い方は皆様の手で書くことが出来ます。
変数や関数、コマンドやキーマップは、自動収集されたもので埋められます。
グローバルなものは何でも取ってくるので、公開したくないものは削除してください。
また、精度が良くないので、間違っている部分があれば修正してください(特に変数について辞書は既定値が取得できません。既定値の取得は結構いい加減です)。
それぞれの説明文は人力で埋めてください。
これで随分とヘルプを作るのが楽になったはずです。
これからはヘルプ無しのプラグインを作るなんてあり得ませんね!
実は
申し訳程度に、ヘルプの出力を全面的にカスタマイズする機構も用意しています。詳しくはhelp
をご覧ください。
新しいバージョンのVimでは上手く動いていませんでした。現在は動作するはずです。問題点を発見すればIssues · LeafCage/vimhelpgeneratorへ報告をお願いします。