Git

ghq管理下のリポジトリを検索するとき、自分で作ったのから絞り込めるようにした

からの続き。

あれ以来、特に置き場の決まっていないなにかをGithubからcloneするときはghq getして、シェル関数で検索できるようにしています。便利。

しかし、管理下にあるリポジトリが増えるにつれ、自分で作ったリポジトリだけ検索したい場合が増えてきました。

そこで、シェル関数をちょっと弄って、「ghq全体から検索」と「自分で作ったリポジトリの中から検索」を分けてみました。

シェル関数

.bashrcで定義。

参考として、ghq管理下のディレクトリ構成は以下のようになります。

(ghqルートディレクトリ)/(リモートリポジトリのドメイン)/(ユーザ名)/(プロジェクト名)

~/.gitconfigでghqルートディレクトリを指定。

1
2
[ghq]
root = ~/ghq

するとこんな感じ。

~/ghq/github.com/catfist/MyHexo
~/ghq/bibucket.org/catfist/dotfiles

ghq listで検索する場合、ドメインは検索対象になりません。(ユーザ名)/(プロジェクト名)から部分一致検索されます。

1個だけ出力して即cd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 自分で作ったのだけ(find repositories)
fr ()
{
dir=$(ghq list -p "catfist/"|grep -im1 "$(ghq root)/[^/]*/catfist/.*$1.*")
if [ -d "$dir" ]; then
cd "$dir"
pwd
else
echo "ERROR:No hit";
fi
}
# ghq全体(find repositories all)
fra ()
{
dir=$(ghq list -p|grep -im1 ".*$1.*")
if [ -d "$dir" ]; then
cd "$dir"
pwd
else
echo "ERROR:No hit"
fi
}

pecoで絞り込みしてcd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 自分で作ったのだけ(ghq+peco)
gp () {
dir=$(ghq list -p catfist/|grep "$(ghq root)/.*/catfist/.*$1.*"|peco)
if [ -d "$dir" ]; then
cd "$dir"
pwd
else
echo "ERROR:No hit"
fi
}
# ghq全体(ghq+peco all)
gpa () {
dir=$(ghq list -p "$1"|peco)
if [ -d "$dir" ]; then
cd "$dir"
pwd
else
echo "ERROR:No hit"
fi
}

横着しないでGitでブランチ切ってフォークしてみた

完全に自分用メモ。

あるいは以下記事の反省。

目的

Alfred Workflowの開発で、スクリプトをGUIウインドウ(データ的にはinfo.plist)に入力したものと、スクリプトファイル化したものを分ける。

実は両方のバージョンを別のWorkflowとして残してあるので、ひとつにしたい。どっちで作業したかわかんなくなりがちだし。

手順

プロジェクトディレクトリに移動。

1
cd (プロジェクトディレクトリのパス)

まず、現在の状態が失われないよう、コミットしておく。

1
2
git add -A
git commit -m "modify"

次に、新規ブランチを作成し、そのブランチに切り替える。

1
2
3
4
git checkout -b plistonly
# 以下でも良し
# git branch plistonly
# git checkout plistonly

ここはFinderで作業。.gitディレクトリを除いて現バージョンのファイルを削除し、旧バージョンのファイルをコピペ。

次に、旧バージョンの内容を’plistonly’ブランチにコミットする。

1
2
git add -A
git commit -m "re-init plistonly"

最後に、’master’ブランチに切り替え、元の状態が保存されているか確認する。

1
git checkout master

無事に元の状態が復元された。

Hexoのローカルファイルを吹っ飛ばしたので粛々と復旧した件

Hexoのローカルファイルを吹っ飛ばした

ghq管理下にハードリンクとかやってたら、なんか変になったハードリンクを削除した際に、なぜか大元まで消えてしまいました。

一瞬だけ頭を抱えた後、まあデプロイ済みのデータをcloneすればよかろうと思い立ち実行。

Herokuのリモートリポジトリを確認

コンテンツはHerokuにデプロイしているので、まずHerokuにログインしてリモートリポジトリを確認します。

https://dashboard-next.heroku.com/apps/wbtmiu/settingsにアクセスしてGit URLを確認。このブログの場合、git@heroku.com:wbtmiu.gitになっています。

Herokuだと、GithubのようなGitホスティングサービスと違ってリモートリポジトリの内容が見えませんが、前git ls-filesしたとき,publicディレクトリ以外もリストされていたので完全に復旧できる……はず。

clone

1
git clone git@heroku.com:wbtmiu.git wbtmiu

とやってクローン。source/_draftsの内容まで復旧しました。

Hexoのdeployコマンドでやってることがわりと謎ですが、どうもソースを全部deployしてアクセスをpublicディレクトリに誘導しているっぽい。の、かな。

git branch -rするとorigin/masterしか出てこないから、Octopressみたくソース専用のブランチ切ってコンテンツだけをorigin/masterにデプロイしてるとかではないと思う。

ともあれ、Hexoでdeployしている場合、ソースも全部保存されているのでみなさん安心しましょう。

分散したローカルリポジトリをhln+ghq+pecoで管理する

こんなことをやっていたら、それghqという彼方からの説教が聞こえたので。

ghqとは

Gitのローカルリポジトリを一括管理できるコマンドラインツールです。指定したディレクトリ以下にローカルリポジトリを配置することにより、検索してcdとかが簡単にできます。

pecoとは

標準入力をインクリメンタルサーチするコマンドラインツールです。これにより、ghq管理下のリポジトリをインクリメンタルサーチすることができます。

ローカルリポジトリの分散

ghq+pecoによるローカルリポジトリ管理は非常に快適なのですが、一身上の都合によりディレクトリを移動できないリポジトリも存在します。Alfred WorkflowとかSublime Textの設定ファイルとか。

ghqのルートディレクトリ以下に/プロジェクト名/.gitを配置しないと、ghqで管理することができません。

どうするか。

ディレクトリのハードリンクを作成する

hlnを利用して、ghqルートディレクトリ以下にディレクトリのハードリンクを作成します。

例えば、Alfred Workflowのディレクトリをターミナルで開いているとして…

1
2
3
$ hln $(pwd) $(ghq root)/github.com/catfist/Add-to-Listacular
$ ghq list Add
github.com/catfist/Add-to-Listacular

こんな具合ですね。当初、シンボリックリンクとかエイリアスとかでなんとかしようとして吐きそうになってました。

おまけ:Gistsもghqで管理しようとしたが

gistyで既存のGistsを全部ローカルに引っ張れるので、これでコード管理楽勝じゃんヤッホーと一瞬だけ思ったのですが。

スクリーンショット

これはつらい。人間が読めるディレクトリ名してないので無理があります。

Gistsだけは別枠で管理するしかなさそうです。まあ、実際そのほうがいいとも思う。

Gitなにそれおいしいのというバックアップ用シェル関数を書いてみた

Git、便利ですよね。

やったこと全部記録されてて、自由に切り戻したりできるし、分岐させて別々のバージョン作ったりもできますしね。

でもね、それはそれでいいんだけど、普通にファイルとして残しといたほうが楽な場合も多々ありませんか?

コピーしましょう。

.bashrcに以下の通り記述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bu () {
if [ ! -d _backup ];then
mkdir _backup
echo "_backup/" >> .gitignore
fi
today=`date '+%Y-%m-%d'`
if [ -d _backup/$today ];then
rm -rf _backup/$today
fi
mkdir _backup/$today
for file in `git ls-files`
do
cp $file _backup/$today
done
}

_backup以下に日付フォルダを作り、そこにgitにステージされたファイルをコピーします。_backupは.gitignoreに追記してステージしないようにします。

冒涜的。

Gitのローカルリポジトリを簡単に呼び出したくて考えた

Alfred WorkflowをGithubで公開しているのだが

しているのですが。

info.plistを直接弄る気合いが入ってないので、Alfred Workflowの開発においてローカルリポジトリ=Workflowフォルダ(~/Library/Application Support/Alfred 2/Alfred.alfredpreferences/workflows 以下)を開いていることがあまりありません。

で、コミットとかプッシュとか簡単にできるように考えてみました。

やりたいこと

  • 登録したリポジトリを検索する
  • cdする
  • export PS1="リポジトリ名"してプロンプトを見やすくする
    • Workflowフォルダのパスがごちゃってるので、デフォルトのプロンプトだと見づらい
    • Workflow名も入ってないし

案1:Alfred Workflow

最初はこんなAlfred Workflowを組んでいました。

スクリーンショット

アクションはTerminal Command、Run Script、AppleScriptのどれでもいけるのですが、いろいろ準備したログがターミナルに残るのが気にくわない。

一応、一度書いたものをGistで上げておきます。

https://gist.github.com/catfist/05fa098a7e88af806702

案2:.bashrcに書く

ログを残さずに色々準備するなら.bashrcでしょう。別にシェルスクリプトファイルとして作ってもいいのですが。

というわけで、.bashrcに以下のようなシェル関数を書き込んでおきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Git Repositories
repo () {
# リポジトリ情報を配列変数reposに格納
repos=(
"Add to Listacular,~/Library/Application Support/Alfred 2/Alfred.alfredpreferences/workflows/user.workflow.AC1E93A3-9A1D-4E8C-ACE7-DC3DDBB87B10"
"MyHexo,~/Library/Application Support/Alfred 2/Alfred.alfredpreferences/workflows/user.workflow.D2F59E8A-D118-44C0-A0B1-BEF01F3B9F44"
"GithubUserPage,~/GitHub/catfist.github.io"
"dotfiles,~/dotfiles"
)
)
# 対象リポジトリを引数で検索してrepo変数に格納
IFS=$'\n'
# 大文字小文字を無視/1個だけ検索/最初のカンマ以前を引っかける
repo=`echo "${repos[*]}" | grep -i -m1 "^[^,]*$1[^,]*,"`
# ヒットがあった場合
if [ -n "$repo" ];then
# リポジトリ名とパスをカンマ区切りで読み出しname,path変数に格納
IFS=',' read name path <<< "$repo"
# パスのチルダ展開ができないのでsedで擬似チルダ展開
path=`echo "$path" | sed "s%~%$HOME%"`
# プロンプト/タイトルを変更
export PS1="repo:${name}$ "
PROMPT_COMMAND='echo -ne "\033]0;${repo}:${PWD/$HOME/~}\007"'
# カレントディレクトリをリポジトリに移動
cd "$path"
# ヒットがなかった場合はエラー表示
else
echo "ERROR: It is not exist repository."
fi
}

(2014-11-24更新:ヒットなしの場合に対応)

これで、repo addとかするとターミナルでリポジトリを開くことができます。

Alfred Workflowでコンフィグファイルを利用する

ユーザ情報の管理がめんどくさい

最近Alfred Workflowを作ったり配布したりしているのですが、けっこう悩まされたのがユーザ情報の管理です。具体的には、いじるファイルを置いてあるフォルダパスとかです。

まあ、シェルスクリプトにdir=~/heroku/wbtmiu.herokuapp.comとか書いたりするわけですが、そうするとふたつ問題がありまして。

  1. パスを必要とするシェルスクリプト全てに記述する必要があり、変更が入ると書き換えがめどい
  2. 配布するとき削除しないと見られちゃう

1については、分岐処理とScript Filterを駆使してシェルスクリプトをまとめることである程度軽減できるのですが、限度がありますし2はどうしようもありません。

困る。

ファイルとして管理すればいい

そこで、ユーザ情報を書き込むファイルを作ってしまうことにします。

例えばWorkflowフォルダに「Config」というファイルを作って、2行目にフォルダパスを書き込むことにすれば、以下のようなスクリプトでパスを取り出すことができます。

1
2
3
# Configの2行目を出力し、自動でチルダ展開できないのでチルダをホームディレクトリに置換する
# 式の区切り文字にスラッシュを使うとパスと混ざるので、何でもいいけどとりあえず%を使う
dir=`sed -n 2p Config | sed "s%~%$HOME%"`

こうすれば、シェルスクリプトがいくつあっても、同様のスクリプトで情報を取り出すことができます。

Gitで管理する場合、.gitingnoreにConfigを書いておけばGithubとかで公開されることもありません。Configを生成するアクションを含めておくとなおよし。

Heroku CLIでApp名指定を要求される場合の対策

Heroku CLIでApp名指定を省略できない場合がある

強力なコマンドラインインターフェースはHerokuの大きな魅力の一つです。ログインが必要ですが、Gitの操作も含めて、作業を省力化できる様々なコマンドが用意されています。

その中でも、heroku openheroku renameなどのアプリ関連の操作は、アプリ名を省略しても動く場合とそうでない場合があります。

アプリ名の指定を要求されるのは、作業中のプロジェクト(カレントディレクトリ)が複数のアプリに関連付けられている場合です。つまり、heroku listを実行すると、複数のアプリが表示されるはずです。

テストで色々作ったり消したりしたけど、もう特定のアプリしかいじらないから省略させてよという場合、.git/configを編集する必要があります。

.git/configの編集

vim .git/configとかして.git/configを見ると、以下のような記述があります。

1
2
3
4
5
6
7
8
9
[branch "master"]
remote = git@heroku.com:hogehoge.git
merge = refs/heads/master
[remote "heroku"]
url = git@heroku.com:hogehoge.git
fetch = +refs/heads/*:refs/remotes/heroku/*
[remote "origin"]
url = git@heroku.com:hogehoge.git
fetch = +refs/heads/*:refs/remotes/origin/*

これは、このローカルリポジトリに関連付けられているリモートリポジトリ=アプリの情報です。

heroku listで複数出る場合、remoteurlが複数存在するはずなので、これを削除して、上記例のようにひとつだけにします。

すると、heroku openでアプリ名を指定しなくても、ブラウザで開けるようになります。