Pertanyaan ini didasarkan pada subdirektori Lepaskan ke dalam repositori Git terpisah
Alih-alih melepaskan satu subdirektori, saya ingin melepaskan pasangan. Misalnya, pohon direktori saya saat ini terlihat seperti ini:
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ
Dan saya ingin ini sebagai gantinya:
/apps
/AAA
/libs
/XXX
The --subdirectory-filter
argumen untuk git filter-branch
tidak akan bekerja karena mendapat menyingkirkan segala sesuatu kecuali untuk direktori yang diberikan pertama kali run. Saya pikir menggunakan --index-filter
argumen untuk semua file yang tidak diinginkan akan berhasil (meskipun membosankan), tetapi jika saya mencoba menjalankannya lebih dari sekali, saya mendapatkan pesan berikut:
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
Ada ide? TIA
sumber
--tag-name-filter cat
parameter AndaLangkah manual dengan perintah git sederhana
Rencananya adalah untuk membagi direktori individu menjadi repositori sendiri, lalu menggabungkannya bersama. Langkah-langkah manual berikut tidak menggunakan skrip geek-to-use tetapi perintah yang mudah dipahami dan dapat membantu menggabungkan N sub-folder tambahan ke dalam satu repositori.
Membagi
Anggaplah repo asli Anda adalah: original_repo
1 - Aplikasi terpisah:
2 - Pisahkan libs
Lanjutkan jika Anda memiliki lebih dari 2 folder. Sekarang Anda akan memiliki dua repositori git baru dan sementara.
Taklukkan dengan Menggabungkan aplikasi dan libs
3 - Siapkan repo baru:
Dan Anda harus membuat setidaknya satu komitmen. Jika tiga baris berikut harus dilewati, repo pertama Anda akan langsung muncul di bawah root repo Anda:
Dengan file temp yang dikomit,
merge
perintah di bagian selanjutnya akan berhenti seperti yang diharapkan.Mengambil dari umpan balik pengguna, daripada menambahkan file acak seperti
a_file_and_make_a_commit
, Anda dapat memilih untuk menambahkan.gitignore
, atauREADME.md
dll.4 - Gabungkan repo aplikasi terlebih dahulu:
Sekarang Anda akan melihat direktori aplikasi di dalam repositori baru Anda.
git log
harus menunjukkan semua pesan komit historis yang relevan.Catatan: seperti yang Chris catat di bawah dalam komentar, untuk versi terbaru (> = 2.9) dari git, Anda perlu menentukan
--allow-unrelated-histories
dengangit merge
5 - Gabungkan repo libs berikutnya dengan cara yang sama:
Lanjutkan jika Anda memiliki lebih dari 2 repo untuk digabungkan.
Referensi: Gabungkan subdirektori dari repositori lain dengan git
sumber
.gitignore
danREADME.md
file.git merge .. git read-tree
langkah tersebut, karena pendekatan ini mencatatnya sebagai file yang baru ditambahkan dan semua git guis saya tidak membuat sambungan ke komit sebelumnya.Mengapa Anda ingin berlari
filter-branch
lebih dari sekali? Anda dapat melakukan semuanya dalam satu sapuan, jadi tidak perlu memaksanya (perhatikan bahwa Anda perluextglob
mengaktifkannya di shell Anda agar ini berfungsi):Ini harus menyingkirkan semua perubahan di subdirektori yang tidak diinginkan dan menyimpan semua cabang dan komit Anda (kecuali mereka hanya memengaruhi file di subdirektori yang dipangkas, berdasarkan
--prune-empty
) - tidak ada masalah dengan komit duplikat, dll.Setelah operasi ini, direktori yang tidak diinginkan akan terdaftar sebagai tidak dilacak oleh
git status
.The
$(ls ...)
perlu stextglob
dievaluasi oleh shell Anda bukan filter indeks, yang menggunakansh
builtineval
(di manaextglob
tidak tersedia). Lihat Bagaimana cara mengaktifkan opsi shell di git? untuk detail lebih lanjut tentang itu.sumber
git
perintah secara eksklusif , dan karenanya tidak rentan terhadap perbedaan dalam carals
interpretasi di seluruh sistem operasi, seperti yang ditemukan @Bae.Menjawab pertanyaan saya sendiri di sini ... setelah banyak trial and error.
Saya berhasil melakukan ini menggunakan kombinasi
git subtree
dangit-stitch-repo
. Instruksi ini didasarkan pada:Pertama, saya mengeluarkan direktori yang ingin saya simpan ke dalam repositori terpisah:
Saya kemudian membuat repositori kosong baru, dan mengimpor / menjahit dua yang terakhir ke dalamnya:
Ini menciptakan dua cabang,
master-A
danmaster-B
, masing-masing memegang konten dari salah satu repo yang dijahit. Untuk menggabungkannya dan membersihkan:Sekarang saya tidak begitu yakin bagaimana / kapan ini terjadi, tetapi setelah yang pertama
checkout
dan yangpull
, kode secara ajaib bergabung ke dalam cabang master (wawasan apa pun tentang apa yang terjadi di sini dihargai!)Semuanya tampaknya telah bekerja seperti yang diharapkan, kecuali jika saya melihat melalui
newRepo
riwayat komit, ada duplikat ketika set perubahan mempengaruhi keduanyaapps/AAA
danlibs/XXX
. Jika ada cara untuk menghapus duplikat, maka itu akan sempurna.sumber
export PERL5LIB="$PERL5LIB:/usr/local/git/lib/perl5/site_perl/"
ke konfigurasi bash saya agar dapat menemukan Git.pm. Kemudian saya menginstalnya dengan cpan.git subtree add
untuk melakukan tugas ini. Lihat stackoverflow.com/a/58253979/1894803Solusi mudah: git-filter-repo
Saya memiliki masalah serupa dan, setelah meninjau berbagai pendekatan yang tercantum di sini, saya menemukan git-filter-repo . Direkomendasikan sebagai alternatif dari git-filter-branch dalam dokumentasi resmi git di sini .
Untuk membuat repositori baru dari subset direktori dalam repositori yang sudah ada, Anda dapat menggunakan perintah:
Filter banyak file / folder dengan merangkainya:
Jadi, untuk menjawab pertanyaan awal , dengan git-filter-repo Anda hanya memerlukan perintah berikut:
sumber
Saya telah menulis filter git untuk menyelesaikan masalah ini dengan tepat. Ini memiliki nama fantastis git_filter dan terletak di github di sini:
https://github.com/slobobaby/git_filter
Ini didasarkan pada libgit2 yang sangat baik.
Saya perlu membagi repositori besar dengan banyak komit (~ 100000) dan solusi berdasarkan cabang filter git membutuhkan beberapa hari untuk dijalankan. git_filter membutuhkan waktu satu menit untuk melakukan hal yang sama.
sumber
Gunakan ekstensi git 'git split'
git splits
adalah skrip bash yang merupakan pembungkusgit branch-filter
yang saya buat sebagai ekstensi git, berdasarkan solusi jkeating .Itu dibuat tepat untuk situasi ini. Untuk kesalahan Anda, coba gunakan
git splits -f
opsi untuk memaksa penghapusan cadangan. Karenagit splits
beroperasi pada cabang baru, itu tidak akan menulis ulang cabang Anda saat ini, jadi cadangannya tidak relevan. Lihat readme untuk detail lebih lanjut dan pastikan untuk menggunakannya pada salinan / klon repo Anda (untuk berjaga-jaga!) .git splits
.Pisahkan direktori menjadi cabang lokal
#change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
#split multiple directories into new branch XYZ git splits -b XYZ apps/AAA libs/ZZZ
Buat repo kosong di suatu tempat. Kami akan menganggap kami telah membuat repo kosong yang disebut
xyz
di GitHub yang memiliki jalur:[email protected]:simpliwp/xyz.git
Dorong ke repo baru.
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz [email protected]:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master
Gandakan repo jarak jauh yang baru dibuat ke direktori lokal baru
#change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone [email protected]:simpliwp/xyz.git
sumber
sumber
for
Loop bernilai mengakui, sejak jawaban serupa lainnya tidak memasukkannya. Jika Anda tidak memiliki salinan lokal dari setiap cabang di klon Anda, makafilter-branch
tidak akan memperhitungkannya sebagai bagian dari penulisan ulangnya, yang berpotensi mengecualikan file yang diperkenalkan di cabang lain, tetapi belum digabungkan dengan cabang Anda saat ini. (Meskipun itu juga layak dilakukangit fetch
di cabang mana pun yang telah Anda periksa sebelumnya untuk memastikan bahwa mereka tetap terkini.)Ya. Paksa menimpa cadangan dengan menggunakan
-f
tanda pada panggilan berikutnyafilter-branch
untuk mengganti peringatan itu. :) Jika tidak, saya pikir Anda memiliki solusi (yaitu, hapus direktori yang tidak diinginkan sekaligusfilter-branch
).sumber
Hapus cadangan yang ada di bawah direktori .git di refs / original seperti yang disarankan pesan. Direktori disembunyikan.
sumber