Написання гачка після отримання прийому для вирішення конкретної галузі


107

Ось мій поточний гачок у голому репо, що живе на сервері компанії: git push origin master Цей гачок підштовхується до Асамбле. Що мені потрібно - це натиснути лише на одну гілку (головну, в ідеалі), коли хтось натискає зміни до цієї гілки на нашому сервері, і ігнорувати натискання на інші гілки. Чи можливо вибрати гілку з голого репо і натиснути лише цю гілку на Асамблею?


Що ви маєте на увазі? git push origin masterбуде лише натискати masterгілку на originвіддалений, який я вважаю визначеним як Асамблея. Ви говорите, що запускати гачок потрібно лише тоді, коли хтось натискає на masterпротивагу feature1, чи щось подібне?
Стефан Кендалл

@Stefan Саме так. Я не зміг знайти слово, хе-хе.
Хорхе Губерте

Відповіді:


386

Гак після отримання отримує свої аргументи від stdin у формі <oldrev> <newrev> <refname>. Оскільки ці аргументи виходять із stdin, а не з аргументу командного рядка, вам потрібно використовувати readзамість $1 $2 $3.

Після прийому гачок може отримати кілька гілок одночасно (наприклад , якщо хтось - то робить git push --all), тому ми повинні обернути readв whileпетлю.

Робочий фрагмент виглядає приблизно так:

#!/bin/bash
while read oldrev newrev refname
do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    if [ "master" = "$branch" ]; then
        # Do something
    fi
done

2
"==" не працює для мене. З одним "=" працює для мене добре.
Рей

1
Вибачте, що з'явився старий потік, але я отримую помилку в операторі if. фатальний: віддалений кінець повісився повільно. помилка: помилка демультиплексора бічної смуги. Це буде відлуння гілки $ поза оператором if.
gin93r

5
@Ray, у тебе #!/bin/shзамість цього #!/bin/bash?
shuttle87

2
Один ризик, який я можу придумати, - це теги, оскільки їх назви можуть перетинатися з іменами гілок. Якщо ви шукаєте refs/heads/masterзамість refs/tags/masterвас, ви маєте гаразд. Можливо, є й інші подібні випадки, про які я не можу придумати. Це може бути хорошим питанням StackOverflow саме по собі.
pauljz

1
@pauljz Я використовую if branch=$(git rev-parse --symbolic --abbrev-ref $refname 2>/dev/null); thenтак, щоб git не скаржився, коли я видаляв гілку.
Jérôme

8

Останній параметр, який отримує гак після отримання на stdin, - це те, що ref було змінено, тому ми можемо використовувати це, щоб перевірити, чи було це значення "refs / heads / master". Трохи рубіну, схожого на те, що я використовую в гачку після отримання:

STDIN.each do |line|
    (old_rev, new_rev, ref_name) = line.split
    if ref_name =~ /master/
         # do your push
    end
end

Зауважте, що він отримує рядок для кожного виправленого листа, тому якщо ви натиснули більше, ніж просто майстер, він все одно буде працювати.


Дякуємо за приклад Рубі. Я збираюся зробити щось подібне до цього.
Лейф

6

Відповідь Стефана не спрацювала для мене, але це :

#!/bin/bash

echo "determining branch"

if ! [ -t 0 ]; then
  read -a ref
fi

IFS='/' read -ra REF <<< "${ref[2]}"
branch="${REF[2]}"

if [ "master" == "$branch" ]; then
  echo 'master was pushed'
fi

if [ "staging" == "$branch" ]; then
  echo 'staging was pushed'
fi

echo "done"

Для мене працювали гілки з простою назвою (майстер, тест тощо), але коли у мене є назва гілки: prod12 / proj250 / ropesPatch12. це не працює на добре. Чи є у вас рішення, яке може працювати з тими спеціальними персонажами?
Шачар Хамузіз Раджуан

3

Жодне з вищезазначених рішень не працювало для мене. Після багато-багато налагодження виявляється, що використання команди 'read' не працює - натомість розбір аргументів командного рядка нормально працює.

Ось точний гак після оновлення, який я тільки що успішно тестував зараз на CentOS 6.3.

#!/bin/bash

echo "determining branch"

branch=`echo $1 | cut -d/ -f3`

if [ "master" == "$branch" ]; then
    echo "master branch selected"
fi

if [ "staging" == "$branch" ]; then
    echo "staging branch selected"
fi

exec git update-server-info

ОНОВЛЕННЯ: навіть у чужій ноті попередньо отриманий гачок приймає свій вхід через stdin, тому читайте з «читати» (ух, ніколи не думав, що я це скажу). Гак після оновлення все ще працює з 1 доларом для мене.


2
Для чого це варто, вищенаведені рішення, можливо, не спрацювали, оскільки вони спеціально для post-receiveгачків, а не для post-updateгачків. Вони приймають свій внесок різними способами.
pauljz

post-receiveприймає stdin, як зазначено тут: git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
h4xnoodle

1

Відповідь від @pauljz прекрасно працює на певні гакі pre-push, але pre-commitне має доступу до цих зміннихoldrev newrev refname

Тому я створив цю альтернативну версію, яка працює для попереднього фіксації, або справді і підключення Це pre-commitгачок, який запустить huskyсценарій, якщо ми НЕ на masterгілці.

#!/bin/bash
# git 'commit' does not have access to these variables: oldrev newrev refname
# So get the branch name off the head

branchPath=$(git symbolic-ref -q HEAD) # Something like refs/heads/myBranchName
branch=${branchPath##*/}      # Get text behind the last / of the branch path

echo "Head: $branchPath";
echo "Current Branch: $branch";

if [ "master" != "$branch" ]; then

   # If we're NOT on the Master branch, then Do something
   # Original Pre-push script from husky 0.14.3

   command_exists () {
     command -v "$1" >/dev/null 2>&1
   }

   has_hook_script () {
     [ -f package.json ] && cat package.json | grep -q "\"$1\"[[:space:]]*:"
   }

   cd "frontend" # change to your project directory, if .git is a level higher

   # Check if precommit script is defined, skip if not
   has_hook_script precommit || exit 0

   # Node standard installation
   export PATH="$PATH:/c/Program Files/nodejs"

   # Check that npm exists
   command_exists npm || {
     echo >&2 "husky > can't find npm in PATH, skipping precommit script in package.json"
     exit 0
   }

   # Export Git hook params
   export GIT_PARAMS="$*"

   # Run npm script
   echo "husky > npm run -s precommit (node `node -v`)"
   echo

   npm run -s precommit || {
     echo
     echo "husky > pre-commit hook failed (add --no-verify to bypass)"
     exit 1
   }
fi

Я сподіваюся, що хтось допомагає. Ви можете легко модифікувати для своїх потреб будь-що, що знаходиться між ifта fiзаявами.


0

Я написав сценарій PHP для себе, щоб виконати цю функціональність.

https://github.com/fotuzlab/githubdump-php

Розмістіть цей файл на вашому сервері, бажано виконайте репо корінь та визначте URL у веб-куточках github. Змініть "allcommissions" у рядку 8 із назвою вашого відділення та додайте код / ​​функцію у рядку 18.

напр

function githubdump($payload_object) {
    // Write your code here.
    exec('git push origin master');
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.