среда, 11 января 2017 г.

Отмена коммита в git

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

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

Я перебрал довольно много вариантов получения разницы между ветками и остановился на команде

git rev-list HEAD..origin/branch --count

Выводом данной команды является число коммитов, на которое локальная ветка отличается от ветки в удаленном репозитории. Если ветки одинаковы - то это число 0. Если ветки в удаленном репозитории нет - то возвращается пустая строка и дополнительное сообщение о том что ветка origin/branch не найдена в удаленном репозитории.

Исходя из этих двух фактов и создадим хук для проверки перед коммитом:

#!/bin/bash
echo "Checking for changes before commit:"
### Получим свежие данные из удаленного репозитория
git fetch

### Получим название ветки на которой мы находимся
BRANCH=`git rev-parse --abbrev-ref HEAD`
### Получим число различающихся коммитов между локальной и удаленной ветками
COMCOUNT=$(git rev-list HEAD..origin/"$BRANCH" --count)

### Если разница в коммитах не 0 и не пустая строка - сообщим разработчику и завершим хук с ненулевым кодом
if [[ "$COMCOUNT" != "0" && "$COMCOUNT" != "" ]]; then
    printf "Sorry, you need to pull new changes (git pull origin $BRANCH) before commiting to branch $BRANCH\n"
    exit 1
fi

### Иначе все хорошо и можно коммитить
exit 0

Файл с хуком размещается в .git/hooks директории проекта с названием pre-commit. Файлу также необходимо установить права на исполнение.

Версия скрипта с небольшими плюшками в git/gist.

Комментариев нет:

Отправить комментарий