gitで特定ディレクトリで特定のタグ/ブランチをディスク容量ケチって追う
gitで以下のようなことをやりたい。試しにスクリプト書いてみたんだが、どうもダサい感じがする。
入力値: リポジトリURL と タグ/ブランチ
指定のリポジトリURLから、特定のタグ/ブランチをcloneしてくる。すでにclone済みであって、clone済みのものが最新であればcloneしてこない。タグ・ブランチ名がバージョン番号っぽいものであれば、–depth 1を使って容量を削減する。
用途としては、モジュールを特定バージョンやブランチに固定したいが、ブランチ名の場合には履歴もちゃんととってそのモジュールの開発もできるようにしたい、というもの。
試しに書いたもの
#!/bin/bash BASE_URL="git@xxxx:user" # $1 = repository_name, $2 = tag or branch if [[ "$1" =~ / ]]; then echo "abune-" # For avoiding 'rm -rf /' exit 1 fi git_dir="./$1/.git" if [ -d "$git_dir" ]; then local_hash=$(GIT_DIR=$git_dir git rev-parse HEAD) fi remote_hash=$(git ls-remote $BASE_URL/$1.git $2^{} | cut -f1) if [ -z "$remote_hash" ]; then remote_hash=$(git ls-remote $BASE_URL/$1.git $2 | cut -f1) if [ -z "$remote_hash "]; then echo "naiyo-" exit 2 fi fi if [ "$local_hash" != "$remote_hash" ]; then if [[ $2 =~ ^v[0-9.]+$ ]]; then clone_flag="--depth 1" else current_branch=$(GIT_DIR=$git_dir git rev-parse --abbrev-ref HEAD) if [ "$current_branch" = "$2" ]; then # just pull pushd $1 git pull origin $2 popd exit 0 fi clone_flag="" fi rm -rf $1 git clone $clone_flag --branch $2 $BASE_URL/$1.git if [ $? -ne 0 ]; then echo "yabainjan" fi else echo "nanmosen" fi
ダサいところ
指定されたtagがannotated tagの場合にはコミットそのもののhash値を取るために、一回^{}を付けて聞いているのがイケてない。annotated tagでない場合は2回聞いちゃうので遅くなる。
git ls-remote git@xxx:user/rep v0.0.1^{commit}
でうまくいくかと思ったけどダメだった。
git ls-remote git@xxx:user/rep v0.0.1*
というのも考えたが、v0.0.1^{}と同時にv0.0.13などもひっかかってしまうのでダメ。
こっちのほうがいい?
ローカルのほうですでにclone済みの場合には、
git describe --tag
した結果現在指しているタグを取得する。次に、取得したタグを用いて、そのタグがannonated tagだった場合annotated tagのhash値を取る。具体的には、
git show-ref --tag -d $fetched_tag
をして、一番下の1行を取得する。
これとリモートの指定されたhash値を比較する。これでリモートに対するコマンド発行数が1回に減らせそう。
ただ、もっとスマートに書けそうな気がするんだよなー。タグとブランチをちゃんと峻別したり、.gitディレクトリの中のファイルを見たりするとよさげか。というわけでブログで投げっぱなしジャーマン。ツッコミは@gunyarakunまで。