Pertanyaan Membagi repositori Git besar ke banyak yang lebih kecil


Setelah berhasil mengubah gudang SVN menjadi Git, sekarang saya memiliki repositori Git yang sangat besar yang ingin saya bagi menjadi beberapa repositori yang lebih kecil dan mempertahankan sejarah.

Jadi, dapatkah seseorang membantu memecahkan sebuah repo yang mungkin terlihat seperti ini:

MyHugeRepo/
   .git/
   DIR_A/
   DIR_B/
   DIR_1/
   DIR_2/

Ke dua repositori yang terlihat seperti ini:

MyABRepo/
   .git
   DIR_A/
   DIR_B/

My12Repo/
   .git
   DIR_1/
   DIR_2/

Saya sudah mencoba mengikuti petunjuk dalam pertanyaan sebelumnya ini tetapi tidak benar-benar cocok ketika mencoba untuk memasukkan beberapa direktori ke repo terpisah (Lepaskan (pindahkan) subdirektori ke dalam repositori Git yang terpisah).


76
2017-10-11 22:32


asal


Jawaban:


Ini akan mengatur MyABRepo; Anda dapat melakukan My12Repo dengan cara yang sama.

git clone MyHugeRepo/ MyABRepo.tmp/
cd MyABRepo.tmp
git filter-branch --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD 

Referensi ke .git / refs / original / refs / heads / master tetap. Anda dapat menghapusnya dengan:

cd ..
git clone MyABRepo.tmp MyABRepo

Jika semua berjalan dengan baik Anda dapat menghapus MyABRepo.tmp.


Jika karena alasan tertentu Anda mendapatkan kesalahan terkait dengan .git-rewrite, Anda dapat mencoba ini:

git clone MyHugeRepo/ MyABRepo.tmp/
cd MyABRepo.tmp
git filter-branch -d /tmp/git-rewrite.tmp --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD 
cd ..
git clone MyABRepo.tmp MyABRepo

Ini akan membuat dan menggunakan /tmp/git-rewrite.tmp sebagai direktori sementara, bukan .git-rewrite. Tentu saja, Anda dapat mengganti jalur yang Anda inginkan, bukan /tmp/git-rewrite.tmp, selama Anda memiliki izin menulis, dan direktori belum ada.


71
2017-10-11 23:37



Anda bisa menggunakannya git filter-branch --index-filter dengan git rm --cached untuk menghapus direktori yang tidak diinginkan dari klon / salinan dari repositori asli Anda.

Sebagai contoh:

trim_repo() { : trim_repo src dst dir-to-trim-out...
  : uses printf %q: needs bash, zsh, or maybe ksh
  git clone "$1" "$2" &&
  (
    cd "$2" &&
    shift 2 &&

    : mirror original branches &&
    git checkout HEAD~0 2>/dev/null &&
    d=$(printf ' %q' "$@") &&
    git for-each-ref --shell --format='
      o=%(refname:short) b=${o#origin/} &&
      if test -n "$b" && test "$b" != HEAD; then 
        git branch --force --no-track "$b" "$o"
      fi
    ' refs/remotes/origin/ | sh -e &&
    git checkout - &&
    git remote rm origin &&

    : do the filtering &&
    git filter-branch \
      --index-filter 'git rm --ignore-unmatch --cached -r -- '"$d" \
      --tag-name-filter cat \
      --prune-empty \
      -- --all
  )
}
trim_repo MyHugeRepo MyABRepo DIR_1 DIR_2
trim_repo MyHugeRepo My12Repo DIR_A DIR_B

Anda harus secara manual menghapus setiap cabang atau tag yang tidak diperlukan dari repositori (mis. Jika Anda memiliki fitur-x-untuk-AB cabang, maka Anda mungkin ingin menghapusnya dari repositori “12”).


9
2017-10-12 00:01



Di sini adalah script ruby ​​yang akan melakukannya. https://gist.github.com/4341033


3
2017-12-19 22:26



Proyek git_split adalah skrip sederhana yang melakukan apa yang Anda cari. https://github.com/vangorra/git_split

Ubah direktori git ke repositori mereka sendiri di lokasi mereka sendiri. Tidak ada subtree bisnis lucu. Script ini akan mengambil direktori yang ada di repositori git Anda dan mengubah direktori itu menjadi repositori independen miliknya sendiri. Sepanjang jalan, itu akan menyalin seluruh sejarah perubahan untuk direktori yang Anda berikan.

./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
        src_repo  - The source repo to pull from.
        src_branch - The branch of the source repo to pull from. (usually master)
        relative_dir_path   - Relative path of the directory in the source repo to split.
        dest_repo - The repo to push to.

3
2018-01-06 02:45



Terima kasih atas jawaban Anda, tetapi saya akhirnya hanya menyalin repositori dua kali kemudian menghapus file yang tidak saya inginkan dari masing-masing. Saya akan menggunakan cabang-filter di kemudian hari untuk menghapus semua komit untuk file yang dihapus karena mereka sudah dikendalikan versi di tempat lain.

cp -R MyHugeRepo MyABRepo
cp -R MyHugeRepo My12Repo

cd MyABRepo/
rm -Rf DIR_1/ DIR_2/
git add -A
git commit -a

Ini berhasil untuk apa yang saya butuhkan.

EDIT: Tentu saja, hal yang sama dilakukan di My12Repo terhadap direktori A dan B. Ini memberi saya dua repo dengan sejarah yang identik sampai pada titik saya menghapus direktori yang tidak diinginkan.


0
2017-10-20 17:34