Buat repositori submodul dari folder dan simpan riwayat git commitnya


111

Saya memiliki aplikasi web yang mengeksplorasi aplikasi web lain dengan cara tertentu. Ini berisi beberapa demo web dalam demosfolder dan salah satu demo sekarang harus memiliki repositori sendiri. Saya ingin membuat repositori terpisah untuk aplikasi demo ini dan menjadikannya sebagaisubpaket submodule dari repositori utama tanpa kehilangan riwayat komitnya.

Apakah mungkin untuk menyimpan riwayat komit dari file dalam folder repositori dan membuat repositori darinya dan menggunakannya sebagai submodul ?


Saya telah mencari cara untuk memindahkan direktori 1 dari repositori Git A ke repositori Git B. +1 untuk tautan ke artikel tersebut.
Chetabahana


Ya, ini memang sangat mirip, solusinya sedikit berbeda, terima kasih telah membagikan ini
GabLeRoux

Jawaban:


191

Solusi Terperinci

Lihat catatan di akhir jawaban ini (paragraf terakhir) untuk alternatif cepat untuk git submodul menggunakan npm;)

Dalam jawaban berikut, Anda akan mengetahui cara mengekstrak folder dari repositori dan membuat repositori git darinya dan kemudian memasukkannya sebagai submodul, bukan folder.

Terinspirasi dari artikel Gerg Bayer Memindahkan File dari satu Repositori Git ke Repositori Git Lainnya, Melestarikan Sejarah

Pada awalnya, 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

Pada langkah-langkah di bawah ini, saya akan menyebutnya someLibsebagai <directory 1>.

Pada akhirnya, kita akan mendapatkan sesuatu seperti ini:

<git repository A>
    someFolders
    someFiles
    @submodule --> <git repository B>

<git repository B>
    someFolders
    someFiles

Buat repositori git baru dari folder di repositori lain

Langkah 1

Dapatkan salinan baru dari repositori untuk dipisahkan.

git clone <git repository A url>
cd <git repository A directory>

Langkah 2

Folder saat ini akan menjadi repositori baru jadi hapus remote saat ini.

git remote rm origin

LANGKAH 3

Ekstrak riwayat folder yang diinginkan dan komit

git filter-branch --subdirectory-filter <directory 1> -- --all

Anda sekarang harus memiliki repositori git dengan file-file dari directory 1root repo Anda dengan semua riwayat komit terkait.

LANGKAH 4

Buat repositori online Anda dan dorong repositori baru Anda!

git remote add origin <git repository B url>
git push

Anda mungkin perlu mengatur upstreamcabang untuk dorongan pertama Anda

git push --set-upstream origin master

Bersih <git repository A>(opsional, lihat komentar)

Kami ingin menghapus jejak (file dan riwayat komit) <git repository B>dari <git repository A>jadi riwayat untuk folder ini hanya ada sekali.

Ini didasarkan pada Menghapus data sensitif dari github.

Buka 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 <directory 1>dengan folder yang ingin Anda hapus. -rakan melakukannya secara rekursif di dalam direktori yang ditentukan :). Sekarang dorong ke origin/masterdengan--force

git push origin master --force

Tahap Bos (Lihat Catatan di bawah)

Buat submodul dari <git repository B>dalam<git repository A>

git submodule add <git repository B url>
git submodule update
git commit

Verifikasi apakah semuanya bekerja seperti yang diharapkan dan push

git push origin master

Catatan

Setelah melakukan semua ini, saya menyadari dalam kasus saya bahwa lebih tepat menggunakan npm untuk mengelola dependensi saya sendiri. Kita dapat menentukan url dan versi git, lihat url git package.json sebagai dependensi .

Jika Anda melakukannya dengan cara ini, repositori yang ingin Anda gunakan sebagai syarat harus menjadi modul NPM sehingga harus berisi package.jsonfile atau Anda akan mendapatkan error ini: Error: ENOENT, open 'tmp.tgz-unpack/package.json'.

tldr (solusi alternatif)

Anda mungkin merasa lebih mudah menggunakan npm dan mengelola dependensi dengan url git :

  • Pindahkan folder ke repositori baru
  • dijalankan npm initdi dalam kedua repositori
  • jalankan di npm install --save git://github.com/user/project.git#commit-ishmana Anda ingin dependensi Anda diinstal

39
Langkah "Bersihkan <git repository A>" harus dihindari. Dengan melakukan ini, Anda tidak dapat sepenuhnya memulihkan / membayar versi lama / melakukan dari riwayat Anda. Anda hanya perlu git rm folder dan menambahkan submodul. Jadi, Anda memastikan untuk memiliki salinan yang berfungsi penuh saat memeriksa komit yang lebih lama.
Cybot

Tidakkah sebaiknya Anda lakukan cd someLibsebelum Langkah 2? Anda mengatakan "Folder saat ini akan menjadi repositori baru" tetapi sebenarnya tidak; repositori baru (submodule) ada di dalam folder itu.
Jago

1
mengonfirmasi: ya, ini berfungsi untuk lebih dari satu submodul. Terima kasih banyak atas jawaban mendetailnya. Juga, tidak harus menggunakan npm.
Breno Inojosa

2
Saya akan menambahkan informasi tentang refs/original/...yang dibuat pada langkah 3.
Emile Bergeron

6
GitHub membuat artikel tentang cara mencapai ekstraksi folder ke dalam repositori baru: help.github.com/articles/…
jrobichaud

9

Solusi oleh @GabLeRoux menghancurkan cabang, dan komit terkait.

Cara sederhana untuk mengkloning dan menyimpan semua cabang dan komitmen ekstra itu:

1 - Pastikan Anda memiliki alias git ini

git config --global alias.clone-branches '! git branch -a | sed -n "/\/HEAD /d; /\/master$/d; /remotes/p;" | xargs -L1 git checkout -t'

2 - Kloning remote, tarik semua cabang, ubah remote, filter direktori Anda, dorong

git clone git@github.com:user/existing-repo.git new-repo
cd new-repo
git clone-branches
git remote rm origin
git remote add origin git@github.com:user/new-repo.git
git remote -v
git filter-branch --subdirectory-filter my_directory/ -- --all
git push --all
git push --tags

3

Solusi GabLeRoux bekerja dengan baik kecuali jika Anda menggunakan git lfsdan memiliki file besar di bawah direktori yang ingin Anda lepaskan. Dalam hal ini, setelah langkah 3 semua file besar akan tetap menjadi file penunjuk, bukan file asli. Saya kira itu mungkin karena .gitattributesfile tersebut dihapus dalam proses cabang filter.

Menyadari hal ini, saya menemukan solusi berikut berfungsi untuk saya:

cp .gitattributes .git/info/attributes

Menyalin .gitattributesgit lfs mana yang digunakan untuk melacak file besar ke .git/direktori agar tidak terhapus.

Ketika filter-branch selesai, jangan lupa untuk mengembalikan .gitattributesjika Anda masih ingin menggunakan git lfs untuk repositori baru:

mv .git/info/attributes .gitattributes
git add .gitattributes
git commit -m 'added back .gitattributes'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.