2つのディレクトリと複数のブランチを持つgitリポジトリがあります。それらを分割してすべてのブランチを作成したいと思います。
`-- Big-repo
|-- dir1
`-- dir2
Branches : branch1, branch2, branch3 ...
欲しいもの
Dir1とdir2を2つの別々のリポジトリとして分割し、両方のリポジトリにブランチbranch1、branch2 ...を保持したいと思います。
dir1
Branches : branch1, branch2, branch3 ...
dir2
Branches : branch1, branch2, branch3 ...
私が試したこと:
私はそれらを使用して2つのリポジトリに分割することができます
git subtree split -P dir1 -b dir1-only
git subtree split -P dir2 -b dir2-only
ただし、分離後にブランチは作成されません。
すべてのブランチを取得するには:
git checkout branch1 (in Big-repo)
git subtree split -p dir1 -b dir1-branch1
git checkout branch2 (in Big-repo)
git subtree split -p dir1 -b dir1-branch2
And Push these branches to newly created repo.
これにはより多くの手作業が必要であり、これを達成するための迅速な方法があると確信していますか?
何か案は???
git filter-branch
必要な機能を正確に提供します。 --subdirectory-filter
オプションを使用すると、subDirectory
の内容がディレクトリのルートにある新しいコミットのセットを作成できます。
git filter-branch --Prune-empty --subdirectory-filter subDirectory -- --branches
以下は、これを安全な方法で実行するための例です。独自のリポジトリ(この場合はdir1
)に分離されるサブディレクトリごとにこれを実行する必要があります。
まず、リポジトリのクローンを作成して、変更を分離します。
git clone yourRemote dir1Clone
cd dir1Clone
複製されたリポジトリを準備するために、すべてのリモートブランチをローカルブランチとして再作成します。 *
で始まるブランチは現在のブランチであるためスキップします。この場合、ヘッドレス状態であるため(no branch)
と表示されます。
# move to a headless state
# in order to delete all branches without issues
git checkout --detach
# delete all branches
git branch | grep --invert-match "*" | xargs git branch -D
すべてのリモートブランチをローカルで再作成するには、git branch --remotes
の結果を確認します。 ->
を含むものはブランチではないため、スキップします。
# get all local branches for remote
git branch --remotes --no-color | grep --invert-match "\->" | while read remote; do
git checkout --track "$remote"
done
# remove remote and remote branches
git remote remove Origin
最後に、filter-branch
コマンドを実行します。これにより、dir1
サブディレクトリにアクセスするすべてのコミットで新しいコミットが作成されます。このサブディレクトリにもアクセスするすべてのブランチが更新されます。出力には、更新されていないすべての参照が一覧表示されます。これは、dir1
にまったく触れていないブランチの場合です。
# Isolate dir1 and recreate branches
# --Prune-empty removes all commits that do not modify dir1
# -- --all updates all existing references, which is all existing branches
git filter-branch --Prune-empty --subdirectory-filter dir1 -- --all
この後、リポジトリのルートにdir1
を持つ新しいコミットのセットが作成されます。リモコンを追加して新しいコミットをプッシュするか、これらをすべて新しいリポジトリとして使用します。
リポジトリのサイズが気になる場合の追加の最後のステップとして:
リポジトリを更新したすべてのブランチに元のリポジトリのすべてのオブジェクトが残っている場合でも、ref-logを介してのみ到達できます。これらの読み取りを削除したい場合 コミットをガベージコレクションする方法
いくつかの追加リソース:
このスクリプトは私のために仕事をします:
#!/bin/bash
set -e
if [ -z "$3" ]; then
echo "usage: $0 /full/path/to/repository path/to/splitfolder/from/repository/root new_Origin"
exit
fi
repoDir=$1
folder=$2
newOrigin=$3
cd $repoDir
git checkout --detach
git branch | grep --invert-match "*" | xargs git branch -D
for remote in `git branch --remotes | grep --invert-match "\->"`
do
git checkout --track $remote
git add -vA *
git commit -vam "Changes from $remote" || true
done
git remote remove Origin
git filter-branch --Prune-empty --subdirectory-filter $folder -- --all
#Prune old objects
rm -rf .git/refs/original/*
git reflog expire --all --expire-unreachable=0
git repack -A -d
git Prune
#upload to new remote
git remote add Origin $newOrigin
git Push Origin master
for branch in `git branch | grep -v '\*'`
do
git Push Origin $branch
done