ひとつのワーキングコピーを複数の git レポジトリに振り向ける(て適宜切り替える)的な話

タイトルは大袈裟だけれども。

これが「誰でも思いつく簡単な話」なのかはよくわからんのだけれど、個人的には「日々欲しくなる/やりたくなる & めっさ簡単」なネタ。ただ、「あまりにも簡単であるがゆえにこれまでちゃんと整理して伝えようとは考えたことがない」ネタ。今回は少し「ちゃんと」これをする必要に迫られたので、まぁ一度は書いておこうかと。

「複数の git レポジトリ」と言ってる通りで、たぶん標準の git の範疇外の話のはず。違ってたらごめん、でも違っててもいいんだ、単純な話なんだから。範疇内の話では git switch とかブランチの話よ、そうではなくて、ね。

要するに、言い換えると「複数の .git を切り替える」という話で、なぜこういうことをしたいかと言えば、「チームのためのレポジトリとは別に、自分ローカルの管理も同時にしたい、しかも自分ローカルはリモートの git レポジトリとは完全に独立のものとしたい」から。具体的には、こういうこと:

1 [me@host: wk]$ git clone https://.../waga-team-no-prod.git
2 [me@host: wk]$ cd waga-team-no-prod
3 [me@host: waga-team-no-prod]$ mv .git ../.git.orig  # 退避
4 [me@host: waga-team-no-prod]$ git init  # オレオレローカルなレポジトリにしちまえよ
5 [me@host: waga-team-no-prod]$ git add *  # オレオレローカルなレポジトリに入れちまえよ
6 [me@host: waga-team-no-prod]$ git commit . -m 'comment.'  # オレオレローカルな...
7 [me@host: waga-team-no-prod]$ mv ../.git.orig .  # 退避したのを。。。

この状態にして、.git/.git.orig を適宜切り替えたい、という話ね。繰り返すけれど、この「オレオレローカル」がチーム全体に共有されるべきだ、というケースなら絶対にこれしちゃダメ、その場合は素直にブランチを使うのだぞ。

ここまでだけはこれまで日常的にやってたけど、「.git/.git.orig を適宜切り替えたい」をちったぁスマートにやれやしないかい、と思って書いたのがこれ:

switchdotgit.sh (→ 追記参照。間違えてる。)
 1 #! /bin/sh
 2 EXPRESSION="${1:-^$}"
 3 dotgitdir=$(pwd)
 4 while test \! -d "${dotgitdir}"/.git ; do
 5     dotgitdir=$(dirname "${dotgitdir}")
 6 done
 7 for gdn in ".git" ".git.orig" ; do
 8     url=$(grep 'url =' ${dotgitdir}/${gdn}/config | sed 's@^[ 	]*url *= *@@')
 9     if expr "${url}" : "${EXPRESSION}" > /dev/null ; then
10         exit 0
11     fi
12 done
13 mv ${dotgitdir}/.git ${dotgitdir}/.git_orig
14 mv ${dotgitdir}/.git.orig ${dotgitdir}/.git
15 mv ${dotgitdir}/.git_orig ${dotgitdir}/.git.orig

スクリプトの引数に、レポジトリの url のパターンを与えることで切り替えるてだけね:

1 [me@host: waga-team-no-prod]$ switchdotgit.sh "^$"
2 [me@host: waga-team-no-prod]$ git status .
3 ...
4 [me@host: waga-team-no-prod]$ switchdotgit.sh ".*/waga-team-no-prod.git"
5 [me@host: waga-team-no-prod]$ git status .
6 ...

19時追記:
そそっかしい…。たぶん最初のでも一方が「おれおれろーかる」でないなら期待通りの場合もあったかもしれないが、ダメじゃん…。こうよな:

switchdotgit.sh
 1 #! /bin/sh
 2 EXPRESSION="${1}"
 3 dotgitdir=$(pwd)
 4 while test \! -d "${dotgitdir}"/.git ; do
 5     dotgitdir=$(dirname "${dotgitdir}")
 6 done
 7 
 8 url=$(grep 'url =' ${dotgitdir}/.git/config | sed 's@^[ 	]*url *= *@@')
 9 test "${EXPRESSION}" = "${url}" && exit 0
10 expr "${url}" : "${EXPRESSION}" > /dev/null && exit 0
11 
12 mv ${dotgitdir}/.git ${dotgitdir}/.git_orig
13 mv ${dotgitdir}/.git.orig ${dotgitdir}/.git
14 mv ${dotgitdir}/.git_orig ${dotgitdir}/.git.orig
15 cat ${dotgitdir}/.git/config

使い方も微妙に違ってて:

1 [me@host: waga-team-no-prod]$ switchdotgit.sh ""  # ^$ じゃなくブランクを与えて…
2 [me@host: waga-team-no-prod]$ git status .
3 ...
4 [me@host: waga-team-no-prod]$ switchdotgit.sh ".*/waga-team-no-prod.git"
5 [me@host: waga-team-no-prod]$ git status .
6 ...