Git pembaruan submodule

242

Saya tidak jelas tentang apa artinya berikut ini (dari dokumentasi pembaruan submodule Git ):

... akan membuat submodules HEAD terlepas, kecuali --rebaseatau --mergeditentukan ...

Bagaimana --rebase/ --mergeperubahan hal?

Kasus penggunaan utama saya adalah memiliki banyak repositori sentral, yang akan saya embed melalui submodul ke dalam repositori lain. Saya ingin dapat memperbaiki repositori sentral ini, baik secara langsung di lokasi asli mereka, atau dari dalam repositori embedding mereka (yang menggunakannya melalui submodule).

  • Dari dalam submodul ini, dapatkah saya membuat cabang / modifikasi dan menggunakan push / pull seperti yang saya lakukan di repositori biasa, atau adakah hal-hal yang perlu diwaspadai?
  • Bagaimana saya memajukan submodule yang direferensikan komit dari say (tagged) 1.0 ke 1.1 (meskipun kepala repositori asli sudah di 2.0), atau memilih komit cabang yang digunakan sama sekali?
biru tua
sumber
Pada topik "kepala terpisah", lihat juga stackoverflow.com/questions/964876/head-and-orighead-in-git dan stackoverflow.com/questions/237408/… untuk contoh praktis (tidak terkait dengan submodule, tetapi masih )
VonC
"Anda tidak dapat mengubah konten submodule dari dalam proyek utama": ya, benar. Dan saya telah mengedit jawaban saya untuk menjelaskan kontradiksi yang tampak (submodule yang tidak dapat dimodifikasi, bahwa Anda masih dapat memodifikasi dari repo proyek utama!)
VonC

Jawaban:

304

Halaman GitPro ini memang merangkum konsekuensi dari pembaruan submodule git dengan baik

Ketika Anda menjalankan git submodule update, itu memeriksa versi spesifik proyek, tetapi tidak dalam cabang. Ini disebut memiliki kepala terpisah - itu berarti file KEPALA menunjuk langsung ke komit, bukan ke referensi simbolis.
Masalahnya adalah bahwa Anda umumnya tidak ingin bekerja di lingkungan kepala yang terpisah, karena mudah kehilangan perubahan .
Jika Anda melakukan pembaruan submodule awal, komit di direktori submodule itu tanpa membuat cabang untuk dikerjakan, dan kemudian jalankan lagi pembaruan submodule git dari proyek super tanpa melakukan sementara, Git akan menimpa perubahan Anda tanpa memberi tahu Anda. Secara teknis Anda tidak akan kehilangan pekerjaan, tetapi Anda tidak akan memiliki cabang yang menunjuk ke sana, sehingga agak sulit untuk mengambilnya.


Catatan Maret 2013:

Seperti disebutkan dalam " git submodule tracking terkini ", submodule sekarang (git1.8.2) dapat melacak cabang.

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 
# or (with rebase)
git submodule update --rebase --remote

Lihat " git submodule update --remotevsgit pull ".

MindTooth 's jawaban menggambarkan pembaruan manual (tanpa konfigurasi lokal):

git submodule -q foreach git pull -q origin master

Dalam kedua kasus, itu akan mengubah referensi submodul ( gitlink , entri khusus dalam indeks repo induk ), dan Anda perlu menambahkan, komit, dan mendorong referensi yang disebutkan dari repo utama.
Lain kali Anda akan mengkloning repo induk, itu akan mengisi submodules untuk mencerminkan referensi SHA1 baru.

Sisa dari jawaban ini merinci fitur submodule klasik (referensi ke komit tetap , yang merupakan titik di belakang gagasan submodule).


Untuk menghindari masalah ini, buat cabang saat Anda bekerja di direktori submodule dengan git checkout -b work atau sesuatu yang setara. Ketika Anda melakukan pembaruan submodule untuk kedua kalinya, itu masih akan mengembalikan pekerjaan Anda, tetapi setidaknya Anda memiliki pointer untuk kembali ke.

Berpindah cabang dengan submodula di dalamnya juga bisa rumit. Jika Anda membuat cabang baru, tambahkan submodule di sana, dan kemudian beralih kembali ke cabang tanpa submodule itu, Anda masih memiliki direktori submodule sebagai direktori yang tidak dilacak:


Jadi, untuk menjawab pertanyaan Anda:

dapatkah saya membuat cabang / modifikasi dan menggunakan push / pull seperti yang saya lakukan pada repo biasa, atau adakah hal-hal yang perlu diwaspadai?

Anda dapat membuat cabang dan mendorong modifikasi.

PERINGATAN (dari Git Submodule Tutorial ): Selalu terbitkan (dorong) perubahan submodule sebelum menerbitkan (dorong) perubahan ke proyek super yang merujuknya. Jika Anda lupa mempublikasikan perubahan submodule, orang lain tidak akan dapat mengkloning repositori.

bagaimana saya memajukan submodule yang direferensikan dari say (tagged) 1.0 ke 1.1 (meskipun kepala repo asli sudah di 2.0)

Halaman " Memahami Submodules " dapat membantu

Git submodules diimplementasikan menggunakan dua bagian yang bergerak:

  • yang .gitmodulesberkas dan
  • jenis khusus objek pohon.

Ini bersama-sama melakukan triangulasi revisi tertentu dari repositori tertentu yang diperiksa ke lokasi tertentu di proyek Anda.


Dari halaman git submodule

Anda tidak dapat mengubah konten submodule dari dalam proyek utama

100% benar: Anda tidak dapat mengubah submodule, hanya merujuk ke salah satu dari komitmennya.

Inilah sebabnya, ketika Anda memodifikasi submodule dari dalam proyek utama, Anda:

  • perlu berkomitmen dan mendorong dalam submodule (ke modul hulu), dan
  • kemudian naik di proyek utama Anda, dan komit ulang (agar proyek utama itu merujuk ke submodule komit baru yang baru saja Anda buat dan dorong)

Sebuah submodule memungkinkan Anda untuk memiliki pengembangan pendekatan berbasis komponen , di mana proyek utama hanya merujuk pada komitmen spesifik dari komponen lain (di sini "repositori Git lain yang dinyatakan sebagai sub-modul").

Sebuah submodule adalah penanda (komit) ke repositori Git lain yang tidak terikat oleh siklus pengembangan proyek utama: ia (yang lain "repositori Git) dapat berkembang secara independen.
Terserah proyek utama untuk memilih dari repo lain apa pun yang diperlukan komit.

Namun, jika Anda ingin, dari kenyamanan , memodifikasi salah satu dari submodula tersebut langsung dari proyek utama Anda, Git memungkinkan Anda untuk melakukan itu, asalkan Anda pertama kali mempublikasikan modifikasi submodule tersebut ke repo Git aslinya, dan kemudian melakukan proyek utama Anda dengan merujuk pada a baru versi submodule kata.

Tetapi ide utamanya tetap: merujuk komponen-komponen spesifik yang:

  • memiliki siklus hidup mereka sendiri
  • memiliki set tag sendiri
  • memiliki pengembangan sendiri

Daftar komit spesifik yang Anda rujuk dalam proyek utama Anda menentukan konfigurasi Anda (ini adalah tentang Manajemen Konfigurasi , melibatkan Sistem Kontrol Versi belaka )

Jika komponen benar-benar dapat dikembangkan pada saat yang sama dengan proyek utama Anda (karena setiap modifikasi pada proyek utama akan melibatkan memodifikasi sub-direktori, dan sebaliknya), maka itu akan menjadi "submodule" tidak lebih, tetapi sebuah subtree merge (juga disajikan dalam pertanyaan Mentransfer basis kode lama dari cvs ke repositori terdistribusi ), yang menghubungkan sejarah kedua repo Git secara bersamaan.

Apakah itu membantu memahami sifat sebenarnya dari Submodules Git?

VONC
sumber
77
Wow. Penjelasan yang panjang itu untuk sesuatu yang pada prinsipnya sesederhana itu seharusnya cukup untuk menakuti setiap pendatang baru agar tetap bertahan dengan svn mereka: eksternal. ;-)
conny
2
@conny: tapi, seperti yang saya rinci dalam " ? Mengapa git submodul tidak sesuai dengan svn eksternal ", submodul yang mendasar berbeda dan tidak kompatibel dengan svn:externals.
VonC
1
Maaf, untuk menjawab pertanyaan saya sendiri, saya mengumpulkan cd'ing ke dalam submodule dan git checkout sha, atau git pull / fetch akan baik-baik saja. Kemudian lakukan pembaruan di repositori lokal.
Henrik
2
@hced: Anda juga dapat menekan semua submodules sekaligus menggunakangit submodule foreach
Dav Clark
1
.. masih belum mengerti. apakah ada penjelasan yang lebih mudah di web di suatu tempat?
eugene
135

Untuk memperbarui setiap submodule, Anda bisa menjalankan perintah berikut (di root repositori):

git submodule -q foreach git pull -q origin master

Anda dapat menghapus opsi -q untuk mengikuti seluruh proses.

MindTooth
sumber
15
Jika Anda hanya menjalankan git submodule update --init --recursivedari root, itu akan mendapatkan semuanya secara rekursif dan menginisialisasi mereka jika belum.
Sam Soffes
10
@SamSoffes Itu melayani tujuan yang sama sekali berbeda. Memperbarui submodula akan memeriksa submodul di komit yang saat ini mereka tunjuk (belum tentu komit terbaru). Solusi dalam jawaban di atas memperbarui komit setiap submodule ke HEAD terbaru dari asal / master.
Indragie
7
Metode baru saya:git submodule update --rebase --remote
MindTooth
19

Untuk mengatasi opsi --rebasevs --merge.:

Katakanlah Anda memiliki super repositori A dan submodule B dan ingin melakukan beberapa pekerjaan dalam submodule B. Anda telah melakukan pekerjaan rumah Anda dan tahu bahwa setelah menelepon

git submodule update

Anda berada dalam kondisi tanpa HEAD, sehingga setiap komitmen yang Anda lakukan pada saat ini sulit untuk kembali. Jadi, Anda sudah mulai bekerja pada cabang baru di submodule B

cd B
git checkout -b bestIdeaForBEver
<do work>

Sementara itu, orang lain dalam proyek A telah memutuskan bahwa versi B terbaru dan terhebat benar-benar layak untuk A. Anda, karena kebiasaan, menggabungkan perubahan terbaru ke bawah dan memperbarui submodul Anda.

<in A>
git merge develop
git submodule update

Oh tidak! Anda kembali dalam keadaan tanpa kepala lagi, mungkin karena B sekarang menunjuk ke SHA yang terkait dengan tip baru B, atau komit lainnya. Andai saja Anda memiliki:

git merge develop
git submodule update --rebase

Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'

Sekarang ide terbaik untuk B telah diubah menjadi komit baru, dan yang lebih penting, Anda masih berada di cabang pengembangan Anda untuk B, bukan dalam keadaan tanpa kepala!

( --mergeAkan menggabungkan perubahan dari sebelumUpdateSHA ke afterUpdateSHA ke cabang kerja Anda, sebagai lawan rebasing perubahan Anda ke afterUpdateSHA.)

robinspb
sumber
7

Git 1.8.2 menampilkan opsi baru --remote,, yang akan mengaktifkan perilaku ini dengan tepat. Lari

git submodule update --rebase --remote

akan mengambil perubahan terbaru dari hulu di setiap submodule, rebase mereka, dan periksa revisi terbaru submodule. Seperti yang dijelaskan dalam dokumentasi :

--terpencil

Opsi ini hanya valid untuk perintah pembaruan. Alih-alih menggunakan SHA-1 rekaman superproyek untuk memperbarui submodule, gunakan status cabang pelacak jarak jauh submodule.

Ini sama dengan menjalankan git pulldi setiap submodule, yang umumnya persis seperti yang Anda inginkan.

(Ini disalin dari jawaban ini .)

Iulian Onofrei
sumber
Jika Anda memutuskan untuk menjawab pertanyaan yang lebih lama yang sudah mapan dan jawaban yang benar, menambahkan jawaban baru di akhir hari mungkin tidak memberi Anda kredit apa pun. Jika Anda memiliki beberapa informasi baru yang khas, atau Anda yakin jawaban lainnya semuanya salah, tentu saja tambahkan jawaban baru, tetapi 'jawaban lain' memberikan informasi dasar yang sama lama setelah pertanyaan diajukan biasanya dimenangkan ' tidak memberi Anda banyak kredit. Tidak ada penjelasan tentang apa ini - bahkan tidak ada tautan ke dokumentasi eksternal (yang tidak akan cukup).
Jonathan Leffler
2
Ini bukan "jawaban lain", karena TIDAK ada jawaban lain yang memiliki perintah ini (buktikan saya salah). Jawaban lain tidak berfungsi untuk saya, komentar ini berhasil, jadi saya memutuskan untuk mempostingnya sebagai jawaban sambil memberikan kredit kepada pemilik aslinya. Jadi pertimbangkan untuk menghapus downvote Anda.
Iulian Onofrei
Ada komentar dari MindTooth dari 2015 mengatakan ini adalah apa yang mereka lakukan sekarang. Anda tidak memberikan penjelasan tentang apa yang dilakukannya (meskipun Anda menyebutkan MindTooth, tetapi tidak ada penjelasan nyata tentang apa yang Anda maksudkan dengan hal itu - memasukkan URL, seperti dalam komentar ini, akan membantu). Anda tidak mengatakan mengapa itu ide yang bagus. Anda tidak memberikan peringatan. Menurut saya, ini bukan jawaban yang bermanfaat karena menimbulkan lebih banyak pertanyaan daripada yang dipecahkan.
Jonathan Leffler
1
Maksud saya, itu berfungsi bukannya tidak bekerja. Percayalah, jika lebih banyak orang melihat jawaban ini, mereka akan senang, karena berhasil . Untuk hal-hal seperti ini, kebanyakan orang hanya ingin mengetahui perintah yang memperbarui submitule git, bukan bagaimana implementasinya.
Iulian Onofrei
Saya mengedit jawaban untuk membuktikan Anda salah, juga, stackoverflow.com/questions/1979167/git-submodule-update/… !!!
Iulian Onofrei