/ 最近 .rdf 追記 設定 本棚

脳log[2018-11-22~]



2018年11月22日 (木) バッチを新しい環境で実行するのに cmd /C を頭に付けて必要なら引数を二重引用符でくくってって面倒くさい。|a.bat とは書けなかったけど call|a.bat とか echo>nul|a.bat なら呼び出し元に影響を与えない新しい環境でバッチを呼び出せた。普通に何も出力しない NOOP コマンドがあれば意図が明確なんだけどなあ。残念、rem|a.bat は無理だった。■あとバッチファイル衝撃の事実。入力を受け取って処理して出力するフィルタを書こうとしたら、標準入力に対して繰り返すコマンドが存在しなかった。for にそういう専用のオプションがあってしかるべきだと思う。これってバッチの用途のど真ん中にあると思うんだ。他のコマンドをパイプで繋ぐのはお手のものなのに、バッチファイルがそのコマンドの一翼を担うことができないのはなんで?

最終更新: 2019-04-12T22:46+0900

[Git] RestoreCommitterDate.ps1: 初めて書いた .ps1 スクリプト

タイムスタンプを保持してくれないために更新日時がチェックアウト日時になってしまう Git のために。

文法が手探りなので何時間もかかった。とりあえず覚えるべきは help *|gm.GetType()。セルフドキュメンテッドである。map は foreach {$_}、filter は where {$_}。式やコマンドをくくるのは $(...)。演算子は -band だったりするからリファレンスを見るしかない。リファレンスが手元にない。

いやあった。Windows SDK > Win32 and COM Development > Administration and Management > Windows PowerShell もしくは、スタートメニュー > すべてのプログラム > アクセサリ > Windows PowerShell > Windows PowerShell ISE を起動して F1。インストールはしたけど興味がないだけだった。

git ls-files | foreach { @{
	File = "$(pwd)\$_" -as [System.IO.FileInfo]
	Time = $(git log --pretty=format:%ci -n 1 -- "$_") -as [DateTime]
} } | where {
	$_.File
} | foreach { try {
	$_.File.LastWriteTime = $_.Time
} catch { Write-Error $_ } }

明らかに git log をパスでフィルタリングして最新の時刻を取り出す処理が遅い。SQL ではないけど構造的には N+1 問題。

ls-files の段階でコミットオブジェクトを取得してそれの時刻を取り出せないかと考えたが、--stage オプションで取り出せた ID を git show した結果はファイルの内容だけだった。

post-checkout フックに仕込むのは無理だなあ。


 @2018-12-21 N+1 問題を解決した新版

N+1 問題を抱えてるのは日本語で公開されているスクリプトであって、Perl と英語で書かれた「ExampleScripts - Git SCM Wiki」はたぶんそうではない。Perl は読めないけどたぶん。

このバージョンだとログの長さに比例した時間がかかるものの、サクラエディタのリポジトリ(ログ数3600)で "Roughly" バージョンのたかだか3倍の時間(6秒)で完了する。

<#
	.SYNOPSIS
	Git ワーキングツリーに含まれるファイルの更新日時に最終コミット日時を設定します。

	.DESCRIPTION
	Git でチェックアウトしたファイルの更新日時はチェックアウト日時になります。これはファイルのタイムスタンプを比較する場合に不都合なことがあり、代わりに最終コミット日時をタイムスタンプに設定します。

	Git リポジトリ内で実行します。すべての階層のファイルが対象になります。
#>
$TopDir = (git rev-parse --show-toplevel)
$waiting = @{}
(git ls-files --full-name "$TopDir") | foreach {
	$waiting[$_] = $NULL
}
(git log --format=format:?%ci --name-only) | foreach {
	if ($_ -eq "") {
	} elseif ($_[0] -eq "?") {
		$t = $_.Substring(1)
	} else {
		$f = [System.IO.FileInfo] "$TopDir\$_"

		# run once a file.
		$c = $waiting.Count
		$waiting.Remove($_)
		if ($waiting.Count -ne $c -and $f.Exists) { try {
			$t = [System.DateTime] $t
			$f.LastWriteTime = $t
		} catch {
			Write-Debug $_
		} }
	}
}
  • かつては Git 管理下にあったが現在はそうではないファイルを対象外にするために git ls-files を使っている。
  • git subtree によって追加されて以後変更されていないファイルのコミット日時が取れない。「Subtrees allow subprojects to be included within a subdirectory of the main project, optionally including the subproject’s entire history.

 @2019-03-09「-m オプションに対する考察

たぶん git log-m --first-parent を付けるのが一番期待するものになる。

最終更新: 2019-04-12T22:46+0900

[Git] RestoreCommitterDateRoughly.ps1

RestoreCommitterDate.ps1 が実行に1分から1分半かかるとしたら、この RestoreCommitterDateRoughly.ps1 は2、3秒で終わる。

"Roughly" が意味するところは、1か月分のログだけを遡ってワーキングツリーにあるファイルのタイムスタンプを設定するのであって、それ以上前に変更されたファイルは一律で1か月前のタイムスタンプが設定されること。

このスクリプトの目的はキャッシュしたビルド産物を再利用することで再コンパイルを省略することにあって、そのためにはファイルのタイムスタンプがチェックアウト日時であっては困る。Git はそうだ。AppVeyor は必ず git clone、git checkout からビルドを始めるから、チェックアウトしたソースファイルが必ず前回のビルド産物より新しくなってしまう。

変更がなくても1か月経てば再コンパイルされてしまうけど、まあ、リーズナブルなスパンでしょう。

<#
	.SYNOPSIS
	Git ワーキングツリーに含まれるファイルの更新日時に最終コミット日時を設定します。

	.DESCRIPTION
	Git でチェックアウトしたファイルの更新日時はチェックアウト日時になります。これはファイルのタイムスタンプを比較する場合に不都合な場合があり、代わりに最終コミット日時をタイムスタンプに設定します。

	Git リポジトリ内で実行します。すべての階層のファイルが対象になります。

	制限: ログを遡りすべてのファイルの最終コミット日時を取得することは1分以上かかることがあるため、このスクリプトでは1か月を上限としてログを遡ります。そのため最も古いタイムスタンプは実行日時を基準として前月同日の00:00:00になります。
#>
$TopDir = (git rev-parse --show-toplevel)
$Oldest = [DateTime]::Today.AddMonths(-1) # Of course, this is incorrect for the oldest timestamp. That's what "Roughly" means.

$waiting = @{}
(git ls-files --full-name "$TopDir") | foreach {
	$waiting[$_] = $NULL
}

@(
	(git log --format=format:?%ci --name-only --since="$($Oldest.ToString("yyyy-MM-dd HH:mm:ss"))")
	, "?$($Oldest.ToString("yyyy-MM-dd HH:mm:ss"))"
	, (git ls-files --full-name "$TopDir")
) | foreach { $_ | foreach {
	if ($_ -eq "") {
	} elseif ($_[0] -eq "?") {
		$t = $_.Substring(1)
	} else {
		$f = [System.IO.FileInfo] "$TopDir\$_"

		# run once a file.
		$c = $waiting.Count
		$waiting.Remove($_)
		if ($waiting.Count -ne $c -and $f.Exists) { try {
			$t = [System.DateTime] $t
			$f.LastWriteTime = $t
		} catch {
			Write-Debug $_
		} }
	}
} }

 @2019-03-09「-m オプションに対する考察

たぶん git log-m --first-parent を付けるのが一番期待するものになる。

何もなしもありっちゃあり。-m のみ付けるのはぴったりはまる状況がわからない。

-m オプションのみの場合に、双方のブランチから見た修正内容が2つのコミットとして出力されています。一方が長大なリストを出力しているのはブランチの側で master を追いかけて pull/merge/rebase した結果だと見られます。

というのはたぶん間違い。むしろ rebase しなかった結果、分岐から合流までのあいだに master が進んだその差分が現れている。

この間違いで論旨(「明らかに無視すべきものです。」)は変わらない。


2018年11月21日 (水) ぷりケツお献立メコン川さんのツイート: 「すんごい昔の会社の勉強会で後輩君が「Makefileには1行目に #!/usr/bin/make って付けて、chmod 777 Makefile して、./Makefike するのが普通です」とか言ってるのを聞いて、痙攣しながら椅子から転げ落ちた記憶が一番衝撃的だったww」■まじめな話。転げ落ちポイントを説明してくれないとわかんない。


2018年11月20日 (火)

最終更新: 2019-04-12T22:46+0900

[Git] 間違ってブランチを削除してしまった

コミット構成を変えるために複数のブランチを作成したりマージしたりなんだりしてから作業用のブランチを整理したら、再構成後のブランチまで一緒に削除してしまっていた! 1時間の作業成果!

.git/objects/*/* から一番新しいコミットオブジェクトをサルベージしてなんとかなった。サルベージっていうのは git checkout -b MyAnHour xxx(全部で40桁)xxx すること。

コミットの再構成は git rebase でもできるらしい。削除・入れ替え・併合は当然。edit オプションを使えばコミットの分割もできるとか。

そういえばまだ reflog って知らない。


2018年11月19日 (月) 年賀はがきの販売に SNS を活用するらしいけど、いっそもう発送まで代行しちゃえばいいと思った。一部分だけでも手書きが~という声は当たらない。E-メールとの間を埋めるサービスだから。■「E-メール」ってすでに懐かしい。いや E- のあるなしでなく LINE とか。


2018年11月18日 (日) ライオンエア610便墜落事故、ボーイングが新機能のトラブル対応手順を知らせていたかどうかで議論に | スラド ハードウェア」■俺は馬鹿な機械に馬鹿をさせないための操作手順を知りたいとは思わないよ。機械のお守りなんて余計な仕事を増やすなよ。■アクセル操作によってパーキングブレーキが自動解除される車のせいでカーディーラーの人間が、その車を売ってる人間が、意図せぬ急発進で人を殺してる。なんでわざわざ条件を増やして複雑さを増すんだよ。そんな機械は俺には扱えない。■Git がいかに素直な道具であることか! 見よ↓

最終更新: 2021-05-07T19:12+0900

[Git] GitHub. プルリクエストの参照。

6.3 GitHub - プロジェクトのメンテナンス - プルリクエストの参照

GitHub のリポジトリを git clone --mirror してると refs/pull/xxx/head, refs/pull/xxx/merge という見慣れない refs がダウンロードされてくる。

これはそのまま refs/pull/xxx/head という名前でコミットオブジェクトが参照でき、git fetchgit pull の引数として利用できる。

リンク先で書かれていることに従って .git/config の <remote> 名のセクションで fetch = +refs/pull/*/head:refs/remotes/<remote>/pull/* というマッピングルールを付け加えると、<remote>/pull/xxx というブランチ名が利用できるようになる。git branch --remotes が大量の PR ブランチで押し流されることと、コミットオブジェクトの大群がダウンロードされてくることが気にならないなら、便利。

PR を出した人のリポジトリを URL なり登録したリモート名なりで参照することなく、git checkout -b PRxxx <remote>/pull/xxx するだけでプルリクエストが試せる。

PR は誰でも出せるものであるからして、問題のあるコードを簡単にダウンロードできてしまう方法だという自覚は必要。

git fetch <remote> したら新規 PR が [new ref] として降ってくるし、更新があった PR の番号もわかる。そこで git show <remote>/pull/xxx すると最新のコミットの内容から PR をチラ見できる。

gitk するとあれやこれやのマージコミットの横に remotes/<remote>/pull/xxx というラベルが付いてどの PR 由来のコミットかがわかる。数が多すぎてちょっとうるさいけど。

いやあ便利。

大量の PR ブランチに押し流されるのが嫌なら、最初に書いた fetch におけるマッピングルールを工夫して、<remote> におけるコミットオブジェクトへの参照名(refs/pull/xxx/head)をそのままローカルで利用する参照名としてダウンロードできると思う。ローカルの名前なら fetch, pull に限らない幅広いサブコマンドで利用できるでしょう。

やってみた。同じ場所に同じように fetch = +refs/pull/*/head:refs/pull/<remote>/* と書いたら同じように [new ref] が降ってきた。refs/pull/xxx/head は GitHub にあるリポジトリで利用できる名前だけど、refs/pull/<remote>/xxx は同じコミットオブジェクトを指すローカルの名前。git show refs/pull/<remote>/xxx でコミットの内容が見られるのはさっきと同じだけど、git checkout -b PRxxx refs/pull/<remote>/xxx するまではブランチとしては存在しない。gitk するとこれまで見たことのない背景色で pull/<remote>/xxx というラベルが付いていた。コマンドの引数で refs/ は省略できるみたい。

refs/heads, refs/remotes, refs/tags の基盤となる refs という機能が Git にはあって、挙げた3つは Git が標準的に利用している。refs/pull は GitHub が私的に利用している。gitk はすべての refs をラベルとして表示することができ、既知の種類のラベルに特別の色分けを施していただけなのだろう。

あまり区別せずにブランチって書いてきたけど、最初の fetch ルールで作成するのはローカルのリポジトリで定義したリモート名の下にあるとするリモートブランチ。ローカルのブランチではないし、リモートにそのままの形で実在するブランチでもない(fetch 後に削除されたかもしれないし、fetch のマッピングルールによって名前を変えたのは自分だ)。実際のところ refs と何が違うのかわからない。git branch -r でリストできるかどうかの違いしか今のところわからない。git push の既定の動作に違いが現れるのかもしれないけど、そういう自動化は無効にしてるから本当に違いがない。

たぶん今日ここに書いたことは、わかる人はすでにわかってる、わからない人には何の参考にもならない、そんな内容だと思う。こち亀で「OS」だの「インストール」だのといった専門用語(※そういう時代!)が飛び交っていて、柱をびっしり埋める脚注を読んでもさっぱりわからなかった回のように。


2018年11月16日 (金) [W53S] あと3年とちょっとは使える。「auが3G終了を発表。iPhone 5sなどLTEスマホも一部使用不可に――22年3月末 - Engadget 日本版」■次も au にする理由はない。まだ返してもらってないものもあるし>20100705p01


2018年11月15日 (木) au、通販で買うと携帯代から値引き~2019年1月から - Engadget 日本版」■au の真意はわからないけど、記事に書かれている「今回発表された「Wowma!」利用者に対する還元は、楽天との提携によって強化されるWowma!の取り扱いを増やしつつ、値下げへの要請にも応える狙いがありそうです。」は寝言で間違いない。逆に、通信料を原資もしくは呼び水にして通販を割り引いてるだろ、これ。


2018年11月14日 (水) 「円周率=4」を証明してみせましょう。“3.14…”を覆す新理論(?)に驚愕する声多数! 理数系学生「反論思いつかなくて草」」■この図なら区分求積法に持ち込んで不等号で上と下から挟む式になると思う。だからこの証明は上半分だけで途中。■そもそも弧の長さをどこでも近似していない。ただ 4 = 4 と言っているだけ。


2018年11月13日 (火) #世界ふしぎ発見 で「銀ブラ」の語源をクイズに出題し、三省堂国語辞典で誤りとされた説を正解として紹介する - Togetter」■モーガン・フリーマンの名前を冠した NHK の教養番組っぽいものが種々雑多な言説をフラットに取り上げていて、それはつまり業界の共通認識と異端児1人の言っていることの取り扱いに差がないということで、その回の放送内容のほとんどすべてを聞きかじっていた分野だからそういう判断ができたけど、それ以外で普通に「へーそーなんかー」と感心していては危険な番組だと思った。

最終更新: 2019-04-12T22:47+0900

[Git] GitHub でプルリクエストを出した後の作業手順

プルリクエストの元になったブランチは、自分の GitHub リポジトリにプッシュしたものが即座にリクエスト先にも反映される点で、公的なブランチだといえる。

プルリクエストに対する修正を事前に私的にテストするために、プルリクエストを意図せず Work in progress 状態にしないために、どういう手順をとるか。

前提として AppVeyor といった CI が自分の GitHub リポジトリと連動しており、GitHub にプッシュしなければテストが完了しないという事情がある。

元になったブランチから私的実験ブランチを派生させるのがいいと思う(これって常識?)。実験して結果を確かめたものを公的ブランチにマージし、必要ならリベース(並べ替え・併合)し、プッシュする。あるいは実験ブランチの段階でリベースによりコミットの取捨選択と整理を行っておき、公的ブランチにはマージとプッシュだけをしてもいい。

最終更新: 2019-04-12T22:47+0900

[Git] Git のサブコマンドについて

操作対象で分かれてるよね。そんで fetch, pull, push 以外はオフラインと考えていい。

remote
外部リポジトリ名
rebase
コミット
branch
ブランチ
checkout
ワーキングツリー
reset
refs/heads [インデックス] [ワーキングツリー]
fetch
refs/remotes
merge
refs から refs へ
pull
リモートからローカルのブランチへ
push
ローカルからリモートのブランチへ

rebase の用途は主にマージの1手段としてと、ブランチの付け替えと、コミットの整理とがあるけど、やってることはコミットオブジェクトの書き換え(※)であると。

※これは概念的な理解であって、もちろんコミットオブジェクトは名前に対して不変であるし、実際には refs/heads の書き換えも行っているはず。

ローカルブランチの削除は branch で行うけど、リモートリポジトリにあるブランチの削除を行うのは push であると。

git pull --all とかやっちゃうと操作対象はブランチだから、現在のブランチにマージコミットが追加されておろおろしてしまうと。git fetch --all にしよう。

もちろんオプションによりブランチだった対象がタグになったりするし、branch サブコマンドでリモート(※ローカルのリポジトリにフェッチ済みのリモート)にあるブランチを表示したりもできる。あくまでも基本の対象ではある。


2018年11月10日 (土) AppVeyor が便利すぎて、酷使しすぎていて、月に1万円以上は払っておかないと今後の扱われ方に不安を覚えるほど。


2018年11月09日 (金) 【悲報】Amazon社「コミュ力?それ最悪。個の力が高ければいいんだよ。」 : 暇人\(^o^)/速報 - ライブドアブログ」■社員同士のコミュニケーションって要は非同期作業を同期する行為でしょ。同期同期同期ではパフォーマンスはスケールしませんよ。アムダールの法則が見えるところまで行ってください。


2018年11月08日 (木) Firefox 52.9.0 がおそらく GitHub に切り捨てられた。スクリプトによる付加機能が軒並み無反応。アップデートしようにも「最新バージョンはご使用のシステムに対応していません」だもんなあ。■Vivaldi はインストールできたし、GitHub も使用できた。■Windows Vista は発売直後に買ったけど、10 はいらないんだよなあ。ほら>「【Windows 10】「勝手にLINEがインストールされていた」の声が増加中(2018年11月11日) | LINEの仕組み」■かくいう Vivaldi も背後のウィンドウとの境目がわからないフラットデザイン(デザイナー仕事しろ!)だけどな。■枠が欲しけりゃ「通常のウィンドウを使用する」という設定が Vivaldi にはあるんだよ。でも、右上のコントロール(_□✖)のサイズが設定とは異なり小さすぎるし、Aero Glass でない単色の青だしで、全然「通常のウィンドウ」ではない。


2018年11月07日 (水) [C++] g++ で -Og -g オプションを付けると if (this) {} else {} みたいなコードが通らなくなる。ヌルポインタかどうかを確かめることには問題がないし、仮想関数を呼び出そうとしたりしない限りは C++ 的にも許されている雰囲気を感じていたのだけど、デバッグ情報が this 付近にあると期待されていたりしてそれが問題につながるんだろうか。■ -g オプションだけなら OK だった。■ -Os でもアウトだったから問題は -Os, -Og という最適化オプションにある。許されてはいなかったのか……。■「C++ の標準としては未定義動作です