前書き
組込のC++プログラマ(2ねんせい)です。
プログラミングミリしら状態でうっかり仕事にしてしまったので、さっさと成長しないと食い殺される。助けて。
本題
表題のaliasが見た限りだと無かったので作った。
笑えるほどに環境依存なので要改変。というかgitもbashも何ならWindowsもLinuxも何も分からん状態で書いている。
Windows10, Git for Windows, git version 2.17.0.windows.1 で確認。(そもそも環境の書き方がこれで十分なのかすら判らない)
git show-file <ブランチ名orコミットハッシュ> <ファイルパス> &で動作する。
# e.g. コミットハッシュが7a65b4cのとき
git show-file 7a65b4c file/path/my_file.cpp &
などと打つと、AppDataの奥底にmy_file-7a65b4c.cppというファイルが生成されてサクラエディタで表示される。なおコミット指定をHEAD^^^^^などとするとmy_file-HEAD^^^^^.cppというクソダサファイルを生成できて少し楽しい。
&はシェルスクリプトのバックグラウンドプロセス指定のために付けている。(参考)
生成後のファイルは7日で削除される。
alias
一番下に少しマシになったバージョンがあるのでスクロールしてください。
[alias]
show-file = "!f(){ \
if [ $# -eq 2 ];then \
git clean-temp-file;\
repo=${1};\
repo_s=${repo##*/};\
f_path=${2};\
f_name=${f_path##*/};\
f_row_name=${f_name%.*};\
f_ext=${f_name##*.};\
git show ${repo}:${f_path} > C:/Users/[user_name]/AppData/Local/Temp/git-show/${f_row_name}-${repo_s}.${f_ext};\
if [ $? -eq 0 ];then \
sakura C:/Users/[user_name]/AppData/Local/Temp/git-show/${f_row_name}-${repo_s}.${f_ext};\
fi;\
else \
echo \"syntax error : git show-file <repo-name> <file-path>\";\
fi;\
};f"
clean-temp-file = !find C:/Users/[user_name]/AppData/Local/Temp/git-show/* -mtime +7 -exec rm {} +
[user_name]は各自のユーザ名。
AppData/Local/Temp/以下の適当なフォルダにgit showで見つけたファイルを拡張子付きで出力して、適当なエディタ(今回は自前の環境で最も軽いサクラエディタ)で開いているだけ。PATHが通っているプログラムなら何でもいいと思う。$EDITOR指定でも行けるのかもしれない(要検証)。
変数repoとf_pathをごちゃごちゃ弄ってるのは、複数のバージョンを同時に開きたい時のためのリネーム処理。用途によってはリネームしない方が適しているかもしれないし、その場合はaliasももっと短くなる。なおブランチ名の/を置き換える処理をしていないので、例えばfeature/some_branchとorigin/feature/some_branchはどちらもmy_file-some_branch.cppにリネームされてしまう。片手落ちも良いところである。(今ふと思ったが、rev-parseでハッシュ取得して使っても良いかもしれない)。
clean-temp-fileは最終更新日から7日経過したファイルを削除するだけのコマンドなので普通にベタ書きしても多分動く。単にデバッグ用に書いたコードを流用しているだけ(手抜き)。
不満点(要改善点)
-
git showに失敗してもファイルが生成されてしまう上にbashが入力待ち状態で停止する(Ctrl+Cなどで脱出) -
AppDataの絶対パスは何らかの方法で取得できそうな気がする -
core.editorを取得して使うようにすると(VSCodeとか使ってる人は)便利かも - (このコマンドに限らず)bashから外部のツールを起動する際、末尾にいちいち
&を付けないと並列起動できない......
参考
- gitで特定のコミット(リビジョン)からファイルを取り出す
- [gitのaliasコマンドに引数を渡す方法]
(https://qiita.com/yatemmma/items/22aa62e232776f4f330b) - シェルスクリプトで単純に並列実行・直列実行を行う
以下日記
使ってみて思ったが、正直git difftool --dir-diffの下位互換みたいな雰囲気がある。特定ファイルを参照したいときは9割方「その時点で生じた差分を見たい」時だということを失念していた。まぁ変更履歴はどうでもいいから特定時点のファイル見たいとかいう要望には応えられるし……いやそれならgit checkoutでも概ねいけるんだけど。
AppData/Local/Temp/以下に一時ファイルを生成するアイデアは、なんかdifftoolの挙動がそうなってるっぽかったので丸々パクった(免責事項)。
サクッと書いているがbashやgitのエスケープシーケンスの挙動が分からずにほぼ丸一日掛かっている。というか\で改行できることすら知らなかった。未だに詳細が分かっていない。
初心者なのでマサカリを沢山投げつけて頂ければ幸いです。頑張ります。
更新
ちょっとマシになった
[alias]
# 特定の時点(コミット/ブランチ等)の特定ファイルをエディタで開く.
# 作業ディレクトリは(Windowsの場合)AppData/Local/Temp/git-show/ であり、1週間以上経過すると削除される.
# git config core.editorに適当なエディタを設定していないと動作しないため注意.
show-file = "!f(){ \
if [ $# -eq 2 ];then \
local repo=$(git rev-parse --short ${1});\
if [ "${?}" -ne 0 ]; then \
return 1;\
fi;\
git ls-files ${2} > /dev/null || return 1 ; \
local f_path=${2};\
local f_name=${f_path##*/};\
local f_row_name=${f_name%.*};\
local f_ext=${f_name##*.};\
mkdir -p /tmp/git-show;\
git show ${repo}:${f_path} > /tmp/git-show/${f_row_name}-${repo}.${f_ext};\
if [ $? -eq 0 ];then \
$(git config core.editor) /tmp/git-show/${f_row_name}-${repo}.${f_ext} &\
fi;\
else \
echo \"syntax error : git show-file <repo-name> <file-path>\";\
fi;\
find /tmp/git-show/* -mtime +7 -exec rm {} + ;\
};f"
まず、作業ディレクトリをtmpにした。Git for Windowsのインストール時点でtmpがAppData\Local\Tempに設定されているらしく、これで正しく動く。当然Linuxでも動く……はず。
次に第一引数をgit rev-parseに、第二引数をgit ls-filesに渡して入力値チェックを行った。
rev-parse --shortはHEADでもブランチ名でも任意桁のコミットハッシュでも全て少ない桁のコミットハッシュに変換してくれるので、入力値チェックに使いやすい。こちらは変数に入れる都合上、$?の値を見て不正だったら1を返して終了するようにした。
第二引数のls-filesは単に実在するか否かのチェックだけだったので、標準出力はdev/nullに投げ捨てた上で||で繋ぎ、失敗したら1を返して終了するようにした。
最後に起動するエディタをgit config core.editorから引っ張ってくるようにした。設定していないと動かないためここはまだちょっと改良の余地がある。