Close

Скрипты Git hook

Хук Git — это скрипт, который автоматически запускается каждый раз, когда в репозитории Git происходит определенное событие. С помощью хуков можно конфигурировать внутреннее поведение Git и запускать настраиваемые действия в ключевые моменты жизненного цикла разработки.

Хуки, исполняемые при создании коммита

Обычно хуки Git используют, чтобы поддерживать политику коммитов, изменять среду проекта в зависимости от состояния репозитория и внедрять рабочие процессы непрерывной интеграции. Однако эти скрипты можно настраивать с учетом любых предпочтений, поэтому они помогут автоматизировать или оптимизировать практически любую сторону процесса разработки.

В этой статье мы разберем основы работы хуков Git, после чего рассмотрим несколько самых популярных скриптов, которые подходят как для локальных репозиториев, так и для репозиториев на стороне сервера.


Обзор основных моментов


Все хуки Git представляют собой обыкновенные скрипты, которые Git исполняет в ответ на определенные события в репозитории. По этой причине их очень просто установить и настроить.

Хуки могут находиться как в локальном, так и в серверном репозитории, при этом они исполняются только при выполнении действий в данном репозитории. Мы рассмотрим категории хуков далее в статье. Конфигурация, описанная в этом разделе, относится и к локальным, и к серверным хукам.

Установка хуков

Хуки находятся в каталоге .git/hooks каждого репозитория Git. Система Git автоматически заполняет этот каталог образцами скриптов при инициализации репозитория. В .git/hooks можно найти следующие файлы:

applypatch-msg.sample       pre-push.sample
commit-msg.sample           pre-rebase.sample
post-update.sample          prepare-commit-msg.sample
pre-applypatch.sample       update.sample
pre-commit.sample
базы данных
Связанные материалы

Перемещение полного репозитория Git

Логотип Bitbucket
СМ. РЕШЕНИЕ

Изучите Git с помощью Bitbucket Cloud

Здесь представлено большинство доступных хуков, но из-за расширения .sample они не исполняются по умолчанию. Чтобы «установить» хук, достаточно удалить расширение .sample. Кроме того, самостоятельно написав новый скрипт, вы сможете быстро добавить новый файл с одним из перечисленных выше имен и без расширения .sample.

В качестве тренировки попробуйте установить простой хук под названием prepare-commit-msg. Уберите из имени скрипта расширение .sample и добавьте в файл следующую запись:

#!/bin/sh

echo "# Please include a useful commit message!" > $1

Хуки должны быть исполняемыми, поэтому вам может понадобиться изменить права доступа к скрипту, если вы создаете его самостоятельно. Чтобы убедиться в том, что скрипт prepare-commit-msg можно исполнить, выполните следующую команду:

chmod +x prepare-commit-msg

Теперь при каждом выполнении команды git commit вместо комментария к коммиту по умолчанию будет отображаться указанный вами текст. Вы сможете узнать больше о подготовке комментариев к коммиту в соответствующем разделе. А пока просто порадуемся тому, что у нас получилось настроить некоторые из внутренних функций Git.

Встроенные образцы служат полезным источником информации, поскольку они содержат параметры, передаваемые каждому хуку (эти параметры различаются в зависимости от хука).

Языки скриптов

Встроенные скрипты большей частью представляют собой сценарии оболочки и PERL, но вы можете выбрать любой язык скриптов при условии, что скрипт можно будет запускать как исполняемый файл. Строка шебанга (#!/bin/sh) в каждом скрипте определяет способ интерпретации файла. Поэтому, чтобы сменить язык, достаточно указать в этой строке путь к нужному интерпретатору.

Например, можно написать исполняемый скрипт на Python в файле prepare-commit-msg вместо того, чтобы использовать команду оболочки. Следующий хук будет делать то же, что и скрипт оболочки из предыдущего раздела.

#!/usr/bin/env python

import sys, os

commit_msg_filepath = sys.argv[1]
with open(commit_msg_filepath, 'w') as f:
    f.write("# Please include a useful commit message!")

Обратите внимание на изменения первой строки: теперь в ней указан путь к интерпретатору Python. Кроме того, вместо позиционного параметра $1, позволяющего получить доступ к первому аргументу скрипта, использован параметр sys.argv[1] (подробнее об этом будет рассказано чуть позже).

Это очень полезная возможность, поскольку она позволяет писать хуки Git на любом удобном для вас языке.

Область действия хуков

Будучи локальными объектами репозитория Git, хуки не копируются в новый репозиторий при выполнении команды git clone. Кроме того, это означает, что их может изменить любой пользователь с доступом к данному репозиторию.

Из этого вытекают важные особенности настройки хуков для команды разработчиков. Во-первых, нужно решить, как поддерживать актуальность скриптов для всех участников. Во-вторых, нельзя заставить разработчиков выполнять коммиты строго определенным образом (об этом их можно лишь попросить).

Поддерживать базу хуков для команды разработчиков может быть непросто, потому что каталог .git/hooks не клонируется вместе с проектом и не подпадает под контроль версий. Обе эти проблемы легко устранить, если сохранить хуки непосредственно в каталоге проекта (над каталогом .git). Это позволит редактировать хуки так же, как и любой файл в системе управления версиями. Чтобы установить хук, можно создать в каталоге .git/hooks символическую ссылку на него либо просто копировать и вставлять хук в каталог .git/hooks при каждом обновлении хука.

Хуки, исполняемые при создании коммита

В качестве альтернативы можно использовать доступный в Git механизм каталога шаблонов, который упрощает автоматическую установку хуков. Все файлы и каталоги, находящиеся в этом каталоге шаблонов, будут копироваться в каталог .git при каждом выполнении команды git init или git clone.

Все описанные ниже локальные хуки может изменить или полностью удалить владелец репозитория. Каждый участник команды сам решает, использовать ли ему тот или иной хук. Об этом стоит помнить и относиться к хукам как к удобному инструменту разработки, а не как к обязательным правилам.

При этом можно отклонять не соответствующие стандарту коммиты, используя серверные хуки. Подробнее об этом читайте далее в статье.

Локальные скрипты hook


Локальные хуки воздействуют только на свой репозиторий. Читая этот раздел, помните о том, что каждый разработчик может изменять свои локальные хуки, а потому они не подходят для внедрения обязательной политики коммитов. Вместе с тем скрипты могут сильно облегчить для разработчиков выполнение определенных правил. В этом разделе мы рассмотрим шесть наиболее полезных локальных хуков:

  • pre-commit;
  • prepare-commit-msg;
  • commit-msg;
  • post-commit;
  • post-checkout;
  • pre-rebase.

Первые четыре скрипта позволяют принять необходимые меры на всех этапах жизненного цикла коммита, а последние два — выполнить дополнительные действия или проверить безопасность в рамках команд git checkout и git rebase соответственно.

Все хуки с префиксом pre- в названии изменяют предстоящее действие, а хуки с префиксом post- используются только для уведомлений.

Мы также рассмотрим полезные приемы, с помощью которых можно разбирать аргументы хука и запрашивать информацию о репозитории с помощью низкоуровневых команд Git.

pre-commit

Скрипт pre-commit исполняется при каждом выполнении команды git commit, перед тем как Git запросит ввод комментария к коммиту или создаст объект коммита. Этот хук можно использовать для проверки отправляемого снимка состояния. К примеру, он позволяет запустить автоматическое тестирование и проверить, не нарушит ли коммит работу существующих функций.

Скрипт pre-commit не принимает аргументов, а ненулевое состояние выхода приведет к отмене всего коммита. Посмотрим на упрощенный (и более длинный) вариант встроенного хука pre-commit. Он отменяет коммит при обнаружении лишних пробелов, наличие которых проверяется командой git diff-index (конечные пробелы, строки только с пробелами, а также последовательность из пробела и табуляции в отступе строки по умолчанию считаются ошибкой).

#!/bin/sh

# Check if this is the initial commit
if git rev-parse --verify HEAD >/dev/null 2>&1
then
    echo "pre-commit: About to create a new commit..."
    against=HEAD
else
    echo "pre-commit: About to create the first commit..."
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Use git diff-index to check for whitespace errors
echo "pre-commit: Testing for whitespace errors..."
if ! git diff-index --check --cached $against
then
    echo "pre-commit: Aborting commit due to whitespace errors"
    exit 1
else
    echo "pre-commit: No whitespace errors :)"
    exit 0
fi

Чтобы использовать команду git diff-index, нужно определить, с какой ссылкой на коммит мы будем сравнивать индекс. Обычно это указатель HEAD. Однако на момент создания первичного коммита никакого указателя HEAD еще нет, поэтому в первую очередь мы учтем этот пограничный случай. Для этого используем команду git rev-parse --verify, которая проверит, является ли аргумент (HEAD) действительной ссылкой. Выражение >/dev/null 2>&1 скрывает выходные данные команды git rev-parse. Указатель HEAD или пустой объект коммита сохраняются в переменной against, которая используется в команде git diff-index. Хеш 4b825d… — это волшебный идентификатор пустого коммита.

Команда git diff-index --cached сравнивает коммит с индексом. Передавая параметр --check, мы просим предупредить нас о наличии лишних пробелов в изменениях. При наличии таких пробелов будет возвращено состояние выхода 1, и коммит будет отменен, а при их отсутствии — 0, и рабочий процесс коммита возобновится в обычном режиме.

Это лишь один из примеров хука pre-commit. В него можно не только добавлять существующие команды Git, чтобы тестировать изменения, вносимые коммитом. Внутри pre-commit также можно выполнять любые другие действия, в том числе запускать другие скрипты и сторонние наборы тестов, а также проверять стиль кода с помощью Lint.

Подготовка комментария к коммиту

Хук prepare-commit-msg вызывается после pre-commit, чтобы составить комментарий к коммиту в текстовом редакторе. На этом этапе можно удобно изменить автоматически сгенерированный комментарий к коммиту склеивания или слияния.

Скрипт prepare-commit-msg принимает от одного до трех аргументов.

1. Имя временного файла, содержащего комментарий. Вы изменяете комментарий к коммиту путем редактирования этого файла на месте.

2. Тип коммита: message (комментарий, обозначается параметром -m или -F), template (шаблон, обозначается параметром -t), merge (для коммитов слияния) или squash (для коммитов, созданных в результате склеивания).

3. Хеш SHA-1 соответствующего коммита. Передается только вместе с параметром -c, -C или --amend.

Как и в случае с pre-commit ненулевое состояние выхода отменяет коммит.

Теперь, когда мы изучили простой пример редактирования сообщения коммита, посмотрим на более полезный скрипт. При использовании системы отслеживания задач каждую задачу принято решать в отдельной ветке. Указав в имени ветки номер задачи, вы можете написать хук prepare-commit-msg, чтобы автоматически включать этот номер в каждое сообщение коммита в данной ветке.

#!/usr/bin/env python

import sys, os, re
from subprocess import check_output

# Collect the parameters
commit_msg_filepath = sys.argv[1]
if len(sys.argv) > 2:
    commit_type = sys.argv[2]
else:
    commit_type = ''
if len(sys.argv) > 3:
    commit_hash = sys.argv[3]
else:
    commit_hash = ''

print "prepare-commit-msg: File: %s\nType: %s\nHash: %s" % (commit_msg_filepath, commit_type, commit_hash)

# Figure out which branch we're on
branch = check_output(['git', 'symbolic-ref', '--short', 'HEAD']).strip()
print "prepare-commit-msg: On branch '%s'" % branch

# Populate the commit message with the issue #, if there is one
if branch.startswith('issue-'):
    print "prepare-commit-msg: Oh hey, it's an issue branch."
    result = re.match('issue-(.*)', branch)
    issue_number = result.group(1)

    with open(commit_msg_filepath, 'r+') as f:
        content = f.read()
        f.seek(0, 0)
        f.write("ISSUE-%s %s" % (issue_number, content))

В приведенном выше хуке prepare-commit-msg можно заметить, что сначала происходит сбор всех параметров, передаваемых скрипту. Затем вызывается команда git symbolic-ref --short HEAD для получения имени ветки, соответствующей положению указателя HEAD. Если имя этой ветки начинается с issue-, содержимое файла с сообщением коммита перезаписывается и в первую строку добавляется номер задачи. Так, если имя вашей ветки issue-224, будет сгенерировано следующее сообщение коммита.

ISSUE-224 

# Please enter the commit message for your changes. Lines starting 
# with '#' will be ignored, and an empty message aborts the commit. 
# On branch issue-224 
# Changes to be committed: 
#   modified:   test.txt

При использовании хука prepare-commit-msg следует помнить, что он запускается даже в том случае, если пользователь передает сообщение с помощью параметра -m команды git commit. Это означает, что приведенный выше скрипт автоматически вставит строку ISSUE-[#] без возможности редактирования. В этом случае можно проверить, есть ли у второго параметра (commit_type) значение message.

Однако если не указывать параметр -m для хука prepare-commit-msg, пользователь сможет отредактировать сообщение после его создания, поэтому такой скрипт упростит работу, но не обеспечит внедрение обязательной политики сообщений коммитов. Чтобы этого добиться, вам понадобится хук commit-msg, описанный в следующем разделе.

Комментарий к коммиту

Хук commit-msg очень похож на prepare-commit-msg, но вызывается после того, как пользователь введет сообщение коммита. На этом этапе полезно предупреждать разработчиков о том, что их сообщение не соответствует стандартам вашей команды.

Единственный аргумент, передаваемый данному хуку, — это имя файла, содержащего сообщение. Если введенное пользователем сообщение не соответствует требованиям, хук может изменить этот файл на месте (как в случае с prepare-commit-msg) или полностью отменить коммит, завершив работу с ненулевым состоянием.

Например, следующий скрипт проверяет, не удалил ли пользователь строку ISSUE-[#], которая была автоматически сгенерирована хуком prepare-commit-msg из предыдущего раздела.

#!/usr/bin/env python

import sys, os, re
from subprocess import check_output

# Collect the parameters
commit_msg_filepath = sys.argv[1]

# Figure out which branch we're on
branch = check_output(['git', 'symbolic-ref', '--short', 'HEAD']).strip()
print "commit-msg: On branch '%s'" % branch

# Check the commit message if we're on an issue branch
if branch.startswith('issue-'):
    print "commit-msg: Oh hey, it's an issue branch."
    result = re.match('issue-(.*)', branch)
    issue_number = result.group(1)
    required_message = "ISSUE-%s" % issue_number

    with open(commit_msg_filepath, 'r') as f:
        content = f.read()
        if not content.startswith(required_message):
            print "commit-msg: ERROR! The commit message must start with '%s'" % required_message
            sys.exit(1)

Несмотря на то что этот скрипт вызывается каждый раз, когда пользователь создает коммит, не рекомендуется выполнять какие-либо дополнительные действия кроме проверки сообщения коммита. Если вам нужно уведомить о создании коммита другие службы, используйте хук post-commit.

post-commit

Хук post-commit вызывается сразу после commit-msg. С его помощью нельзя изменить результат операции git commit, поэтому он используется в основном для уведомлений.

Этот скрипт не имеет параметров, и его статус выхода не влияет на коммит. Большинству скриптов post-commit требуется доступ к только что созданному коммиту. Вы можете использовать команду git rev-parse HEAD, чтобы получить хеш SHA-1 нового коммита, или команду git log -1 HEAD, чтобы получить полную информацию о нем.

Например, если вы хотите отправлять своему руководителю электронное письмо при каждом создании коммита (такой подход вряд ли окажется полезным для большинства рабочих процессов), можно добавить следующий хук post-commit.

#!/usr/bin/env python

import smtplib
from email.mime.text import MIMEText
from subprocess import check_output

# Get the git log --stat entry of the new commit
log = check_output(['git', 'log', '-1', '--stat', 'HEAD'])

# Create a plaintext email message
msg = MIMEText("Look, I'm actually doing some work:\n\n%s" % log)

msg['Subject'] = 'Git post-commit hook notification'
msg['From'] = 'mary@example.com'
msg['To'] = 'boss@example.com'

# Send the message
SMTP_SERVER = 'smtp.example.com'
SMTP_PORT = 587

session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
session.ehlo()
session.starttls()
session.ehlo()
session.login(msg['From'], 'secretPassword')

session.sendmail(msg['From'], msg['To'], msg.as_string())
session.quit()

Для запуска локальной системы непрерывной интеграции можно использовать post-commit, но в большинстве случаев вы будете делать это в хуке post-receive. Он выполняется на сервере, а не на локальном компьютере пользователя, и запускается каждый раз, когда любой разработчик отправляет свой код. Именно поэтому он лучше всего подходит для непрерывной интеграции.

post-checkout

Хук post-checkout очень похож на post-commit, но вызывается каждый раз при успешном переключении с помощью git checkout. Им удобно пользоваться в тех случаях, когда нужно очистить рабочий каталог от сгенерированных файлов, которые в противном случае привели бы к путанице.

Этот хук принимает три параметра, и его статус выхода не влияет на команду git checkout. Вот эти параметры:

1. предыдущий указатель HEAD;

2. ссылка на новый указатель HEAD;

3. флаг, указывающий на то, было ли выполнено переключение на ветку или на файл; имеет значение 1 или 0 соответственно.

Разработчики, пишущие код на Python, часто сталкиваются с проблемой, когда созданные файлы .pyc остаются после переключения между ветками. Интерпретатор иногда использует эти файлы .pyc вместо исходного файла .py. Чтобы избежать путаницы, можно удалять все файлы .pyc после каждого переключения на новую ветку с помощью следующего скрипта post-checkout:

#!/usr/bin/env python

import sys, os, re
from subprocess import check_output

# Collect the parameters
previous_head = sys.argv[1]
new_head = sys.argv[2]
is_branch_checkout = sys.argv[3]

if is_branch_checkout == "0":
    print "post-checkout: This is a file checkout. Nothing to do."
    sys.exit(0)

print "post-checkout: Deleting all '.pyc' files in working directory"
for root, dirs, files in os.walk('.'):
    for filename in files:
        ext = os.path.splitext(filename)[1]
        if ext == '.pyc':
            os.unlink(os.path.join(root, filename))

Текущий рабочий каталог хуков всегда помещается в корень репозитория, поэтому функция os.walk('.') последовательно обработает каждый файл в репозитории. После этого можно проверить расширения файлов и удалить файлы .pyc.

С помощью хука post-checkout также можно сменить рабочий каталог в зависимости от ветки, на которую вы переключились. Например, вы можете хранить все плагины за пределами основной базы кода — в ветке plugins. Если для такого плагина нужно много двоичных файлов, которые не требуются в других ветках, вы можете работать над ним только в ветке plugins.

pre-rebase

Хук pre-rebase вызывается прежде, чем будут внесены изменения в рамках команды git rebase, поэтому на данном этапе можно удобно выполнить проверки и предотвратить возможные разрушительные последствия.

Этот хук принимает два параметра: вышестоящую ветку, от которой был создан форк последовательности, и ветку, для которой выполняется перебазирование. При перебазировании текущей ветки второй параметр будет пустым. Ненулевое состояние выхода отменит операцию перебазирования.

Например, чтобы полностью запретить перебазирование в репозитории, можно использовать следующий скрипт pre-rebase:

#!/bin/sh

# Disallow all rebasing
echo "pre-rebase: Rebasing is dangerous. Don't do it."
exit 1

После каждого выполнения git rebase будет отображаться следующее сообщение:

pre-rebase: Rebasing is dangerous. Don't do it.
The pre-rebase hook refused to rebase.

В качестве усложненного примера изучите встроенный скрипт pre-rebase.sample. В нем содержится условная логика для запрета перебазирования. Скрипт проверяет, выполнялось ли объединение тематической ветки, которую вы пытаетесь перебазировать, с веткой next (предполагается, что она является главной). Если это так, перебазирование может создать серьезные проблемы, поэтому скрипт отменит операцию.

Серверные скрипты hook


Хуки на стороне сервера работают аналогично локальным и отличаются только тем, что находятся в серверных репозиториях (например, в центральном репозитории или общедоступном репозитории разработчика). Некоторые из этих хуков можно закрепить за официальным репозиторием и настроить для них отклонение определенных коммитов для внедрения нужной обязательной политики.

И наконец, рассмотрим три серверных хука:

  • pre-receive
  • Обновить
  • post-receive

Все они позволяют принять необходимые меры на различных этапах процесса git push.

Выходные данные серверных хуков передаются в консоль клиента, поэтому разработчик легко получит обратную связь. Однако следует помнить, что эти скрипты возвращают управление терминалом только после их исполнения, поэтому запускайте длительные операции с осторожностью.

pre-receive

Хук pre-receive исполняется каждый раз, когда кто-либо отправляет коммит в репозиторий с помощью git push. Этот скрипт должен всегда находиться в удаленном репозитории назначения, а не в исходном репозитории.

Этот хук запускается перед обновлением любых ссылок, поэтому на данном этапе можно удобно внедрить выбранную обязательную политику разработки. Если вас не устраивает пользователь, выполняющий отправку, изменения в коммите или формат комментария к нему, такой коммит можно отклонить. Разработчики не застрахованы от ошибок, но вы можете предотвратить попадание некорректных коммитов в официальную базу кода, отклонив их с помощью скрипта pre-receive.

Скрипт не принимает параметров, но каждая отправляемая ссылка передается ему в отдельной строке стандартного ввода в следующем формате:

<old-value> <new-value> <ref-name>

Работу хука pre-receive можно изучить в его базовом варианте, который просто считывает отправляемые ссылки и выводит их для просмотра.

#!/usr/bin/env python

import sys
import fileinput

# Read in each ref that the user is trying to update
for line in fileinput.input():
    print "pre-receive: Trying to push ref: %s" % line

# Abort the push
# sys.exit(1)

Напомним, что этот хук немного отличается от других, поскольку он получает информацию через стандартный ввод, а не в виде аргументов командной строки. Поместив вышеуказанный скрипт в каталог .git/hooks удаленного репозитория и отправив главную ветку main, вы увидите в консоли нечто подобное:

b6b36c697eb2d24302f89aa22d9170dfe609855b 85baa88c22b52ddd24d71f05db31f4e46d579095 refs/heads/main

Эти хеши SHA-1 можно использовать вместе с некоторыми низкоуровневыми командами Git для проверки вносимых изменений. Перечислим некоторые из стандартных примеров использования:

  • отклонение изменений, предполагающих перебазирование вышестоящей ветки;
  • предотвращение неускоренных слияний;
  • проверка наличия у пользователя разрешений на внесение изменений (в основном используется для централизованных рабочих процессов Git).

Если отправлено несколько ссылок, возврат ненулевого состояния из pre-receive отменит отправку каждой из них. Чтобы принимать или отклонять отдельные ветки, используйте хук update.

Обновить

Хук update вызывается после pre-receive и дает примерно тот же результат. Он также вызывается перед любыми обновлениями, однако операция выполняется отдельно для каждой отправленной ссылки. Это означает, что, если пользователь попытается отправить четыре ветки, скрипт update будет исполнен четыре раза. В отличие от pre-receive, этот хук не считывает данные из стандартного ввода, а принимает три нижеперечисленных аргумента:

1. имя обновляемой ссылки;

2. старое имя объекта, хранящееся в ссылке;

3. новое имя объекта, хранящееся в ссылке.

Скрипт update получает ту же информацию, что и pre-receive, однако может отклонить одни ссылки и допустить другие, поскольку он срабатывает отдельно для каждой ссылки.

#!/usr/bin/env python

import sys

branch = sys.argv[1]
old_commit = sys.argv[2]
new_commit = sys.argv[3]

print "Moving '%s' from %s to %s" % (branch, old_commit, new_commit)

# Abort pushing only this branch
# sys.exit(1)

Приведенный выше хук update просто отображает ветку, а также старые и новые хеши коммитов. При отправке нескольких веток в удаленный репозиторий вы увидите, что выражение print выполняется для каждой ветки.

post-receive

Хук post-receive вызывается после успешной операции push, что делает его хорошим инструментом для отправки уведомлений. Во многих рабочих процессах это более подходящий этап для запуска рассылки, чем при срабатывании post-commit, поскольку изменения находятся на общедоступном сервере, а не только на локальном компьютере пользователя. Отправка электронных сообщений другим разработчикам и запуск системы непрерывной интеграции являются распространенными примерами использования post-receive.

Скрипт не принимает параметров, но получает ту же информацию, что и pre-receive, через стандартный ввод.

Резюме


В этой статье мы научились использовать хуки Git, чтобы изменять внутреннее поведение системы и рассылать уведомления при возникновении определенных событий в репозитории. Хуки — это обычные скрипты, которые находятся в каталоге .git/hooks, поэтому их очень просто установить и настроить.

Мы также рассмотрели некоторые из наиболее распространенных локальных и серверных хуков. Это позволит нам принимать необходимые меры на всех этапах жизненного цикла разработки. Теперь мы знаем, как выполнять настраиваемые действия на каждом этапе создания коммита, а также в процессе git push. Изучив основы написания скриптов, вы сможете делать с репозиторием Git практически все, на что хватит вашей фантазии.


Поделитесь этой статьей

Рекомендуемые статьи

Добавьте эти ресурсы в закладки, чтобы изучить типы команд DevOps или получать регулярные обновления по DevOps в Atlassian.

Люди сотрудничают друг с другом, используя стену со множеством инструментов

Блог Bitbucket

Рисунок: DevOps

Образовательные программы DevOps

Демонстрация функций в демо-зале с участием экспертов Atlassian

Как инструмент Bitbucket Cloud работает с Atlassian Open DevOps

Подпишитесь на информационную рассылку по DevOps

Thank you for signing up