Введение
Обучение в Школе 21 строится на двух типах проектов: индивидуальных и командных. Основная сложность индивидуального проекта, будь то разработка консольного приложения или погружение в основы девопса, — задачи самого проекта. В командной же разработке прибавляется необходимость распределения задач между участниками и построение комфортной работы с общим репозиторием. В этой заметке хочу описать, как мы настроили работу с репозиторием.
Peer-to-peer
Помню, на отборочном интенсиве я в основном концентрировался на коде и не углублялся в изучение возможностей системы контроля версий. Знал только стандартную последовательность заклинаний: git add .
→ git commit -m "commit message"
→ git push origin develop
, и то не до конца понимал, как это всё работает. А в групповых проектах, где я принимал участие, мы работали каждый в своей ветке, а окончательный код тимлид копипастом из наших веток собирал в единое целое, либо он сольно писал весь проект, особо не обращая внимания на результаты разработки остальных членов команды.
Слышал, правда, от нескольких пиров по соседству загадочные слова фетч
, мёрж
и пул
, но вникать в их суть тогда не стал, чтобы не уронить и без того шаткое понимание работы с репозиторием.
На основном обучении повезло скорефаниться с одним пиром из предыдущей волны набора. Он поделился концепцией командной разработки и скинул пару скриптов, которые почти автоматизировали весь процесс работы с общим репозиторием.
На первый взгляд всё показалось запутанным и непонятным, да ещё и в скриптах прописаны незнакомые команды. Всё, что я понял:
работай в своей ветке и в своей папке;
в начале рабочей сессии запускай скрипт
get
;перед пушем в репозиторий запускай скрипт
get
, потом создавай коммит и запускай скриптupdate
окончательный вариант проекта собирается из общей ветки и пушится на ветку develop (школьный prod)
Можно было бы этим и ограничиться, но хотелось использовать полученные инструменты более осознанно, с пониманием того, что стоит за вызовом предоставленных скриптов.
Выделил время и сел разбираться с темой ветвления в Git и утилитой sed. Оказалось, что всё не так уж и сложно. Идея в том, что помимо личных веток существует буферная общая ветка, в которой хранится код всех участников. Через неё весь код попадает в ветки разработчиков. Таким образом, каждый участник имеет доступ к наработкам сокомандников. Эта концепция подразумевает, что:
каждый работает в своей ветке и пишет код только в своих файлах
перед началом рабочей сессии актуальное состояние кода на удалённой общей ветке подтягивается на локальный репозиторий разработчика:
$ git checkout common_branch # переключаемся на общую ветку;
$ git pull # забираем последние изменения из удалённой
# общей ветки;
$ git checkout developer_branch # переключаемся обратно в личную ветку;
$ git merge common_branch # сливаем полученные изменения
# в личную ветку;
$ git push origin developer_branch # пушим эти изменения на удалённую
# личную ветку.
перед тем, как пушить свои изменения в личную ветку, проделывается последовательность команд из пункта 2, а затем общая ветка дополняется изменениями кода разработчика:
$ последовательность команд из п.2
$ git add .
$ git commit -m "commit message" # создаём коммит;
$ git checkout common_branch # переключаемся на общую ветку;
$ git merge developer_branch # сливаем свой коммит в общую ветку;
$ git push origin common_branch # пушим этот коммит на общую удалённую ветку;
$ git checkout developer_branch # переключаемся на личную ветку;
$ git push origin developer_branch # пушим этот коммит на личную ветку.
И вот на основе этих двух последовательностей вводимых команд можно составить простые скрипты, запуск которых будет ускорять работу с общим репозиторием.
Скрипт get_remote_common_branch.sh
#!/bin/sh
CUR_BRANCH=$(git branch | grep "*" | sed 's/* //')
COMMON_BRANCH=duslar
git checkout $COMMON_BRANCH
git pull
git checkout $CUR_BRANCH
git merge $COMMON_BRANCH
git push origin $CUR_BRANCH
Скрипт update_remote_common_branch.sh
#!/bin/sh
CUR_BRANCH=$(git branch | grep "*" | sed 's/* //')
COMMON_BRANCH=duslar
git checkout $COMMON_BRANCH
git merge $CUR_BRANCH
git push origin $COMMON_BRANCH
git checkout $CUR_BRANCH
git push origin $CUR_BRANCH
Теперь для пуша своего кода в репозиторий вместо двенадцати команд достаточно ввести всего четыре:
$ sh get_remote_common_branch.sh
$ git add .
$ git commit -m "commit message"
$ sh update_remote_common_branch.sh
А, может, вообще можно обойтись одной строкой в терминале?
Этот вопрос задал себе на третьем групповом проекте, когда стало влом каждый раз вводить эти четыре строки. Что, если внутри скрипта организовать вызов функции get_from_common_remote_branch()
или update_common_remote_branch()
в зависимости от ключа из командной строки, а для функции push_to_user_remote_branch()
ещё и сообщение коммита зацепить?
Изучив немного информации по bash-скриптам, понял, как можно организовать вызов определённой функции внутри скрипта и как прочитать аргументы командной строки. В итоге, теперь для работы нужно запустить скрипт с ключом -g
(--get)
, чтобы забрать себе актуальное состояние проекта, или -u
(--update)
с сообщением коммита в кавычках, чтобы запушить свои изменения.
Скрипт duslar.sh
#!/bin/sh
function get_from_common_remote_branch() {
echo "\033[33m$COMMON_BRANCH\033[32m remote branch last stage getting\033[0m"
git checkout $COMMON_BRANCH
git pull # get latest commit from remote common branch
git checkout $USER_BRANCH
git merge $COMMON_BRANCH
git push origin $USER_BRANCH
}
function push_to_user_remote_branch() {
echo "\033[33m$USER_BRANCH\033[32m committing and pushing to remote\033[0m"
shift
git add .
git commit -m "$USER_BRANCH: $*"
git push origin $USER_BRANCH
}
function update_common_remote_branch() {
echo "\033[33m$COMMON_BRANCH\033[32m remote branch updating\033[0m"
git checkout $COMMON_BRANCH
git merge $USER_BRANCH
git push origin $COMMON_BRANCH
git checkout $USER_BRANCH
git push origin $USER_BRANCH
}
function usage() {
echo "$0: illegal option -- $1"
echo "usage: sh $0 [--help][-h][man] [--get][-g] [--update \"commit message\"][-u \"commit message\"]"
}
function man_print() {
echo "
Team working script.
usage: sh $0 [--help][-h][man] [--get][-g] [--update \"commit message\"][-u \"commit message\"]
Use options [--get][-g] for getting $COMMON_BRANCH remote branch last stage.
Use options [--update][-u] with your commit message (in quotes!) for updating your own and $COMMON_BRANCH remote branches.
"
}
USER_BRANCH=$(git branch | grep "*" | sed 's/* //') # sed is Stream EDitor
COMMON_BRANCH=duslar
if [ $1 = --get ] || [ $1 = -g ]
then
get_from_common_remote_branch
elif [ $1 = --update ] || [ $1 = -u ]
then
get_from_common_remote_branch
push_to_user_remote_branch $*
update_common_remote_branch
elif [ $1 = --help ] || [ $1 = -h ] || [ $1 = man ]
then
man_print
else
usage $1
fi
Вместо заключения
Не думаю, что такая модель работы с Git подойдёт для реальной разработки, но на первых порах она нам позволила не думать о хранении и использовании командного кода и сосредоточиться на написании проектов.
peer-to-peer
Комментарии (3)
s21useragent
22.07.2023 22:21-3Отличная первая статья, Тагир! Подчерпнул для себя новый способ пуша файлов в git.
SWATOPLUS
22.07.2023 22:21А, может, вообще можно обойтись одной строкой в терминале?
А может вообще обойтись кнопками в IDE?
Статья была бы куда полезнее если бы вы просто дали ссылки на главы git-book, которые дают основы работы с гит. Эти велосипедные скрипты никому не нужны. Обычно все делается мышкой в IDE или хоткеями. А консоль используется для более тонких действий, например для rebase или reset hard/force push.
Да и про branching-strategy не мешало бы рассказать.
kos21
Полезные скрипты!