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
git submodule foreach git pull origin BRANCH
git submodule update
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
git submodule foreach git pull origin BRANCH
git add module_1_name
git add module_2_name
......
git add module_n_name
git push origin BRANCH
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
#!/bin/bash
APP_PATH=$1
shift
if [ -z $APP_PATH ]; then
echo "Missing 1st argument: should be path to folder of a git repo";
exit 1;
fi
BRANCH=$1
shift
if [ -z $BRANCH ]; then
echo "Missing 2nd argument (branch name)";
exit 1;
fi
echo "Working in: $APP_PATH"
cd $APP_PATH
git checkout $BRANCH && git pull --ff origin $BRANCH
git submodule sync
git submodule init
git submodule update
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
git commit -m "Updated $BRANCH branch of deployment repo to point to latest head of submodules"
git push origin $BRANCH
Untuk menjalankannya, jalankan
git-update-submodules.sh /path/to/base/repo BRANCH_NAME
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).
git checkout $BRANCH && git pull --ff origin $BRANCH
Maka beberapa submodule yang diinisialisasi, mungkin diperlukan, jika submodul baru telah ditambahkan atau belum diinisialisasi:
git submodule sync
git submodule init
git submodule update
Lalu saya memperbarui / menarik semua submodul:
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
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:
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
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 lakukan git 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.
--remote
opsi, mungkin akan berguna untuk menandai bahwa sebagai jawaban yang diterima daripada pendekatan "dengan tangan" dalam jawaban Jason?