Bagaimana cara membuat submodul git dangkal?


145

Apakah mungkin memiliki submodul yang dangkal? Saya memiliki superproject dengan beberapa submodul, masing-masing dengan sejarah yang panjang, jadi tidak perlu terlalu besar menyeret semua sejarah itu.

Yang saya temukan hanyalah utas yang belum terjawab ini .

Haruskah saya meretas git-submodule untuk menerapkan ini?


1
" git submodule add/update" sekarang dapat mengkloning repositori submodul secara dangkal! Lihat jawaban saya di bawah
VonC

Jawaban:


137

Baru di git1.8.4 mendatang (Juli 2013) :

" git submodule update" secara opsional dapat mengkloning repositori submodul secara dangkal.

(Dan git 2.10 Q3 2016 memungkinkan untuk merekamnya dengan git config -f .gitmodules submodule.<name>.shallow true.
Lihat akhir dari jawaban ini)

Lihat commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f :

Tambahkan --depthopsi ke perintah tambah dan perbarui "git submodule", yang kemudian diteruskan ke perintah klon. Ini berguna ketika submodul berukuran besar dan Anda tidak terlalu tertarik pada apa pun kecuali commit terbaru.

Pengujian ditambahkan dan beberapa penyesuaian indensi dilakukan untuk menyesuaikan dengan sisa testfile pada "pembaruan submodule dapat menangani tautan simbolik dalam pwd".

Ditandatangani oleh: Fredrik Gustafsson <iveqy@iveqy.com>
Diakui oleh: Jens Lehmann<Jens.Lehmann@web.de>

Artinya, ini berfungsi:

git submodule add --depth 1 -- repository path
git submodule update --depth -- [<path>...]

Dengan:

--depth::

Opsi ini berlaku untuk perintah adddan update.
Buat klon 'dangkal' dengan riwayat terpotong ke jumlah revisi yang ditentukan.


atwyman menambahkan di komentar :

Sejauh yang saya tahu opsi ini tidak dapat digunakan untuk submodul yang tidak melacak dengan mastersangat dekat. Jika Anda menyetel kedalaman 1, maka submodule updatehanya bisa berhasil jika komit submodul yang Anda inginkan adalah master terbaru. Jika tidak, Anda mendapatkan " fatal: reference is not a tree" .

Itu benar.
Artinya, hingga git 2.8 (Maret 2016). Dengan 2.8, submodule update --depthmemiliki satu kesempatan lagi untuk berhasil, bahkan jika SHA1 dapat langsung dijangkau dari salah satu HEAD repo jarak jauh.

Lihat commit fb43e31 (24 Feb 2016) oleh Stefan Beller ( stefanbeller) .
Dibantu oleh: Junio ​​C Hamano ( gitster) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 9671a76 , 26 Feb 2016)

submodule: berusaha lebih keras untuk mengambil sha1 yang dibutuhkan dengan mengambil langsung sha1

Saat meninjau perubahan yang juga memperbarui submodul di Gerrit, praktik tinjauan yang umum adalah mengunduh dan memilih patch secara lokal untuk mengujinya.
Namun saat mengujinya secara lokal, ' git submodule update' mungkin gagal mengambil submodul yang benar sha1 karena komit yang sesuai di submodul belum menjadi bagian dari riwayat proyek, tetapi juga hanya perubahan yang diusulkan.

Jika $sha1bukan bagian dari pengambilan default, kami mencoba mengambil $sha1secara langsung . Namun beberapa server tidak mendukung pengambilan langsung oleh sha1, yang menyebabkan git-fetchkegagalan dengan cepat.
Kita bisa gagal sendiri di sini karena sha1 yang masih hilang akan menyebabkan kegagalan nanti di tahap checkout, jadi gagal di sini sebaik yang kita bisa dapatkan.


MVG menunjukkan di komentar untuk melakukan fb43e31 (git 2.9, Feb 2016)

Tampaknya bagi saya bahwa komit fb43e31 meminta komit yang hilang oleh id SHA1, jadi pengaturan uploadpack.allowReachableSHA1InWantdan uploadpack.allowTipSHA1InWantpada server mungkin akan memengaruhi apakah ini berfungsi.
Saya menulis posting ke daftar git hari ini , menunjukkan bagaimana penggunaan submodul dangkal dapat dibuat agar bekerja lebih baik untuk beberapa skenario, yaitu jika komit juga merupakan tag.
Kita lihat saja.

Saya rasa ini adalah alasan mengapa fb43e31 membuat pengambilan untuk SHA1 tertentu sebagai fallback setelah pengambilan untuk cabang default.
Namun demikian, dalam kasus "--depth 1" saya pikir akan masuk akal untuk membatalkan lebih awal: jika tidak ada referensi yang terdaftar sesuai dengan yang diminta, dan meminta oleh SHA1 tidak didukung oleh server, maka tidak ada gunanya mengambil apa pun, karena kami juga tidak dapat memenuhi persyaratan submodule.


Perbarui Agustus 2016 (3 tahun kemudian)

Dengan Git 2.10 (Q3 2016), Anda dapat melakukannya

 git config -f .gitmodules submodule.<name>.shallow true

Lihat " Submodul Git tanpa bobot ekstra " untuk informasi selengkapnya.


Git 2.13 (Q2 2017) lakukan add in commit 8d3047c (19 Apr 2017) oleh Sebastian Schuberth ( sschuberth) .
(Digabung oleh Sebastian Schuberth - sschuberth- di commit 8d3047c , 20 Apr 2017)

klon dari submodul ini akan dilakukan sebagai klon dangkal (dengan kedalaman riwayat 1)

Namun, Ciro Santilli menambahkan di komentar (dan rincian jawabannya )

shallow = truepada .gitmoduleshanya mempengaruhi referensi dilacak oleh KEPALA remote saat menggunakan --recurse-submodules, bahkan jika target komit ditunjukkan oleh cabang, dan bahkan jika Anda menempatkan branch = mybranchpada .gitmodulesjuga.


Git 2.20 (Q4 2018) meningkatkan dukungan submodule, yang telah diperbarui untuk dibaca dari blob pada HEAD:.gitmodulessaat.gitmodules file hilang dari pohon kerja.

Lihat commit 2b1257e , commit 76e9bdc (25 Okt 2018), dan commit b5c259f , commit 23dd8f5 , commit b2faad4 , commit 2502ffc , commit 996df4d , commit d1b13df , commit 45f5ef3 , commit bcbc780 (05 Oct 2018) oleh Antonio Ospite ( ao2) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit abb4824 , 13 Nov 2018)

submodule: mendukung membaca .gitmodulessaat tidak ada di pohon kerja

Ketika .gitmodulesfile tidak tersedia di pohon kerja, coba gunakan konten dari indeks dan dari cabang saat ini.
Ini mencakup kasus ketika file adalah bagian dari repositori tetapi karena alasan tertentu tidak diperiksa, misalnya karena pembayaran yang jarang.

Ini memungkinkan untuk menggunakan setidaknya perintah ' git submodule' yang membaca filegitmodules file konfigurasi tanpa sepenuhnya mengisi pohon bekerja.

Menulis ke .gitmodulesakan tetap mengharuskan file tersebut diperiksa, jadi periksalah sebelum meneleponconfig_set_in_gitmodules_file_gently .

Tambahkan juga pemeriksaan serupa git-submodule.sh::cmd_add()untuk mengantisipasi kegagalan akhir dari perintah " git submodule add" saat .gitmodulestidak dapat ditulisi dengan aman; ini mencegah perintah meninggalkan repositori dalam keadaan palsu (misalnya, repositori submodul telah digandakan tetapi .gitmodulestidak diperbarui karenaconfig_set_in_gitmodules_file_gently gagal).

Selain itu, karena config_from_gitmodules()sekarang mengakses penyimpanan objek global, semua jalur kode yang memanggil fungsi harus dilindungi dari akses bersamaan ke penyimpanan objek global.
Saat ini ini hanya terjadi di builtin/grep.c::grep_submodules(), jadi panggil grep_read_lock()sebelum memanggil kode yang melibatkanconfig_from_gitmodules() .

CATATAN: ada satu kasus yang jarang terjadi di mana fitur baru ini belum berfungsi dengan baik: submodul bersarang tanpa .gitmodulespohon kerja mereka.


Catatan: Git 2.24 (Q4 2019) memperbaiki kemungkinan segfault saat mengkloning submodul dangkal.

Lihat commit ddb3c85 (30 Sep 2019) oleh Ali Utku Selen ( auselen) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 678a9ca , 09 Okt 2019)


Git 2.25 (Q1 2020), memperjelas git submodule update dokumentasi.

Lihat commit f0e58b3 (24 Nov 2019) oleh Philippe Blain ( phil-blain) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit ef61045 , 05 Des 2019)

doc: sebutkan bahwa 'git submodule update' mengambil komit yang hilang

Dibantu oleh: Junio ​​C Hamano
Dibantu: Johannes Schindelin
Ditandatangani oleh: Philippe Blain

' git submoduleupdate' akan mengambil komit baru dari remote submodule jika SHA-1 yang direkam di superproject tidak ditemukan . Ini tidak disebutkan dalam dokumentasi.


Peringatan: Dengan Git 2.25 (K1 2020), interaksi antara " git clone --recurse-submodules" dan penyimpanan objek alternatif tidak dirancang dengan baik.

Dokumentasi dan kode telah diajarkan untuk membuat rekomendasi yang lebih jelas ketika pengguna melihat kegagalan.

Lihat commit 4f3e57e , commit 10c64a0 (02 Des 2019) oleh Jonathan Tan ( jhowtan) .
(Digabung oleh Junio ​​C Hamano -gitster - di commit 5dd1d59 , 10 Des 2019)

submodule--helper: saran tentang kesalahan alternatif yang fatal

Ditandatangani oleh: Jonathan Tan
Diakui oleh: Jeff King

Saat mengkloning superproject secara rekursif dengan beberapa modul dangkal yang ditentukan di dalamnya .gitmodules, kemudian melakukan kloning ulang dengan " --reference=<path>", kesalahan terjadi. Sebagai contoh:

git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  master
git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  --reference master master2

gagal dengan:

fatal: submodule '<snip>' cannot add alternate: reference repository
'<snip>' is shallow

Ketika alternatif yang dihitung dari alternatif superproject tidak dapat ditambahkan, baik dalam kasus ini atau lainnya, saran tentang mengkonfigurasi " submodule.alternateErrorStrategy" opsi konfigurasi dan menggunakan "--reference-if-able " daripada " --reference" saat kloning.

Itu dirinci dalam:

Dengan Git 2.25 (Q1 2020), interaksi antara "git clone --recurse-submodules" dan penyimpanan objek alternatif tidak dirancang dengan baik.

Doc: jelaskan submodule.alternateErrorStrategy

Ditandatangani oleh: Jonathan Tan
Diakui oleh: Jeff King

Commit 31224cbdc7 (" clone: opsi rekursif dan referensi memicu alternatif submodule", 17-08-2016, Git v2.11.0-rc0 - merge yang terdaftar di batch # 1 ) mengajari Git untuk mendukung opsi konfigurasi " submodule.alternateLocation" dan "submodule.alternateErrorStrategy " pada superproject .

Jika " submodule.alternateLocation" dikonfigurasi ke "superproject " di superproject, setiap kali submodul dari superproject itu dikloning, ia akan menghitung jalur alternatif analog untuk submodul tersebut dari$GIT_DIR/objects/info/alternates superproject, dan mereferensikannya.

Opsi " submodule.alternateErrorStrategy" menentukan apa yang terjadi jika alternatif itu tidak dapat dirujuk.
Namun, tidak jelas bahwa hasil klon seolah-olah tidak ada alternatif yang ditentukan saat opsi tersebut tidak disetel ke "mati" (seperti yang dapat dilihat dalam pengujian di 31224cbdc7 ).
Oleh karena itu, dokumentasikan dengan benar.

The dokumentasi config submodule sekarang termasuk:

submodule.alternateErrorStrategy::

Menentukan cara menangani kesalahan dengan alternatif untuk submodule seperti yang dihitung melalui submodule.alternateLocation.
Nilai yang mungkin adalah ignore, info, die.
Default-nya adalah die.
Perhatikan bahwa jika disetel ke ignoreatau info, dan jika ada kesalahan dengan alternatif yang dihitung, proses penggandaan seolah-olah tidak ada alternatif yang ditentukan .


2
Wow, cepat sekali! Terima kasih untuk jawabannya. Oh dan --depthharuskah bertengkar juga;)
Brice

3
Tampaknya bagi saya bahwa komit fb43e31 meminta komit yang hilang oleh id SHA1, jadi pengaturan uploadpack.allowReachableSHA1InWantdan uploadpack.allowTipSHA1InWantpada server mungkin akan memengaruhi apakah ini berfungsi. Saya menulis posting ke daftar git hari ini, menunjukkan bagaimana penggunaan submodul dangkal dapat dibuat agar bekerja lebih baik untuk beberapa skenario, yaitu jika komit juga merupakan tag. Kita lihat saja.
MvG

2
Dengan penambahan opsi dangkal baru-baru ini .gitmodules, apakah --depth 1opsi tersebut berfungsi untuk cabang yang tidak melacak master dengan cermat?
CMCDragonkai

2
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Terima kasih atas ketepatan dan tesnya. Saya telah memasukkan komentar Anda dalam jawaban untuk visibilitas lebih lanjut, dan telah memberi suara positif pada jawaban Anda.
VonC

3
Tidak jelas dari jawabannya apa cara saat ini untuk melakukannya. Selain itu, tidak jelas apakah semua itu diperlukan setiap kali seseorang mengkloning salinan baru atau setelan submodul yang jarang ini menjadi bagian dari repo yang mereferensikan submodul ini (mis. Setiap klon baru dan pembaruan submodul menghasilkan pembayaran submodul yang jarang)
Pavel P

28

Git 2.9.0 mendukung submodul shallow clone secara langsung, jadi sekarang Anda dapat memanggil:

git clone url://to/source/repository --recursive --shallow-submodules

2
Opsi ini paling menjanjikan, tetapi gagal pada git 2.14.1 komit submodul tidak dilacak baik oleh cabang atau tag: stackoverflow.com/a/47374702/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 刘晓波 死 六四 事件 法轮功 Pastikan server git Anda juga diperbarui
KindDragon

Terima kasih, saya telah menguji secara lokal, tanpa server, dan di GitHub, yang tidak dapat saya perbarui :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
Saya memiliki masalah yang sama menggunakan git 2.20, itu tidak berfungsi saat submodule tidak ada di ujung cabang.
Zitrax

16

Mengikuti jawaban Ryan, saya dapat menghasilkan skrip sederhana ini yang mengulangi semua submodul dan mengkloningnya:

#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
    spath=$(git config -f .gitmodules --get submodule.$i.path)
    surl=$(git config -f .gitmodules --get submodule.$i.url)
    git clone --depth 1 $surl $spath
done
git submodule update

Saya mendapatkan fatal: reference is not a tree: 88fb67b07621dfed054d8d75fd50672fb26349dfuntuk setiap submodul
knocte


1
@knocte: Saya menulis jawaban saya pada tahun 2010. Banyak hal telah berubah. Anda tidak dapat mengharapkan semua orang mempertahankan semua jawaban mereka. Saya menandai jawaban valid saat ini sebagai diterima.
Mauricio Scheffer

13
@knocte Ini adalah salah satu alasan mengapa saya berhenti berkontribusi ke Stackoverflow. Orang memiliki ekspektasi yang tidak realistis ini. Ini akan menjadi pekerjaan penuh waktu untuk mempertahankan setiap jawaban 1637 saya. Dan kemudian ada juga komentar, saya kira saya harus mempertahankannya juga? Lihatlah tanggalnya, untuk itulah mereka. Jika Anda membaca beberapa blog .NET dari tahun 2002 dengan kode menggunakan ArrayList, bukan List, apakah Anda akan menggunakannya? Apakah Anda akan meminta penulis untuk memperbarui postingannya? Prinsip yang sama berlaku di sini.
Mauricio Scheffer

1
s / statusquo / kemajuan /
knocte

8

Membaca "source" git-submodule, sepertinya git submodule adddapat menangani submodul yang sudah memiliki repositori. Dalam hal itu...

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...

Anda akan ingin memastikan komit yang diperlukan ada di repo submodule, jadi pastikan Anda menyetel --depth yang sesuai.

Sunting: Anda mungkin bisa lolos dengan beberapa klon submodul manual diikuti dengan satu pembaruan:

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update

5
Sekarang untuk git 1.8.0, Anda tidak dapat lagi menggandakan repositori di dalam repositori. Jadi solusi ini tidak berfungsi lagi.
Bohr

7

Ringkasan perilaku buggy / tidak terduga / mengganggu pada Git 2.14.1

  1. shallow = truedi .gitmoduleshanya mempengaruhi git clone --recurse-submodulesjika HEADpoin submodule remote untuk yang diperlukan komit, bahkan jika target komit ditunjukkan oleh cabang, dan bahkan jika Anda menempatkan branch = mybranchpada .gitmodulesjuga.

    Skrip pengujian lokal . Perilaku yang sama di GitHub 2017-11, HEADyang dikontrol oleh setelan repo cabang default:

    git clone --recurse-submodules https://github.com/cirosantilli/test-shallow-submodule-top-branch-shallow
    cd test-shallow-submodule-top-branch-shallow/mod
    git log
    # Multiple commits, not shallow.
    
  2. git clone --recurse-submodules --shallow-submodulesgagal jika komit yang tidak direferensikan oleh cabang atau tag dengan pesan: error: Server does not allow request for unadvertised object.

    Skrip pengujian lokal . Perilaku yang sama di GitHub:

    git clone --recurse-submodules --shallow-submodules https://github.com/cirosantilli/test-shallow-submodule-top-sha
    # error
    

    Saya juga bertanya di milis: https://marc.info/?l=git&m=151863590026582&w=2 dan jawabannya adalah:

    Secara teori ini seharusnya mudah. :)

    Sayangnya, dalam praktiknya tidak begitu banyak. Ini karena kloning hanya akan mendapatkan ujung cabang terbaru (biasanya master). Tidak ada mekanisme dalam klon untuk menentukan sha1 persis yang diinginkan.

    Protokol kawat mendukung untuk meminta sha1 yang tepat, sehingga itu harus ditutupi. (Peringatan: ini hanya berfungsi jika operator server mengaktifkan uploadpack.allowReachableSHA1InWant yang github tidak AFAICT)

    git-fetch memungkinkan untuk mengambil sembarang sha1, sehingga sebagai solusinya, Anda dapat menjalankan pengambilan setelah penggandaan rekursif dengan menggunakan "git submodule update" karena tindakan tersebut akan menggunakan pengambilan setelah penggandaan awal.

Tes TODO: allowReachableSHA1InWant.


Sepertinya tidak ada cara sederhana untuk melakukan pembayaran hash komit HEAD yang terlepas untuk submodul, dan memiliki pengguna hilir git clone --recursiveyang hanya mengambil komit khusus tersebut.
CMCDragonkai

3

Apakah lokasi kanonik untuk submodul Anda jauh? Jika ya, apakah Anda setuju dengan kloningnya satu kali? Dengan kata lain, apakah Anda menginginkan klon dangkal hanya karena Anda menderita bandwidth yang terbuang dari klon (ulang) submodul yang sering?

Jika Anda ingin klon dangkal untuk menghemat ruang disk lokal, maka jawaban Ryan Graham sepertinya cara yang bagus. Kloning repositori secara manual agar dangkal. Jika menurut Anda itu akan berguna, sesuaikan git submoduleuntuk mendukungnya. Kirim email ke daftar menanyakannya (saran untuk menerapkannya, saran tentang antarmuka, dll.). Menurut pendapat saya, orang-orang di sana cukup mendukung kontributor potensial yang dengan sungguh-sungguh ingin meningkatkan Git dengan cara yang konstruktif.

Jika Anda tidak keberatan melakukan satu klon penuh dari setiap submodul (ditambah pengambilan nanti untuk menjaganya tetap mutakhir), Anda dapat mencoba menggunakan --referenceopsi git submodule update(ada di Git 1.6.4 dan yang lebih baru) untuk merujuk ke penyimpanan objek lokal (mis. buat --mirrorklon dari repositori submodul kanonik, lalu gunakan --referencedi submodul Anda untuk menunjuk ke klon lokal ini). Pastikan untuk membaca tentang git clone --reference/ git clone --sharedsebelum menggunakan --reference. Satu-satunya masalah yang mungkin terjadi dengan mirror referensi adalah jika mereka akhirnya mengambil pembaruan non-fast-forward (meskipun Anda dapat mengaktifkan reflog dan memperluas jendela kedaluwarsa untuk membantu mempertahankan komitmen yang ditinggalkan yang mungkin menyebabkan masalah). Anda seharusnya tidak memiliki masalah selama

  • Anda tidak membuat komitmen submodul lokal, atau
  • komitmen apa pun yang dibiarkan menggantung oleh penerusan non-cepat yang mungkin diterbitkan oleh repositori kanonik bukanlah leluhur dari submodul lokal Anda, atau
  • Anda rajin menjaga komitmen submodul lokal Anda yang didasarkan pada apa pun yang tidak dipercepat-maju mungkin diterbitkan dalam repositori submodul kanonik.

Jika Anda menggunakan sesuatu seperti ini dan ada kemungkinan Anda membawa komit submodul lokal di pohon kerja Anda, mungkin ide yang bagus untuk membuat sistem otomatis yang memastikan objek penting yang direferensikan oleh submodul yang diperiksa tidak dibiarkan tergantung di repositori mirror (dan jika ada yang ditemukan, salin ke repositori yang membutuhkannya).

Dan, seperti yang git clonedikatakan halaman manual, jangan gunakan --referencejika Anda tidak memahami implikasi ini.

# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git

# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super

# To avoid extra packs in each of the superprojects' submodules,
#   update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done

cd super
git pull             # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
                     #   but no download since they reference the updated mirrors

Alternatifnya, alih-alih --reference, Anda dapat menggunakan klon cermin yang dikombinasikan dengan fungsionalitas tautan keras default git clonedengan menggunakan cermin lokal sebagai sumber untuk submodul Anda. Dalam klon super-proyek baru, lakukan git submodule init, edit URL submodule di . Anda perlu menyalin kembali semua submodul yang telah diperiksa untuk mendapatkan tautan keras. Anda akan menghemat bandwidth dengan hanya mengunduh sekali ke dalam mirror, kemudian mengambil secara lokal dari itu ke dalam submodul yang Anda check-out. Tautan keras akan menghemat ruang disk (meskipun pengambilan cenderung terakumulasi dan diduplikasi di beberapa contoh penyimpanan objek submodul yang diperiksa; Anda dapat secara berkala membuat ulang submodul yang diperiksa dari cermin untuk mendapatkan kembali penghematan ruang disk yang disediakan oleh hardlinking)..git/config untuk mengarah ke mirror lokal, lalu lakukangit submodule update


2

Saya membuat versi yang sedikit berbeda, karena saat itu tidak berjalan di tepi berdarah, yang tidak semua proyek melakukannya. Penambahan submodul standar tidak berfungsi, begitu pula skrip di atas. Jadi saya menambahkan pencarian hash untuk tag ref, dan jika tidak memilikinya, itu kembali ke klon penuh.

#!/bin/bash
git submodule init
git submodule | while read hash name junk; do
    spath=$(git config -f .gitmodules --get submodule.$name.path)
    surl=$(git config -f .gitmodules --get submodule.$name.url)
    sbr=$(git ls-remote --tags $surl | sed -r "/${hash:1}/ s|^.*tags/([^^]+).*\$|\1|p;d")
    if [ -z $sbr ]; then
        git clone $surl $spath
    else
        git clone -b $sbr --depth 1 --single-branch $surl $spath
    fi
done
git submodule update 

2

Referensi ke Bagaimana cara mengkloning repositori git dengan revisi / perubahan tertentu?

Saya telah menulis skrip sederhana yang tidak memiliki masalah ketika referensi submodul Anda jauh dari master

git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'

Pernyataan ini akan mengambil versi submodul yang direferensikan.

Ini cepat tetapi Anda tidak dapat melakukan suntingan Anda pada submodule (Anda harus mengambil unshallow sebelum https://stackoverflow.com/a/17937889/3156509 )

sepenuhnya:

#!/bin/bash
git submodule init
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'
git submodule update --recursive

1

Klon dangkal dari submodul sempurna karena mereka mengambil snapshot pada revisi / set perubahan tertentu. Sangat mudah untuk mengunduh zip dari situs web jadi saya mencoba untuk membuat skrip.

#!/bin/bash
git submodule deinit --all -f
for value in $(git submodule | perl -pe 's/.*(\w{40})\s([^\s]+).*/\1:\2/'); do
  mysha=${value%:*}
  mysub=${value#*:}
  myurl=$(grep -A2 -Pi "path = $mysub" .gitmodules | grep -Pio '(?<=url =).*/[^.]+')
  mydir=$(dirname $mysub)
  wget $myurl/archive/$mysha.zip
  unzip $mysha.zip -d $mydir
  test -d $mysub && rm -rf $mysub
  mv $mydir/*-$mysha $mysub
  rm $mysha.zip
done
git submodule init

git submodule deinit --all -f membersihkan pohon submodul yang memungkinkan skrip dapat digunakan kembali.

git submodulemengambil 40 karakter sha1 diikuti dengan jalur yang sesuai dengan di .gitmodules. Saya menggunakan perl untuk menggabungkan informasi ini, dibatasi oleh titik dua, kemudian menggunakan transformasi variabel untuk memisahkan nilai menjadi myshadan mysub.

Ini adalah kunci penting karena kita memerlukan sha1 untuk diunduh dan jalur untuk menghubungkan urlin .gitmodules.

Diberikan entri submodul khas:

[submodule "label"]
    path = localpath
    url = https://github.com/repository.git

myurltombol pada path =kemudian mencari 2 baris setelah untuk mendapatkan nilainya. Metode ini mungkin tidak bekerja secara konsisten dan membutuhkan perbaikan. Url grep menghapus semua .gitreferensi jenis yang tersisa dengan mencocokkan yang terakhir /dan apa pun hingga a ..

mydiradalah mysubminus final /nameyang akan dilakukan oleh direktori yang mengarah ke nama submodule.

Berikutnya adalah wgetdengan format url arsip zip yang dapat diunduh. Ini mungkin berubah di masa depan.

Buka zip file mydiryang akan menjadi subdirektori yang ditentukan di jalur submodul. Folder yang dihasilkan akan menjadi elemen terakhir dari url- sha1.

Periksa untuk melihat apakah subdirektori yang ditentukan di jalur submodul ada dan hapus untuk memungkinkan penggantian nama folder yang diekstrak.

mv ganti nama folder yang diekstrak yang berisi sha1 kami ke jalur submodul yang benar.

Hapus file zip yang diunduh.

Submodul init

Ini lebih merupakan bukti konsep WIP daripada solusi. Saat berhasil, hasilnya adalah klon dangkal dari submodule pada set perubahan tertentu.

Jika repositori mengembalikan submodul ke komit yang berbeda, jalankan ulang skrip untuk memperbarui.

Satu-satunya saat skrip seperti ini akan berguna adalah untuk bangunan lokal non-kolaboratif dari proyek sumber.


0

Saya membutuhkan solusi untuk kloning submodul yang dangkal ketika saya tidak dapat mempengaruhi kloning repo utama. Berdasarkan satu solusi di atas:

#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
    git submodule update --init --depth 1 -- $i
done
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.