Wygląda na to, że w tej dyskusji łączone są dwa różne scenariusze:
Scenariusz 1
Używając wskaźników mojego repozytorium nadrzędnego do podmodułów, chcę sprawdzić zatwierdzenie w każdym podmodule, na który wskazuje repozytorium nadrzędne, być może po pierwszej iteracji przez wszystkie podmoduły i aktualizacji / ściągnięciu ich ze zdalnego.
Jest to, jak wskazano, zrobione z
git submodule foreach git pull origin BRANCH
git submodule update
Scenariusz 2, do którego, jak sądzę, dąży
W jednym lub więcej submodułach wydarzyły się nowe rzeczy i chcę 1) pobrać te zmiany i 2) zaktualizować repozytorium nadrzędne, aby wskazywało zatwierdzenie HEAD (najnowsze) tego / tych submodułów.
Zostanie to zrobione przez
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
Niezbyt praktyczne, ponieważ musiałbyś zakodować n ścieżek do wszystkich n podmodułów, np. W skrypcie, aby zaktualizować wskaźniki zatwierdzenia repozytorium nadrzędnego.
Byłoby fajnie mieć zautomatyzowaną iterację przez każdy podmoduł, aktualizując wskaźnik nadrzędnego repozytorium (za pomocą git add
), aby wskazywał na głowę submodułu (-ów).
W tym celu stworzyłem ten mały skrypt Bash:
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
Aby go uruchomić, uruchom
git-update-submodules.sh /path/to/base/repo BRANCH_NAME
Opracowanie
Po pierwsze zakładam, że gałąź o nazwie $ BRANCH (drugi argument) istnieje we wszystkich repozytoriach. Możesz to jeszcze bardziej skomplikować.
Pierwsza para sekcji to sprawdzanie, czy istnieją argumenty. Następnie ściągam najnowsze rzeczy z repozytorium nadrzędnego (wolę używać --ff (szybkie przewijanie do przodu) za każdym razem, gdy robię ciągnięcia. Mam wyłączoną bazę, BTW).
git checkout $BRANCH && git pull --ff origin $BRANCH
W takim przypadku może być konieczne zainicjowanie niektórych modułów podrzędnych, jeśli dodano nowe moduły podrzędne lub nie zostały jeszcze zainicjowane:
git submodule sync
git submodule init
git submodule update
Następnie aktualizuję / ściągam wszystkie podmoduły:
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
Zwróć uwagę na kilka rzeczy: Po pierwsze, łączę niektóre polecenia Git za pomocą &&
- co oznacza, że poprzednie polecenie musi zostać wykonane bezbłędnie.
Po możliwym udanym pobraniu (jeśli nowe rzeczy zostały znalezione na pilocie), robię push, aby upewnić się, że ewentualne scalenie-zatwierdzenie nie zostanie pozostawione na kliencie. Znowu dzieje się tak tylko wtedy, gdy pociągnięcie rzeczywiście przynosi nowe rzeczy.
Wreszcie, ostatecznym || true
zadaniem jest upewnienie się, że skrypt kontynuuje błędy. Aby to zadziałało, wszystko w iteracji musi być zawinięte w cudzysłowy, a polecenia Git są umieszczone w nawiasach (pierwszeństwo operatora).
Moja ulubiona część:
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
Iteruj wszystkie podmoduły - za pomocą --quiet
, która usuwa wyjście „Wprowadzanie MODULE_PATH”. Używając 'echo $path'
(musi być w cudzysłowach), ścieżka do submodułu zostaje zapisana do wyjścia.
Ta lista względnych ścieżek podmodułu jest przechwytywana w array ( $(...)
) - w końcu iteruj to i zrób git add $i
aktualizację repozytorium nadrzędnego.
Na koniec zatwierdzenie z komunikatem wyjaśniającym, że repozytorium nadrzędne zostało zaktualizowane. To zatwierdzenie zostanie domyślnie zignorowane, jeśli nic nie zostało zrobione. Wciśnij to do źródła i gotowe.
Mam skrypt uruchamiający to w zadaniu Jenkins, który następnie łączy się z zaplanowanym automatycznym wdrożeniem i działa jak urok.
Mam nadzieję, że komuś to pomoże.
--remote
opcji, być może warto byłoby zaznaczyć to jako odpowiedź zaakceptowaną, a nie podejście „ręczne” w odpowiedzi Jasona?