Как я могу заставить коммит от пользователя prod иметь --author - PullRequest
4 голосов
/ 12 октября 2019

На моем рабочем месте мы используем git для контроля версий в Linux (CENTOS 7). У нас есть идентификаторы пользователей, но также есть несколько идентификаторов продуктов, которые мы можем олицетворять.

Поскольку мы слабые, мы позволили идентификаторам продуктов фиксировать и вставлять репозитории, как правило, для практичности, когда мы исправляем ошибки. вопрос. Мы должны использовать --author при этом, но время от времени забываем.

Есть ли способ принудительно использовать --author при использовании определенных пользователей Prod?

1 Ответ

5 голосов
/ 12 октября 2019

Как только коммит сделан, он никогда не может быть изменен. Но у вас есть возможность не отправлять коммит, и другой вариант: отказаться от принятия коммит. Таким образом, здесь есть ровно три варианта:

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

  • Проверьте перед отправкой. Если вы используете git push для отправки коммитов из Git Repository A в Git Repository B, отправляющий Git (Git A) выполнит свой предварительный push-прием после вызова Git B, но перед передачей коммитовGit B. В это время вы можете, в ловушке перед нажатием, проверить коммиты: если они не той формы, которая вам нравится, не отправляйте их.

  • Проверяйте перед получением, в хуке предварительного получения или обновления. Это требует действий на самом сервере. Поскольку вы упомянули Bitbucket, см. их страницу о серверных хуках . Крюк предварительного получения может отклонить git push (все это);хук обновления может отклонить одну часть git push (одно обновление имени).

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

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

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

Написание хука перед фиксацией

Хук перед фиксацией относительно прост: Git будет искать внутри .git/hooks/ файлпо имени pre-commit. Если этот файл существует и является исполняемым , git commit запустит его. Этот файл - просто программа, написанная на любом языке, который вам нравится: Python, Perl, sh / bash, C, C ++, Java, Go, что угодно. Если вы пишете на интерпретируемом языке, убедитесь, что системный вызов ОС exec вызовет интерпретатор. То есть для сценария /bin/sh в первой строке файла читается #! /bin/sh, чтобы системный вызов exec мог запустить его напрямую, а затем chmod +x файл.

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

В вашем конкретном случае вам в некоторой степени повезло: ловушка запускается после Git устанавливает GIT_AUTHOR_NAME и другие переменные среды Git (это основано на тестировании с Git 2.21; помните, что CentOS Git по умолчанию может быть устаревшим, поэтому проверьте версию Git и убедитесь, что она работает в вашей версии, или обновите, если необходимо). Например, вот несколько глупый хук перед фиксацией, который я написал, чтобы проверить это:

$ cat .git/hooks/pre-commit
#! /bin/sh
env | grep GIT | sed 's/@/ /'
exit 1

Этот хук перед фиксацией просто запрещает каждый коммит после отображения всех переменных средыв них есть строка GIT (и удаление @ для сокращения спама после публикации этого сообщения). Так что теперь (после chmod +x):

$ git commit
GIT_EXEC_PATH=/usr/local/libexec/git-core
GIT_INDEX_FILE=.git/index
GIT_AUTHOR_NAME=Chris Torek
GIT_PREFIX=
GIT_AUTHOR_EMAIL=chris.torek gmail.com
GIT_AUTHOR_DATE= 1570904668 -0700

или:

$ git commit --author='A U Thor <thor@example.com>'
GIT_EXEC_PATH=/usr/local/libexec/git-core
GIT_INDEX_FILE=.git/index
GIT_AUTHOR_NAME=A U Thor
GIT_PREFIX=
GIT_AUTHOR_EMAIL=thor example.com
GIT_AUTHOR_DATE= 1570904927 -0700

Теперь должно быть очевидно, как проверить настройку «автора». Вы можете сделать это всегда или только в том случае, если id говорит, что вы работаете как «продвинутый пользователь» (что бы это ни значило на практике).

Написание ловушки предварительного нажатия

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

Как и раньше, ваш хук может быть написан на любом языке, который вам нравится, хотя сценарии оболочки, как правило, здесь будут самыми простыми. Его задача - проверить уже существующие коммиты, убедиться, что вы готовы отправить их в Git-получатель, и выйти из 0, если это так. Если ловушка предварительного нажатия выходит из нуля, весь push прерывается.

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

<local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF

(как указано в документация githooks ).

К сожалению, во время git push идентификатор удаленного хэша sha-1 может быть или не быть в локальном хранилище. Если это не так, единственное, что вы знаете об этом, - это то, что если и вы, и другой Git позволяют завершить push, некоторые коммиты будут потеряны с удаленной ссылки. Таким образом, в этом случае вы можете прервать push-запрос, поскольку он будет успешным, только если пользователь использовал --force и git push --force, что часто нежелательно. (Если пользователю действительно необходимо форсировать этот толчок, он / она / они / что-либо может использовать git push --n-verify -f, чтобы обойти крюк предварительного толкания тоже ... или они могут сначала запустить git fetch, так что фиксация существует локально.)

Убедившись, что хеш-идентификатор удаленного устройства существует локально, так что вы можете проверять исходящие коммиты (и / или коммиты, которые должны быть отброшены), вы можете использовать git rev-list для получения хеш-идентификаторов таких коммитов.

В качестве полностью непроверенного примера рассмотрим этот бит сценария оболочки:

while read localref localhash remoteref remotehash; do
    case $remoteref in
    refs/heads/*)
        remotebranch=${localref#refs/heads/};;
    *)
        echo "pushing to non-branch $remoteref - not checking this one"
        continue;;
    esac
    if ! git rev-parse --quiet --verify $remotehash >/dev/null; then
        echo "push to branch $remotebranch aborted"
        echo "need commits from them; please run git fetch first"
        exit 1
    fi
    git rev-list $remotehash..$remotehash | while read hash; do
        if ! check-commit $hash; then
            echo "git push to branch $remotebranch aborted: commit $hash failed check"
            exit 1
        fi
    done
    n_removed=$(git rev-list --count $localhash..$remotehash)
    if [ $n_removed -ne 0 ]; then
        echo "warning: force push discards $n_removed commits from $remotebranch"
    fi
done

Если этот фрагмент сценария оболочки верный (помните, он не проверен), он все равно требует написания собственногофункция оболочки check-commit. Эта функция должна проверять коммит, который будет отправлен, и убедиться, что вы готовы отправить его другому Git.

Запись перехвата предварительного приема на стороне сервера

Еслиу вас есть полный контроль над сервером Git, вы можете написать свой собственный хук предварительного получения. Как и прежде, это просто исполняемая программа, написанная на любом понравившемся вам языке, которую ОС может вызывать с помощью системного вызова exec, хранящегося в файле с именем .git/hooks/pre-receive.

Как и при предварительном нажатиивыше, ловушка предварительного получения получает свой ввод в виде последовательности строк на своем стандартном входе, по одной на запрошенное обновление ссылки. Ваша задача - прочитать все строки, убедиться, что все входящие коммиты разрешены, и если да, выйти из ноля. Если некоторые коммиты должны быть отклонены, вы просто выходите из нуля. очень хорошая идея распечатать почему вы отклоняете коммиты, так что тот, кто работает git push видит ваш вывод, с префиксом слова remote:, так чтоони могут сказать , почему их толчок отклонен. Но просто выход из ненулевого состояния приведет к отклонению всего push.

Написание ловушки обновления на стороне сервера

Если вы имеете полный контроль над сервером Git, вы можете написать свою собственную ловушку обновления. Как и прежде, это просто исполняемая программа, написанная на любом понравившемся вам языке, которую ОС может вызывать с помощью системного вызова exec, хранящегося в файле с именем .git/hooks/update.

* 114. 3 * Хук обновления получает свои аргументы как фактические аргументы. Порядок аргументов отличается от порядка строк, передаваемых в ловушку предварительного получения. Обратитесь к документации githooks для деталей. Как и в случае с ловушкой предварительного получения, ваша задача - проверить предлагаемое эталонное обновление и выйти из 0, чтобы разрешить обновление, или ненулевое, чтобы отклонить его. В отличие от ловушки предварительного получения, отклонение одного обновления автоматически не отклоняет другие. Как и ловушка предварительного получения, очень хорошая идея напечатать сообщение о , почему обновление отклонено.
...