npmを使ったgitサブモジュールの簡単な代替案については、この回答の最後(最後の段落)にある注釈を参照してください ;)
次の回答では、リポジトリからフォルダを抽出して、そこからgitリポジトリを作成し、フォルダの代わりにサブモジュールとしてインクルードする方法を知っていることになります。
Gerg Bayer's の記事 Moving Files from one Git Repository to Another, Preserving History からインスパイアされました。
最初はこのようなものです。
<git repository A>
someFolders
someFiles
someLib <-- we want this to be a new repo and a git submodule!
some files
以下の手順では、この someLib
を <directory 1>
として参照します。
最後に、このようなものができあがります。
<git repository A>
someFolders
someFiles
@submodule --> <git repository B>
<git repository B>
someFolders
someFiles
分割するリポジトリの新しいコピーを取得します。
git clone <git repository A url>
cd <git repository A directory>
現在のフォルダが新しいリポジトリになるので、現在のリモートを削除します。
git remote rm origin
目的のフォルダのhistoryを展開し、コミットする
git filter-branch --subdirectory-filter <directory 1> -- --all
これで、ディレクトリ 1` のファイルを含む git リポジトリが、関連するすべてのコミット履歴とともにあなたのリポジトリのルートに作成されました。
オンラインリポジトリを作成し、新しいリポジトリをプッシュしましょう!
git remote add origin <git repository B url>
git push
最初のプッシュでは upstream
ブランチを設定する必要があるかもしれません。
git push --set-upstream origin master
<git repository A>
(任意、コメント参照)gitリポジトリB>の痕跡(ファイルやコミット履歴)を
<gitリポジトリA>`から削除し、このフォルダの履歴は一度だけにしたいのです。
これはgithubのRemoving sensitive dataを元にしています。
新しいフォルダに移動して
git clone <git repository A url>
cd <git repository A directory>
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch <directory 1> -r' --prune-empty --tag-name-filter cat -- --all
ディレクトリ1>を削除したいフォルダに置き換えてください。r
は指定したディレクトリの中で再帰的に実行されます :)。次に、--force
を使って origin/master
にプッシュします。
git push origin master --force
サブモジュール]3を <git repository B>
から <git repository A>
に作成する。
git submodule add <git repository B url>
git submodule update
git commit
期待通りに動作しているか確認し、push
します。
git push origin master
ここまでやって、私の場合、代わりにnpmを使って自分の依存関係を管理する方が適切だと気づきました。gitのURLやバージョンを指定することができるので、package.json git urls as dependenciesを参照してください。
この方法でやる場合、要件として使いたいリポジトリは npm module である必要があるので、 package.json
ファイルが含まれていないと、次のエラーが発生します: Error.ENOENT, open ལ/*npm.json
ファイルを開くには、次のようにします: package.json
ファイルが含まれていないと、要件として使いたいリポジトリは npm module である必要があります。ENOENT, open 'tmp.tgz-unpack/package.json'`.
npm]5 と git urls で依存関係を管理する を使うと楽かもしれません。
npm init
を実行します。npm install --save git://github.com/user/project.git#commit-ish
を実行します。GabLeRoux による解決策は、ブランチとそれに関連するコミットを潰しています。
余分なブランチやコミットをすべてクローンして保持するシンプルな方法です。
1 - この git エイリアスがあることを確認します。
git config --global alias.clone-branches '! git branch -a | sed -n "/\/HEAD /d; /\/master$/d; /remotes/p;" | xargs -L1 git checkout -t'
2 - リモートをクローンし、すべてのブランチをプルし、リモートを変更し、ディレクトリをフィルタリングし、プッシュします。
git clone [email protected]:user/existing-repo.git new-repo
cd new-repo
git clone-branches
git remote rm origin
git remote add origin [email protected]:user/new-repo.git
git remote -v
git filter-branch --subdirectory-filter my_directory/ -- --all
git push --all
git push --tags
GabLeRoux'の解決策は、git lfs
を使用していて、切り離したいディレクトリの下に大きなファイルがある場合以外はうまくいきます。この場合、ステップ3の後に、すべての大きなファイルが実際のファイルではなくポインターファイルとして残ります。おそらく、フィルターブランチの過程で .gitattributes
ファイルが削除されたことが原因だと思います。
このことに気づいて、私は以下の解決策を見つけました。
cp .gitattributes .git/info/attributes
git lfs が大きなファイルを追跡するために使用する .gitattributes
を .git/
ディレクトリにコピーして、削除されないようにする。
フィルターブランチが完了したら、新しいリポジトリでも git lfs を使用したい場合は .gitattributes
を元に戻すのを忘れないようにしてください。
mv .git/info/attributes .gitattributes
git add .gitattributes
git commit -m 'added back .gitattributes'