Aktualizacja aplikacji przez Git
Przeprowadzisz ręczną, kontrolowaną aktualizację aplikacji z brancha main, a następnie zrestartujesz usługę i wykonasz podstawowy smoke test.
1. Krótka teoria
Repozytorium Git może być źródłem wersji kodu wdrażanej na serwerze. Przed aktualizacją trzeba wejść do /opt/example-app/app, potwierdzić branch main i sprawdzić, czy working tree jest czyste. Lokalne zmiany na serwerze utrudniają ustalenie rzeczywistej wersji i mogą wejść w konflikt z kodem z repozytorium, dlatego plików produkcyjnych nie należy ręcznie edytować. git fetch origin pobiera informacje i obiekty z repozytorium zdalnego, ale sam nie przesuwa bieżącego brancha. git pull pobiera zmiany i integruje je z bieżącym branchem. W kontrolowanym deploymencie warto użyć git pull --ff-only origin main: polecenie powiedzie się tylko wtedy, gdy branch można przesunąć bez tworzenia merge commita. Nie rozwiązuje to wszystkich ryzyk, ale zatrzymuje wdrożenie przy rozbieżnej historii zamiast samodzielnie scalać kod na serwerze. Operacje Git w katalogu aplikacji powinien wykonywać właściciel repozytorium, zwykle użytkownik usługi lub dedykowane konto wdrożeniowe, a nie przypadkowo root. Przed pobraniem warto zapisać bieżący commit, a po nim sprawdzić git log -1 --oneline. Jeżeli zmienił się requirements.txt lub dokumentacja wydania tego wymaga, należy zainstalować zależności przez interpreter z /opt/example-app/venv. Nie trzeba wykonywać tej operacji przy każdym wdrożeniu bez potrzeby. Następnie restartuje się example-app.service, sprawdza status i logi oraz wywołuje lokalny endpoint na 127.0.0.1:8000. git reset --hard nie jest standardową procedurą aktualizacji: może bezpowrotnie usunąć lokalne zmiany i ukryć przyczynę rozbieżności. W tej lekcji wdrożenie pozostaje ręczne; automatyczne CI/CD wymaga osobnego projektu procesu.
2. Przykłady komend
cd /opt/example-app/app && git branch --show-current && git status --short
Potwierdza katalog, branch i czystość working tree przed wdrożeniem.
$ cd /opt/example-app/app
$ git branch --show-current
main
$ git status --short
git fetch origin
Pobiera aktualne dane z origin bez zmiany bieżącego brancha.
$ git fetch origin
git pull --ff-only origin main
Aktualizuje main tylko wtedy, gdy możliwy jest fast-forward.
$ git pull --ff-only origin main
git log -1 --oneline
Pokazuje commit znajdujący się aktualnie na szczycie wdrożonego brancha.
$ git log -1 --oneline
7ab12cd Prepare release
/opt/example-app/venv/bin/python -m pip install -r requirements.txt
Aktualizuje zależności, gdy zmienił się requirements.txt lub wymaga tego wydanie.
$ /opt/example-app/venv/bin/python -m pip install -r requirements.txt
sudo systemctl restart example-app && sudo systemctl status example-app --no-pager -l
Restartuje usługę i natychmiast pokazuje jej szczegółowy stan.
$ sudo systemctl restart example-app
$ sudo systemctl status example-app --no-pager -l
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/
Wykonuje prosty lokalny smoke test i wypisuje kod HTTP.
$ curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/
200
3. Zadanie praktyczne
/opt/example-app/app. Jako użytkownik właściwy dla repozytorium sprawdź branch i czyste working tree, zapisz bieżący commit, wykonaj git fetch origin, przejrzyj zmiany i użyj git pull --ff-only origin main. Sprawdź najnowszy commit. Zaktualizuj zależności tylko wtedy, gdy zmienił się requirements.txt, potem zrestartuj usługę, oceń jej status i wykonaj test HTTP na 127.0.0.1:8000. Zapisz wyniki kolejnych kroków w notatce wdrożeniowej.
4. Typowe błędy
- Wykonywanie pull bez sprawdzenia brancha i lokalnych zmian.
- Ręczna edycja kodu na serwerze produkcyjnym.
- Używanie zwykłego pull, który może utworzyć nieplanowany merge commit.
- Uruchamianie Git jako root mimo innego właściciela repozytorium.
- Instalowanie zależności globalnie zamiast w venv aplikacji.
- Kończenie wdrożenia po restarcie bez statusu, logów i smoke testu.
- Stosowanie git reset --hard do maskowania rozbieżności na serwerze.
5. Podsumowanie
Kontrolowana aktualizacja zaczyna się od właściwego brancha, czystego working tree i zapisu bieżącego commita. Fetch pobiera stan zdalny bez integracji, a pull --ff-only zatrzymuje proces przy rozbieżnej historii. Po pobraniu zmian aktualizuje się zależności tylko w razie potrzeby, restartuje usługę i weryfikuje commit, status, logi oraz lokalny endpoint.