太字は今見てるページ。
2011(18)  2012(3)  2013(3)  2018(1) 
1  2  3  4  5(1)  6(2)  7  8  9  10  11  12 

2013/5/21 mercurialはsvnの負の遺産を引きずっているようにしか見えない ほか
たぶんpermalink: http://murachue.ddo.jp/web/diary.cgi?mode=past&query=201305#20130521

はじめに

http://twitter.com/murachue/status/336493263584366593
mercurialを仕方なく使うたびに、mercurialはsvnの負の遺産を引きずっているようにしか見えないと思うよ…

と某所(ばれてる)でつぶやいたら、『入門TortoiseHg+Mercurial』『入門Mercurial』『俺のコードのどこが悪い?』などを執筆していらっしゃるらしい方(@flyingfoozyさん)から以下のようなリプライ

https://twitter.com/flyingfoozy/status/336499937804161025
@murachue #mercurialjp どう言った点で『svnの負の遺産』を感じられるのでしょうか?利便性向上の修正提案の参考にしたいので、是非お気軽にお知らせください

をいただいたので、gitさいこーmercurialとかないわーという生産性のないdisをしていたのを反省しつつ、ここにまとめ?たいと思います。
(たぶん)面識ないうちに対して優しい言葉遣いでリプライしていただいてありがとうございます。世の中(特にIT系)にはいきなりマサカリ投げつけてくる人もいるのですごく助かります。きゃー。

内容が微妙な割には長文なので、読みたい人は時間を気にするといいと思います。

ちなみにmercurialないわーという考えになった(なってる)のは、きっとgitに慣れていてmercurialを良く知らないこと(つまり無知…)によるものが多いような気がするので、つっこみお願いします。
(でも知らない人に対するつっこみって文章考える労力が必要なのは知っているので、できればでいいです。つっこんでも得するのうちだけだし。)
あと個人差もすごくあると思います、というとりあえず逃げのような免責文たち。

以下mercurialって長いしtypoしそうなのでhgと略します。

TOC

・gitとhgの履歴に対する考え方について (改変おっけー/rebase/黒魔術filter-branch vs 改変だめっしょ/rollback/MQ)
・ブランチ (ただのタグみたいなもの vs changesetに記録されるもの) (追記@22:03: それ標準機能のbookmarkでできるよ)
・(リポジトリごとに違う可能性のある)リビジョン番号…
・git add -p / hunkごとの編集 (vs hg add、TortoiseHg Workbench) (追記@22:03: それrecord extensionでできるよ)
・svnに微妙に似てるようで微妙に違うとか名前変わってるコマンド(svn ls,svn info(?) vs hg manifest,hg summary)
・スリルが味わえます (hg strip)
・それgitなら簡単にできるよ/それgitでできるけどhgだと(すごく面倒だ|できない)よ (もはやsvn関係ない)
 ・indexつかったcase folding解決(これは嘘かも)、git add -p(またかよ)、ブランチつけかえ、rebaseやamendや…
 ・(追記@22:03: rebaseは標準添付のrebase extensionでできるよ)
・extensionとは… vs git "plumbing" commands

・gitよりmercurialの方が優れてる点 (ちゃんとcase-folding認識してくれる(&add時警告もしてくれるらしい)、svnのような履歴の硬さのいい面)

やばいTOC書いているだけで飽きてきた…

とにかく伝えたいのは、「gitは(バージョン管理によって作られる)歴史という概念に対する認識をガラッと変えてしまったのに対して、
hgではそうでもないな(たぶんsvnからgit触らずhgに移行した時でも)」ということです。いやなんかずれてる…。
gitと比べればsvnとの差分が小さいから(svn触ってる人には)覚えやすい、と見ればhgの方が上か。
gitは構造がシンプルなのに複雑なことができるから好きなんです。
gitを知れば大人になれる。(嘘

決してPythonだからというわけではないんです

●gitとhgの履歴に対する考え方について (改変おっけー/rebase/黒魔術filter-branch vs 改変だめっしょ/rollback/backout/MQ)

hgをググりつつ学んでand少しだけ使ってて思ったのが、「gitの歴史改変しやすさに比べると、hgの歴史改変しにくさは異常(言い過ぎ)、svnと似てるな」ということ。

gitはとりあえず履歴を記録しておいて、後で見返して「このcommitの内容は(メッセージがラフすぎて|粒度が不適切で|そもそもデバッグメッセージとか消し忘れたから)だめだなー」と思ったらrebase -iすればいいじゃん(ただしpush前に限る)、という気軽さがあるのに対して、
hgは「いつcommit内容を決めるの? 今でしょ!」といわれている気がした。(流行に乗ってみた。)
これは後述のブランチにも関係してる。
hgには履歴改変ツール?としてMQ(Mercurial Queue)というextensionがあるようだけど、パッチがスタックみたいな感じだったりしてgitに比べると面倒という印象。
あとMQはextensionなので、(標準で添付されているから追加でダウンロードしなくてもいいけど).hgrcに一文追加しなければいけなかったりして面倒(?)。
え、TortoiseHgにMQの機能が付いてるらしい? すいません今聞きました…(追記@22:03: 事前に.hgrcなどでmq extensionを有効にする必要がある。それ知らなくてすごく探した…。)

話を戻して…
hg rollbackで戻せるからたぶん安心(でも変更点が蒸発しそう…)、と思っていたらrollbackは直前の「1回」のcommitやpull(pullも!?)などしか取り消せないらしい。
hg backoutはgitでいうrevert commitなので、履歴に残る。(svnに同じ。)
参考:http://akisute.com/2010/02/mercurial-hg-revert-hg-rollback-hg.html
gitもrevertでbackoutと同じことできるけど、そもそもpushする前ならそんな残念commit残すよりrebaseで消し去るような。(間違って消し去ってもreflogで復帰できる安心感もある。)
(追記@22:03: hgもpush前ならMQで何とかするのが一般的なのかな?)

hg pullからも、どうも「みんなで一つの履歴を共有」的な考えを感じる。(svnに同じ。)(追記@22:03: 「履歴を共有」というより「履歴空間を共有」といった方がより正しく伝わりそう? いや微妙だな…)
(たぶんリビジョン番号があるからか? もしくはブランチ先端がごちゃまぜで同じ空間にあるから? tipも誰彼かまわず「最新」につくし。)
gitはfetchしてきてもリモートブランチ?(refs/remotes/以下のこと)が変わるだけで、refs/heads/以下もHEADも変わらない。(pullなら変わるけど、これは例外としていいよね)

hgではgitでいうgit reset --hard hogehoge的なことはできない? いやできそうだけど、知らない…。(どうもhg stripがその一部っぽいようです。戻す方向にしかできなさそうだけども。)


そういえばhg upってローカルに変更あったらどうなるの? svn upみたいなことに…? あとで試す。
→TortoiseHgで試すと、どうも「無かったことにする(discard)」、「パッチで残しとく(けどWorktreeから消し去る?)(Shelve:git stash的なものらしい)」、「変更を残したままupdate(Merge)」と選べる模様。


ちなみに、gitを最初使ったとき「いやー『元に戻した』という変更も(svnみたいに)記録しておこうよ…」と思ったけれど、
だんだんgitを使っていくにつれて歴史を見返す機会が少しずつ増えて、見返すたびに、
「微妙な分割のコミットや元に戻すようなコミットがところどころまじるより、(機能ごとなど)一定の単位で変更点(だけ)が分割されて残っていた方が見返しやすいなあ」と思った、というのもあります。

メモ:
gitなら気軽にコミットしておけばとりあえず変更点は消えないし、あとで書き換えられる(あとでブランチをコミットごとに分けることすらできる)ので
適当にコミットしておいても気軽に直せる。
hgはそこまで気軽にコミットできない(ような気がする)し、いざという時MQ持ち出すのはいいけど、順番変えるのにqpop -aしとかないといけないという罠があったり
そこそこ重要そうなファイル(.hg/patches/series)を改変する事でなんとかする方式でちょっと怖い気がする。(それってMQをよく知らないだけでは!)
// MQの参考:http://d.hatena.ne.jp/dayflower/20090520/1242794877
ついでに↑のページの
> qrefresh したけど実は前の内容のほうが正しかった
> それは今からではどうしようもない!
いやそれgitだったら1コマンド(git reset HEAD@{1} (--hardはお好みで))で巻き戻せるし… (→それgitなら簡単にできるよ)

>でもこれからのことを考えるなら,パッチ群自体も履歴管理するという方法がある。
それ泥沼では…。しかも事前に用意しておかないといけないとか…。

●ブランチ (ただのタグみたいなもの vs changesetに記録されるもの)

確かによくブランチの説明でよく見るような図
(頭の中:http://nvie.com/posts/a-successful-git-branching-model/ )
と照らし合わせるとhgの(名前付き)ブランチは自然かもしれない(gitはmergeされると見分けつかなくなる)けれど、

「そのchangesetそれぞれについてるブランチの情報、今後ずっと(mergeされた後でも)必要ですか?」

って思ってしまう…。(チームで開発してたりするとまた違う感じなのかな。)
svnもコピーすることでブランチ(とタグ)を表現してたから、リポジトリ全体でみるとhgと同じなんだよね。

hgはそれに加えて、名前付きブランチ vs 名前なしブランチの話もあって、svnやgitのブランチと比べるとすごくややこしくなってる。
( http://d.hatena.ne.jp/flying-foozy/20120801/1343816083 のシリーズでは名前付きブランチを「リビジョングループ」といい変えていて、こっちの方が分かりやすい
…ってこのblogは@flyingfoozyさんのblogではないか!わかりやすい解説ありがとうございます…。)

gitのブランチは枝分かれ先にそれぞれ名前が付いている(いや正確にはgcされてない名前ついてないブランチというのも存在しえますが…)けど、
hgのブランチは枝分かれ先の識別にはリビジョンのハッシュ(で正しい?)(もしくはリビジョン番号)しかないように見える。これはつらい。hg heads…。
(local tagがあるけど自動で進まないよね。bookmarkはextensionを導入する必要があります。面倒。(追記@22:03: ver1.8から基本機能になったらしい。
しかも「自動的に参照先リビジョンを変更することができる」らしい。 http://d.hatena.ne.jp/flying-foozy/20120803/1343994576 見落としていたーすみません><;;))

●(リポジトリごとに違う可能性のある)リビジョン番号…

覚えにくいリビジョンのハッシュ値の代わりに(ハッシュに比べれば)覚えやすい10進数の通し番号なので、
(hgで)ちょっとしたことをするとき、リビジョンを指定するときにショートカットに使えますが、
そもそもリビジョンのハッシュ値なんて4ケタも指定すればたいていのリポジトリなら十分(linuxとかだと7ケタ必要だったりする、それでも7ケタ)なので、
リポジトリごとに違うようなリビジョン番号使うよりリビジョンのハッシュ値を使いましょう。(人に伝えやすいし、打ち間違えてもエラーになってくれる確率が高そう[要出典])
もしくはgitにおけるHEAD~3というように「"commit-ish"のn個前」みたいな指定でもいいでしょう。(HEAD@{2.months.ago}みたいに指定もできる…と思ったらこれはreflogだけか。)
(追記@22:03: hgでもgitみたいに指定できるそうです。@flyingfoozyさんより: http://d.hatena.ne.jp/flying-foozy/20120511/1336713963 もしくは http://mercurial-users.jp/manual/hg.1.html#revset )
わざわざ地雷原に特攻する必要はない。

ちなみに今知ったことですが、hgはリビジョンのハッシュ値3文字以下でも(あいまいでなければ)受け付けてくれるんですね。
gitは必ず4文字以上でないといけない… (→gitよりmercurialの方が優れてる点)

しかし重箱の隅だけど、リビジョンのハッシュ値の先頭あたりが[0-9]+で一意な時に、リビジョン番号と被ってたらちょっとかわいそうなことが起こりそうだよね…。(そんなに無いと思うけど。)

●git add -p / hunkごとの編集 (vs hg add、TortoiseHg Workbench)

gitでうちがすごーーーーーーーーーーーーーーく感動したのがgit add -p。
計画性のない自分は、本来なら複数のコミットに分割しなければいけないような変更点を(やる気があるときに)がしがしコミットせず書いちゃう。
そしてあとで「しまった…」となったときに助けてくれるのがこのgit add -p。
コミットしたい変更点だけ抽出して部分的にコミットできるのです。

で、これがhgにどうもないらしい。
ただでさえ「いつcommit内容を決めるの? 今でしょ!」(→gitとhgの履歴に対する考え方について)という空気を感じるのに、
さらに気を使って(時にはブランチを作って?)ファイルを変更していかなければならない。
つらい…。

そこでTortoiseHg!(Windows限定)
なんとTortoiseHgにはWorkbenchというのがあって、その機能の一つに「次のコミットに含める変更点をhunk単位で指定できる」機能があるのです!(git add -pみたいだ!)
やったね!

そんな感動に浸っていた時、次のような変更点が現れた。
@@ -196,7 +202,10 @@
        if(n < BIT16SZ)
                error(Eshortstat);

+if(DBG)fprintf(stderr, "fsstat: %s\n", c2name(c)); // これは次のコミットに含めたくない…
+       fspath(c, 0, path);                         // これは含めたい!
+if(DBG)fprintf(stderr, "fsstat: -> %s\n", path);   // これは次のコミットに含めたくない…
        if(stat(path, &stbuf) < 0)
                error(strerror(errno));

うちは死んだ。
(git add -pならhunk編集もできるので、↑のコメントに書いたような要望も(あまり面倒なことなしに)実現できる。)

結局(hgを良く知らない)自分は、ファイルから含めたくない部分を削って保存→commit→元に戻す、としてなんとかした…。svnかよ。
こんなときはMQなのかな。(MQをよく知らないので、その分期待してしまう)

(追記@22:03: record extensionというのを使うとgit add -p相当の操作ができるようになるそうです。http://mercurial-users.jp/manual/hg.1.html#record )

…とここまで書いたけど、この項目はsvn関係ないんじゃないか。いやsvn addとhg addは似てるから、これでいっか…。(ひどい。)

●svnに微妙に似てるようで微妙に違うコマンド(svn ls,svn info(?) vs hg manifest,hg summary)

hgはsvnのコマンドに似ていて覚えやすいらしい。
確かにaddやrename(mv)、remove(rm)などコマンドが似ているし、gitみたいにindexとかいう変な概念がないのでsvnを使っていた人にはとっつきやすそう。

でも「今いる(=最後にupdateした)リビジョンどこだっけ」と思ってhg infoとすると、そこには無慈悲な
hg: unknown command 'info'
というメッセージ(とそこそこ長いヘルプ)。
そのそこそこ長いヘルプをちょっと見てsummaryが対応するコマンドだとわかったので、わかりやすいヘルプだなーと思いつつhg summaryを実行しました。

また、「あのリビジョンのとき、ファイル○○ってあったっけ/どんな構成になってたっけ」と思ったのでhg ls -r xxxとしたら、そこには無慈悲な
hg: unknown command 'ls'
というメッセージ(とそこそこ長いヘルプ)。
そのそこそこ長いヘルプをちょっと見ても対応するコマンドが分からなかったので、ググったらhg manifestが対応するコマンドということがわかりました。
ちょっと今回はわかりにくかったなーと思いつつhg manifestを実行しました。

●スリルが味わえます (hg strip)

どうもhgでも履歴を抹殺できるらしいと聞きました。(他の項目を書いた後にググりました。)
hg stripとやらを使うとサクッと消せるそうですが、もちろん諸刃の剣のようです。
復旧するにはhg unbundle .hg/strip-backup/...とする必要があるそうですね。

gitならstripの代わりにresetを使いますが(もしくはgit branch -fかな)、万が一やってしまっても
resetの場合
$ git reset HEAD@{1} もしくは git reset ぶらんち@{1} (--hardはお好みで)
branch -fの場合
$ git branch -f ぶらんち ぶらんち@{1}
これで戻ります。
これは「やってしまった」直後の場合ですが、直後じゃなかった場合は@{xxx}のxxxが変わるだけです。(もちろんreflogでなくともハッシュでも可)
hg unbundleと違って(?)、resetやbranchコマンドは日常のうちです。緊急時でも悩みません。(ちょっとこじつけ感あるけど…)

svnもsvnadminで履歴を編集できるそうですね(でも試したことはない…)。それと同じスリルがhgにはありそうです。
(自動でバックアップとるhgの方が上だとは思う。)
gitはいつでも安心して戻れます。(ただしGCさえ走らなければ(これ重要…かなしい。))

●それgitなら簡単にできるよ/それgitでできるけどhgだと(すごく面倒だ|できない)よ (もはやsvn関係ない)

なんだっけ…ここまで書いてて忘れた。メモっておけばよかった。

・git add -p
 ・追記@22:03: hgではTortoiseHgを使うか、record extensionを有効にしないといけない
・rebaseや歴史書き換え(黒魔術filter-branch)
 ・しかもパッチの履歴管理とか変なことしなくても元に戻せる (→gitとhgの履歴に対する考え方について の後半)
 ・追記@22:03: hgではrebase extensionを有効にする必要がある。がしがしrebaseする前の履歴を削除するけど、一応backupはとられる模様。(hg stripと同じような感じ)
  ・hgではrebaseした後、元に戻すためにhg unbundleしてもrebaseした後の履歴は手動で削除する必要がありそう。ちょっと面倒。( http://stackoverflow.com/questions/8132868/mercurial-how-to-restore-after-rebase )
・ブランチ後付け (意外と大規模変更だったわー、とcommitしたあとに気づくなど)
・glog、カラー表示
 ・gitはgit log --graph --color のようにオプションつけるだけ。(よく使うなら.gitconfigに書きますが…。)
 ・追記@22:03: glogの代わりにhg log -Gが(標準で)使えるそうです。colorはextensionで。
 --colorはgit diffなどにも使えます。
・case-foldingやWindowsで使えないファイル名の解決 (ほんと?→嘘かも。git mvがindexに対してできない悲しさ。git rmはできるのに…。git write-treeで? それはくるしい…)
・git stash? (これはhg shelveでいけるらしい。extensionだけど。git stash apply相当は?)

●extensionとは… vs git "plumbing" commands

・extension(plug-in)文化 vs UNIXの「小さなコマンド」文化 (これは好き嫌いがあるね)
・緊急時にも面倒だけどなんとかなる? (そしてplumbingなやつが必要な時は大体緊急時である(例外は学習時)) →それhgでいうdebug系じゃね
(追記@22:03: hgはextensionをいろいろ入れてからが始まり感ある。)

●gitよりmercurialの方が優れてる点 (ちゃんとcase-folding認識してくれる、svnのような履歴の硬さのいい面)

・case-foldingおよび予約名に対する姿勢
 (hgはUnix系OS上でもadd時に大小文字衝突とか気遣ってくれてるらしい一方、gitは何も言わずcheckout時にお構いなしで壊れる…かなしい。)
・履歴が硬い
 残念なこともなかったことにしない。あとで巻き戻しにくいので、しっかりした記録として使える。
・空間効率? (といってもgitにpackがある今となっては…ただし未検証)
・hg serveがHTTPベース (git-daemonはGIT独自プロトコル…なのでファイアウォールとかプロキシとか面倒、LANなら関係ないけど。)
・リビジョンのハッシュ値3文字以下でも(あいまいでなければ)受け付けてくれる

眠くなったのでこのあたりでいったん更新。
気が向いたら肉付けします…。

追記@22:03: @flyingfoozyさんに色々とつっこみいただきました。

http://twitter.com/flyingfoozy/status/336717744189865986
@murachue とりあえず気になったところを。履歴の考え方の差は http://d.hatena.ne.jp/flying-foozy/20120730/1343659761 が参考になれば幸いです。また、現行の操作モデルは『(非エンジニア利用も含めた)安全性を重視』した結果なので『SVN との類似』は副作用的なものと考えた方がよいです。
http://twitter.com/flyingfoozy/status/336717927686488064
@murachue hg には(エクステンションだけど) rebase 機能もあります。bookmark は 1.8 から標準機能です http://d.hatena.ne.jp/flying-foozy/20120803/1343994576 "HEAD~3" 的な指定は可能です http://d.hatena.ne.jp/flying-foozy/20120511/1336713963
http://twitter.com/flyingfoozy/status/336719151697653760
flyingfoozy:@murachue 編集付きのハンク単位取り込みは record エクステンションで可能になります http://mercurial-users.jp/manual/hg.1.html#record
http://twitter.com/flyingfoozy/status/336719372188020736
@murachue なお、文字コード設定/言語設定 http://www.lares.dti.ne.jp/~foozy/fujiguruma/scm/mercurial-language.html をすることで日本語でヘルプを参照可能ですので、対応機能等を調べる場合はご利用ください。ウェブ上でも参照可能です http://mercurial-users.jp/#id5
http://twitter.com/flyingfoozy/status/336720118883184640
@murachue ASCII グラフ表示は log -G で可能です(現在はコア機能になってます)。 color 表示は color エクステンションで有効にできます

hgの勉強になりました。わざわざ返信ありがとうございます!つっこみ内容に従って追記をいくつか入れておきました。
(gitを主に使っている身からすると異文化探訪感すごくある。)

2013/6/8 dice (for windows) がお名前.comのDDNS更新に失敗する
ので、なんとか更新できるようにした。
dice for windows 1.59についてくるonamae.pllに以下のパッチ(長い…)を当てれば、とりあえず動くはず。
なにやってるかはコメントと実際にあたるパッチの内容を眺めてみてください。
厳密にはonamae.com.plgの[Options]のO1bの値の最後の空白文字も消去したほうがいい気がしますが、今のところそのままでも動きます。
// dice for Linuxはしらない

# ASCII部分の空白をonamae公式の3.1.0.3に準拠させる (厳密にはplg側も変更する)
0000B03D: 20 25
0000B03E: 25 73
0000B03F: 73 0A
0000B040: 0A 50
0000B041: 50 41
0000B042: 41 53
0000B044: 53 57
0000B045: 57 4F
0000B046: 4F 52
0000B047: 52 44
0000B048: 44 3A
0000B049: 3A 25
0000B04A: 20 73
0000B04B: 25 0A
0000B04C: 73 2E
0000B04E: 2E 00
0000B04F: 0A 00
0000B063: 20 25
0000B064: 25 73
0000B065: 73 0A
0000B066: 0A 44
0000B067: 44 4F
0000B068: 4F 4D
0000B069: 4D 4E
0000B06A: 4E 41
0000B06B: 41 4D
0000B06C: 4D 45
0000B06D: 45 3A
0000B06E: 3A 25
0000B06F: 20 73
0000B070: 25 0A
0000B071: 73 25
0000B072: 0A 73
0000B073: 25 0A
0000B074: 73 2E
0000B076: 2E 00
0000B077: 0A 00
# SSLのレスポンスが途中で切れても何とかするようにする
0000ABB4: 8B E8
0000ABB5: C6 07
0000ABB6: 48 06
0000ABB7: 3B 00
0000ABB8: D8 00
0000B1C0: 00 56
0000B1C1: 00 57
0000B1C2: 00 8B
0000B1C3: 00 74
0000B1C4: 00 E4
0000B1C5: 00 0C
0000B1C6: 00 29
0000B1C7: 00 FE
0000B1C8: 00 8D
0000B1C9: 00 4F
0000B1CA: 00 FE
0000B1CB: 00 83
0000B1CC: 00 F9
0000B1CE: 00 7E
0000B1CF: 00 19
0000B1D0: 00 56
0000B1D1: 00 51
0000B1D2: 00 6A
0000B1D3: 00 03
0000B1D4: 00 59
0000B1D5: 00 8B
0000B1D6: 00 7C
0000B1D7: 00 E4
0000B1D8: 00 10
0000B1D9: 00 81
0000B1DA: 00 C7
0000B1DB: 00 38
0000B1DC: 00 06
0000B1DF: 00 F3
0000B1E0: 00 A6
0000B1E1: 00 59
0000B1E2: 00 5E
0000B1E3: 00 74
0000B1E4: 00 04
0000B1E5: 00 46
0000B1E6: 00 49
0000B1E7: 00 EB
0000B1E8: 00 E2
0000B1E9: 00 31
0000B1EA: 00 C0
0000B1EB: 00 39
0000B1EC: 00 C8
0000B1ED: 00 5F
0000B1EE: 00 5E
0000B1EF: 00 C3
0000B1F0: 00 90
0000B1F1: 00 0A
0000B1F2: 00 2E
0000B1F3: 00 0A

2013/6/10 hgでリポジトリがぶっ壊れるとき
終了…

cpu% hg qpop -f
popping 1
transaction abort!
failed to truncate 00changelog.d
rollback failed - please run hg recover
abort: Invalid argument
cpu% hg recover
rolling back interrupted transaction
failed to truncate 00changelog.d
abort: Invalid argument
cpu% 

何もおかしいところはなさそうなんだけどなあ。

cpu% ls -l /.hg/
--rw-rw-r-- M 541 glenda sys       0 Jan 18  2012 /.hg/.tags.cache--rATcG
--rw-rw---- M 541 glenda sys       0 Jan 18  2012 /.hg/.tags.cache-LTdzlS
--rw-rw-r-- M 541 glenda sys      57 Jan 18  2012 /.hg/00changelog.i
--rw-rw-r-- M 541 glenda sys       3 Jun  4 21:26 /.hg/branch
--rw-rw-r-- M 541 glenda sys     139 Jun 10 22:45 /.hg/branchheads.cache
--rw-rw-r-- M 541 glenda sys 1033306 Jun 10 23:32 /.hg/dirstate
--rw-rw-r-- M 541 glenda sys      56 Jan 18  2012 /.hg/hgrc
--rw-rw-r-- M 541 glenda sys       2 Jun 10 23:32 /.hg/journal.branch
--rw-rw-r-- M 541 glenda sys 1033306 Jun 10 23:32 /.hg/journal.dirstate
--rw-rw-r-- M 541 glenda sys      10 Jan 18  2012 /.hg/last-message.txt
d-rwxrwxr-x M 541 glenda sys       0 Jun 10 22:47 /.hg/patches
--rw-rw-r-- M 541 glenda sys      23 Jan 18  2012 /.hg/requires
d-rwxrwxr-x M 541 glenda sys       0 Jun 10 23:32 /.hg/store
--rw-rw-r-- M 541 glenda sys      47 Jun  9 23:17 /.hg/tags.cache
--rw-rw-r-- M 541 glenda sys       2 Jun 10 22:47 /.hg/undo.branch
--rw-rw-r-- M 541 glenda sys 1033306 Jun 10 22:47 /.hg/undo.dirstate
cpu% ls -l /.hg/store
--rw-rw-r-- M 541 glenda sys  565192 Jun 10 22:47 /.hg/store/00changelog.d
--rw-rw-r-- M 541 glenda sys  167296 Jun 10 22:47 /.hg/store/00changelog.i
--rw-rw-r-- M 541 glenda sys 1523689 Jun 10 22:47 /.hg/store/00manifest.d
--rw-rw-r-- M 541 glenda sys  167296 Jun 10 22:47 /.hg/store/00manifest.i
d-rwxrwxr-x M 541 glenda sys       0 Jun  1 21:58 /.hg/store/data
--rw-rw-r-- M 541 glenda sys  966802 Jun  4 21:10 /.hg/store/fncache
--rw-rw-r-- M 541 glenda sys     123 Jun 10 23:32 /.hg/store/journal
cpu% 

このサイズ通りに切り詰めればいいのかな(危険

cpu% cd /.hg
cpu% cat store/journal
00changelog.d 565070
00changelog.i 167232
00manifest.d 1523608
00manifest.i 167232
data/sys/src/cmd/disk/kfs/main.c.i 4536
cpu% 

※↑nulバイトを空白に置き換え済み

どうもpythonのtruncateがうまく動いてないっぽい?

cpu% dd -if /mnt/term/dev/random -of test -bs 1024 -count 16
16+0 records in
16+0 records out
cpu% ls -l test
--rw-rw-r-- M 541 glenda glenda 16384 Jun 10 23:46 test
cpu% python
Python 2.5.1 (r251:54863, May 18 2013, 04:09:18) [C] on plan9
Type "help", "copyright", "credits" or "license" for more information.
>>> open("test","r+b").truncate(10000)
Traceback (most recent call last):
  File "", line 1, in 
IOError: [Errno 12] Invalid argument