こんな多段操作をするしかないのか?するしかありません
gitの概念を考えてみれば、 こういう操作しか出来ないだろうと納得できます。 できますが、まぁ面倒ですね ;-)
gitの操作対象は、 つねに「リポジトリ(.git/というコントローラを擁するディレクトリ(階層))」(のみ) というところがポイントだと思います
実行例
SRC-REPOが対象(一部を切り出ししたいリポジトリ)で、
DST-REPOが(切り出したものを)取り込みたい側のリポジトリです。
SRC-REPO以下にある切り出したいサブディレクトリを
__subdir__(つまりSRC-REPO/__subdir__)と仮定しています。
$ git clone SRC-REPO
$ git clone DST-REPO
$ cd SRC-REPO
$ git filter-repo --path __subdir__
$ cd ../DST-REPO
$ git remote add TARGET ../DST-REPO
$ git fetch TARGET
$ git read-tree --prefix=tmp/ TARGET/main
$ git remote remove TARGET
... 調整作業 ...
$ git commit
$ git push
- 「… 調整作業 …」の部分
- tmp/subdir/ が作成されているはずです
- 適切な場所にgit mvなりしていってください
作業手順 Aパート【輸入元の操作】
- まず、操作する対象(輸入元)のリポジトリをチェックアウトします
- 新鮮(fresh)な作業リポジトリ(SRC-REPO)を作成し、それを操作します
- 注:そもそも新鮮(fresh)なリポジトリでないとgit filter-repoが動作しません。 これはfail-safeな仕様ですね
- 対象のデータベースを縮小する操作なので、決して、大元をいじってはいけません
- 当然、操作後の(この)作業リポジトリ(SRC-REPO)は捨てる前提です
- 新鮮(fresh)な作業リポジトリ(SRC-REPO)を作成し、それを操作します
- 対象(輸入元)のリポジトリ(SRC-REPO)から(importしたい)部分を切り出します
- git filter-repo というコマンドを使います
- git filter-repo というコマンドが(1.22以降)では使えます。 これは、いわゆる grep にあたる操作をするものです (フィルタという表現ですが、これだけでは、どっち向きのフィルタなのか分かりにくい;-)
- デフォルトではgit filter-repoは使えません。別途インストールが必要です
[インストール例] $ sudo apt install git-filter-repo- 引数に「切り出したいサブディレクトリ」を指定して、切り出す操作を実行します
[操作例] $ git clone github/hogeUser/SRC-REPO $ cd SRC-REPO $ git filter-repo --path __subdir__
作業手順 Bパート 【輸入先での操作】
importしたいgitリポジトリ側(DST-REPO)での作業です
- 追跡したいリポジトリに名前(ここでは TARGET)をつけてください。
ここで追跡する対象はSRC-REPO (すでに欲しい部分だけが切り抜き済みのリポジトリ)になります
- このマシン上にある(上で作業した)ディレクトリを指定してください
- githubにpushしてはいけません
$ cd DST-REPO $ git remote add TARGET 上で切り出し作業をしたディレクトリ(/どこか/SRC-REPO) `'` - TARGETの内容をfetchします。この結果、TARGETブランチが作成されます
- .git/ 以下にSRC-REPOからのデータが追加され、ブランチが作成されます
- 注:データベースに輸入されるだけでファイルは作成されません
- 注:このあとファイルを展開する作業が続きます
$ git fetch TARGET $ git branch -a * main remotes/TARGET/main remotes/origin/HEAD -> origin/main remotes/origin/main - TARGETブランチの内容をgit indexに読みこみます(いわゆるgit addした状態にします)
- 一式あらたにimportすればよい場合は git read-tree コマンドでimportできます
- indexに取りこんだあと、(git checkoutで)ファイルを展開します
$ git read-tree --prefix=target-dir/ TARGET/main $ git checkout -- .- ここで
target-dir/の右端の/(ディレクトリの意味)は大事みたい。忘れないこと - ちなみに、新規の場合に
git merge -s subtree ..を実行すると、fatal: refusing to merge unrelated historiesと怒られます - 同じ名前のディレクトリがあってマージが必要な場合は
git mergeです。 マージの難易度によってはmerge strategyの選択が必要になるようです
[例] (これは未実施のため、雰囲気のみ) $ git merge -s subtree -X subtree=target-dir TRACK/main - git status -s してみるとimportしたファイル群が表示されるはず
- git remote remove TARGET
- importするためだけに必要だったので、追跡対象は削除してOKです
- 適切な場所にファイルやディレクトリを移動(git mv …)するなりしてください
- git commit
- git push