Saya memiliki sebuah aplikasi web yang mengeksplorasi aplikasi web lain dengan cara tertentu. Ini berisi beberapa web demo di demo
folder dan salah satu demo yang sekarang harus memiliki itu's repositori sendiri. Saya ingin membuat repositori terpisah untuk aplikasi demo ini dan membuatnya menjadi subpackage submodule dari repositori utama tanpa kehilangan komit sejarah.
Adalah mungkin untuk tetap komit sejarah dari file dalam repositori's folder dan membuat repositori dari itu dan menggunakannya sebagai submodule sebaliknya?
Lihat catatan di akhir jawaban ini (paragraf terakhir) untuk alternatif yang cepat untuk git submodul menggunakan npm ;)
Dalam jawaban berikut, anda akan tahu bagaimana untuk mengekstrak folder dari repositori dan membuat repositori git dari itu dan kemudian termasuk sebagai submodule bukan folder.
Terinspirasi dari Gerg Bayer's artikel Memindahkan File dari satu Repositori Git yang Lain, Melestarikan Sejarah
Di awal, kami memiliki sesuatu seperti ini:
<git repository A>
someFolders
someFiles
someLib <-- we want this to be a new repo and a git submodule!
some files
Dalam langkah-langkah di bawah ini, saya akan menyebut ini someLib
sebagai <direktori 1>
.
Pada akhirnya, kita akan memiliki sesuatu seperti ini:
<git repository A>
someFolders
someFiles
@submodule --> <git repository B>
<git repository B>
someFolders
someFiles
Mendapatkan salinan repositori untuk membagi.
git clone <git repository A url>
cd <git repository A directory>
Folder saat ini akan menjadi repositori baru sehingga menghapus jarak jauh saat ini.
git remote rm origin
Ekstrak sejarah folder yang diinginkan dan melakukan itu
git filter-branch --subdirectory-filter <directory 1> -- --all
Anda sekarang harus memiliki repositori git dengan file dari direktori 1` di repo's root dengan semua yang terkait komit sejarah.
Membuat repositori online dan mendorong anda repositori baru!
git remote add origin <git repository B url>
git push
Anda mungkin perlu untuk mengatur hulu
cabang untuk mendorong pertama
git push --set-upstream origin master
<repositori git A>
(opsional, lihat komentar)Kami ingin menghapus jejak (file dan melakukan sejarah) dari <repositori git B>
dari <repositori git A>
jadi sejarah untuk folder ini hanya ada sekali.
Hal ini didasarkan pada Menghapus data sensitif dari github.
Pergi ke folder baru dan
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
Ganti <direktori 1>
oleh folder yang ingin anda hapus. -r
akan melakukannya secara rekursif dalam direktori tertentu :). Sekarang mendorong untuk asal/induk
dengan --force
git push origin master --force
Membuat submodule dari <repositori git B>
menjadi <repositori git A>
git submodule add <git repository B url>
git submodule update
git commit
Memverifikasi jika semuanya bekerja seperti yang diharapkan dan push
git push origin master
Setelah melakukan semua ini, saya menyadari dalam kasus saya, itu lebih tepat untuk menggunakan npm untuk mengelola sendiri dependensi sebagai gantinya. Kita dapat menentukan git url dan versi, lihat paket.json git url sebagai dependensi.
Jika anda melakukannya dengan cara ini, repositori yang ingin anda gunakan sebagai kebutuhan yang harus *npm modul* sehingga harus mengandung paket.json
file atau anda'll mendapatkan error ini: Error: ENOENT, pembukaan 'tmp.tgz-membongkar/paket.json'
.
Anda mungkin merasa lebih mudah untuk menggunakan npm dan mengelola dependensi dengan git url:
npm init
dalam kedua repositori npm install-simpan git://github.com/user/proyek.git#melakukan-ish
di mana anda ingin menginstal dependensiSolusinya by @GabLeRoux squashes cabang-cabang, dan terkait melakukan.
Cara yang mudah untuk mengkloning dan membuat semua orang tambahan cabang-cabang dan melakukan:
1 - pastikan anda memiliki git alias
git config --global alias.clone-branches '! git branch -a | sed -n "/\/HEAD /d; /\/master$/d; /remotes/p;" | xargs -L1 git checkout -t'
2 - Clone remote, tarik semua cabang, mengubah jarak jauh, filter direktori anda, mendorong
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's solusi bekerja dengan baik kecuali jika anda menggunakan git lfsdan memiliki besar file di bawah direktori yang ingin anda lepaskan. Dalam kasus itu, setelah langkah 3 semua file besar akan tetap menjadi pointer file yang bukan file nyata. Saya kira itu's mungkin karena
.gitattributes` file yang dihapus di filter cabang proses.
Menyadari hal ini, saya menemukan berikut solusi yang bekerja untuk saya:
cp .gitattributes .git/info/attributes
Menyalin .gitattributes
yang git lfs menggunakan untuk melacak file-file besar ke .git/
direktori untuk menghindari dihapus.
Ketika filter-cabang dilakukan don't lupa untuk menempatkan kembali .gitattributes
jika anda masih ingin menggunakan git lfs untuk repositori baru:
mv .git/info/attributes .gitattributes
git add .gitattributes
git commit -m 'added back .gitattributes'