Saya punya proyek dengan submission Git. Itu dari ssh: // ... URL, dan sedang dalam komit A. Komit B telah didorong ke URL itu, dan saya ingin submodule untuk mengambil komit, dan mengubahnya.
Sekarang, pemahaman saya adalah yang git submodule update
seharusnya melakukan ini, tetapi tidak. Itu tidak melakukan apa-apa (tidak ada output, kode keluar sukses). Ini sebuah contoh:
$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...
Saya juga sudah mencoba git fetch mod
, yang tampaknya melakukan pengambilan (tetapi tidak mungkin, karena itu tidak meminta kata sandi!), Tetapi git log
dan git show
menolak keberadaan komitmen baru. Sejauh ini saya baru saja rm
membuka modul dan menambahkannya kembali, tetapi pada prinsipnya keduanya salah dan membosankan dalam praktiknya.
git
git-submodules
git-pull
Thanatos
sumber
sumber
--remote
opsi, mungkin akan berguna untuk menandai bahwa sebagai jawaban yang diterima daripada pendekatan "dengan tangan" dalam jawaban Jason?--remote
merupakan solusi yang lebih baik pada titik waktu ini, dan karena pertanyaan ini telah dikaitkan dengan dari Github Gist tentang submodul, saya merasa akan lebih baik bagi pembaca yang datang untuk melihat jawaban baru.hunter2
kata sandi: o)Jawaban:
The
git submodule update
perintah sebenarnya memberitahu Git bahwa Anda ingin submodul Anda untuk setiap memeriksa komit sudah ditentukan dalam indeks superproject tersebut. Jika Anda ingin memperbarui submodules Anda ke komit terbaru yang tersedia dari jarak jauh mereka, Anda harus melakukan ini secara langsung di submodules.Jadi dalam ringkasan:
Atau, jika Anda orang yang sibuk:
sumber
git submodule foreach git pull
git submodule foreach git pull origin master
.git submodule foreach --recursive git pull origin master
.-a
Sakelar untukgit commit
"Beri tahu [s] perintah untuk secara otomatis mengatur file yang telah dimodifikasi dan dihapus, tetapi file baru yang belum Anda beri tahu tentang Git tidak terpengaruh."Git 1.8.2 menampilkan opsi baru
--remote
,, yang akan mengaktifkan perilaku ini dengan tepat. Lariakan mengambil perubahan terbaru dari hulu di setiap submodule, menggabungkannya, dan memeriksa revisi terbaru dari submodule. Seperti yang dijelaskan dalam dokumentasi :
Ini sama dengan menjalankan
git pull
di setiap submodule, yang umumnya persis seperti yang Anda inginkan.sumber
git pull
di setiap submodule" Untuk memperjelas, tidak ada perbedaan (dari perspektif pengguna) antara jawaban Anda dangit submodule foreach git pull
?foreach git pull
hanya memeriksanya, tetapi tidak memperbarui pointer repo utama untuk menunjuk ke komit yang lebih baru dari submodule. Hanya dengan--remote
itu membuatnya menunjukkan komit terbaru.Di direktori induk proyek Anda, jalankan:
Atau jika Anda menjalankan submodul rekursif:
Kadang-kadang ini masih tidak berhasil, karena entah bagaimana Anda memiliki perubahan lokal di direktori submodule lokal saat submodule sedang diperbarui.
Sebagian besar waktu perubahan lokal mungkin bukan yang ingin Anda komit. Ini bisa terjadi karena penghapusan file di submodule Anda, dll. Jika demikian, lakukan reset di direktori submodule lokal Anda dan di direktori induk proyek Anda, jalankan lagi:
sumber
Proyek utama Anda menunjuk ke komit tertentu yang harus diserahkan pada submodule.
git submodule update
mencoba memeriksa komit di setiap submodule yang telah diinisialisasi. Submodule benar-benar repositori independen - hanya membuat komit baru di submodule dan mendorong itu tidak cukup. Anda juga perlu secara eksplisit menambahkan versi baru dari submodule di proyek utama.Jadi, dalam kasus Anda, Anda harus menemukan komit yang tepat dalam submodule - anggaplah itulah ujung dari
master
:Sekarang kembali ke proyek utama, tahapan submodule dan komit bahwa:
Sekarang dorong versi baru proyek utama Anda:
Mulai saat ini, jika ada orang lain memperbarui proyek utama mereka, maka
git submodule update
bagi mereka akan memperbarui submodule, dengan asumsi itu sudah diinisialisasi.sumber
Sepertinya dua skenario berbeda digabungkan dalam diskusi ini:
skenario 1
Menggunakan pointer repositori orang tua saya untuk submodul, saya ingin memeriksa komit di setiap submodul yang ditunjuk repositori induk, mungkin setelah terlebih dahulu mengulangi semua submodul dan memperbarui / menariknya dari jarak jauh.
Ini, sebagaimana ditunjukkan, dilakukan dengan
Skenario 2, yang saya pikir adalah tujuan OP
Hal-hal baru telah terjadi dalam satu atau lebih submodul, dan saya ingin 1) menarik perubahan ini dan 2) memperbarui repositori induk untuk menunjuk ke komit HEAD (terbaru) dari submodul ini / ini.
Ini akan dilakukan oleh
Tidak terlalu praktis, karena Anda harus meng-hardcode n paths ke semua n submodules dalam skrip misalnya untuk memperbarui pointer komit repositori induk.
Akan lebih baik untuk memiliki iterasi otomatis melalui setiap submodule, memperbarui pointer repositori induk (menggunakan
git add
) untuk menunjuk ke kepala submodule (s).Untuk ini, saya membuat skrip Bash kecil ini:
git-update-submodules.sh
Untuk menjalankannya, jalankan
Elaborasi
Pertama-tama, saya berasumsi bahwa cabang dengan nama $ CABANG (argumen kedua) ada di semua repositori. Jangan ragu untuk membuat ini lebih kompleks.
Beberapa bagian pertama adalah beberapa memeriksa bahwa argumen ada di sana. Kemudian saya menarik hal-hal terbaru repositori induk (saya lebih suka menggunakan - f (fast-forwarding) setiap kali saya hanya melakukan menarik. Saya telah rebase off, BTW).
Maka beberapa submodule yang diinisialisasi, mungkin diperlukan, jika submodul baru telah ditambahkan atau belum diinisialisasi:
Lalu saya memperbarui / menarik semua submodul:
Perhatikan beberapa hal: Pertama-tama, saya menggunakan beberapa perintah Git
&&
- artinya perintah sebelumnya harus dijalankan tanpa kesalahan.Setelah kemungkinan tarikan yang berhasil (jika hal-hal baru ditemukan pada remote), saya melakukan push untuk memastikan bahwa kemungkinan gabungan-komit tidak tertinggal pada klien. Sekali lagi, itu hanya terjadi jika tarikan benar-benar membawa barang baru.
Akhirnya, final
|| true
memastikan bahwa skrip berlanjut pada kesalahan. Untuk membuat ini bekerja, semua yang ada di iterasi harus dibungkus dengan tanda kutip ganda dan perintah Git dibungkus dengan tanda kurung (prioritas operator).Bagian favorit saya:
Iterate semua submodules - with
--quiet
, yang menghilangkan output 'Entering MODULE_PATH'. Menggunakan'echo $path'
(harus dalam tanda kutip tunggal), path ke submodule ditulis ke output.Daftar jalur submodule relatif ini ditangkap dalam array (
$(...)
) - akhirnya iterate ini dan lakukangit add $i
untuk memperbarui repositori induk.Akhirnya, komit dengan beberapa pesan yang menjelaskan bahwa repositori induk telah diperbarui. Komit ini akan diabaikan secara default, jika tidak ada yang dilakukan. Dorong ini ke asal, dan Anda selesai.
Saya memiliki skrip menjalankan ini dalam pekerjaan Jenkins yang berantai ke penyebaran otomatis terjadwal setelah itu, dan itu berfungsi seperti pesona.
Saya harap ini akan membantu seseorang.
sumber
pwd
perintah mencetak tepat 'absolut path' untuk setiap hadir submodule;--recursive
memastikan kami mengunjungi semua submodul, termasuk submodul-dalam-submodul -... yang mungkin ada dalam proyek besar. Kedua metode menyebabkan masalah dengan direktori yang mencakup spasi, misalnya/c/Users/Ger/Project\ Files/...
kebijakan untuk tidak pernah menggunakan spasi putih di mana pun dalam proyek kami.--remote
opsi.git submodule update --remote
berperilaku kira-kira seperti yang dilakukan skrip Anda.The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
Saya tidak ingin mengedit .gitmodules atau .git / config setiap kali saya ingin melakukan ini ke cabang lain selain master. Tapi mungkin saya melewatkan sesuatu? Selain itu, metode ini tampaknya menerapkan penggabungan rekursif (sehingga tidak ada kemungkinan maju cepat).Polos dan sederhana, untuk mengambil submodul:
Dan sekarang lanjutkan memperbarui mereka ke cabang utama terbaru (misalnya):
sumber
Catatan, sementara bentuk modern dari memperbarui submodule akan:
Bentuk yang lebih tua adalah:
Kecuali ... bentuk kedua ini tidak benar-benar "tenang".
Lihat commit a282f5a (12 Apr 2019) oleh Nguyễn Thái Ngọc Duy (
pclouds
) .(Digabung oleh Junio C Hamano -
gitster
- di commit f1c9f6c , 25 Apr 2019)Dan Git 2.23 (Q3 2019) memperbaiki masalah lain: "
git submodule foreach
" tidak melindungi opsi baris perintah yang diteruskan ke perintah untuk dijalankan di setiap submodule dengan benar, ketika opsi "--recursive
" sedang digunakan.Lihat komit 30db18b (24 Jun 2019) oleh Morian Sonnet (
momoson
) .(Digabung oleh Junio C Hamano -
gitster
- di commit 968eecb , 09 Jul 2019)sumber
Ini akan menarik semua komitmen terbaru.
sumber
Dalam kasus saya, saya ingin
git
memperbarui ke yang terbaru dan pada saat yang sama mengisi kembali file yang hilang.Berikut ini memulihkan file yang hilang (terima kasih
--force
yang sepertinya tidak disebutkan di sini), tetapi tidak menarik komitmen baru:git submodule update --init --recursive --force
Ini berhasil:
git submodule update --recursive --remote --merge --force
sumber
@Jason benar dengan cara tetapi tidak sepenuhnya.
Jadi,
git submodule update
apakah checkout, tetapi itu adalah untuk komit dalam indeks repositori yang mengandung. Ia belum tahu tentang komitmen baru di hulu sama sekali. Jadi pergi ke submodule Anda, dapatkan komit yang Anda inginkan dan komit keadaan submodule yang diperbarui di repositori utama dan kemudian lakukangit submodule update
.sumber
git submodule update
, pembaruan akan memindahkan submodule ke komit yang ditentukan dalam KEPALA superproyek saat ini. (Apa pun komit terbaru dalam proyek super mengatakan proyek harus di - perilaku ini, setelah penjelasan di posting Jason, tampaknya logis bagi saya) Itu juga tampaknya mengambil, tetapi hanya dalam kasus bahwa proyek berada pada komit yang salah , yang menambah kebingungan saya.Berikut ini adalah one-liner yang luar biasa untuk memperbarui semuanya ke master terbaru:
Terima kasih kepada Mark Jaquith
sumber
Jika Anda tidak tahu cabang host, buat ini:
Ini akan mendapatkan cabang dari repositori Git utama dan kemudian untuk setiap submodule akan menarik cabang yang sama.
sumber
Jika Anda ingin checkout
master
cabang untuk setiap submodule - Anda dapat menggunakan perintah berikut untuk tujuan itu:sumber