Pisanie podpięcia git po odbiorze w celu obsługi określonej gałęzi

107

Oto mój obecny punkt zaczepienia w gołym repozytorium, który znajduje się na serwerze firmy: git push origin master To przechwytywanie wypycha do Assembla. Potrzebuję tylko jednej gałęzi (najlepiej głównej), gdy ktoś wypycha zmiany do tej gałęzi na naszym serwerze i ignoruje wypychanie do innych gałęzi. Czy można wybrać gałąź z samego repozytorium i przekazać tylko tę gałąź do Assembla?

Jorge Guberte
źródło
Co masz na myśli? git push origin masterprzesyła tylko mastergałąź do originpilota, który, jak zakładam, jest zdefiniowany jako Assembla. Czy mówisz, że musisz aktywować hak tylko wtedy, gdy ktoś popycha master, a nie feature1, czy coś w tym stylu?
Stefan Kendall,
@Stefan Dokładnie to. Nie mogłem znaleźć słowa, hehe.
Jorge Guberte

Odpowiedzi:

386

Punkt zaczepienia po odbiorze pobiera argumenty ze standardowego wejścia w postaci <oldrev> <newrev> <refname>. Ponieważ te argumenty pochodzą ze stdin, a nie z argumentu wiersza poleceń, należy użyć readzamiast $1 $2 $3.

Hak po odbiorze może otrzymać wiele gałęzi jednocześnie (na przykład jeśli ktoś zrobi a git push --all), więc musimy również zawinąć readw whilepętlę.

Działający fragment wygląda mniej więcej tak:

#!/bin/bash
while read oldrev newrev refname
do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    if [ "master" = "$branch" ]; then
        # Do something
    fi
done
pauljz
źródło
2
„==” nie działa dla mnie. Z pojedynczym "=" dobrze mi pasuje.
Ray
1
Przepraszam, że wyświetlam stary wątek, ale w instrukcji if pojawia się błąd. fatalny: zdalny koniec niespodziewanie się rozłączył. błąd: błąd w demultiplekserze pasma bocznego. Powoduje to odbicie gałęzi $ poza instrukcją if.
gin93r
5
@Ray, czy masz #!/bin/shzamiast #!/bin/bash?
transfer: 87
2
Jednym z zagrożeń, które przychodzą mi do głowy, są tagi, ponieważ ich nazwy mogą pokrywać się z nazwami gałęzi. Jeśli szukasz refs/heads/masterzamiast refs/tags/masterciebie, powinno być dobrze. Mogą istnieć inne takie skrajne przypadki, o których nie mogę myśleć. Może to być dobre pytanie dotyczące StackOverflow samo w sobie.
pauljz
1
@pauljz używam if branch=$(git rev-parse --symbolic --abbrev-ref $refname 2>/dev/null); then, aby git nie narzekał, gdy usuwam gałąź.
Jérôme
8

Ostatnim parametrem, który podpięcie po odbiorze otrzymuje na stdin, jest zmiana ref, więc możemy go użyć do sprawdzenia, czy ta wartość to „refs / heads / master”. Trochę rubinu podobnego do tego, którego używam w hooku po odbiorze:

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

Zauważ, że dostaje linię dla każdego wypchniętego ref, więc jeśli pchnąłeś więcej niż tylko master, nadal będzie działać.

ebneter
źródło
Dzięki za przykład Rubiego. Zrobię coś podobnego do tego.
Leif
6

Odpowiedź Stefana nie działa dla mnie, ale to tak:

#!/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"
Dean Rather
źródło
Pracowałem dla mnie dla gałęzi o prostej nazwie (master, test itp.), Ale kiedy mam taką nazwę oddziału: prod12 / proj250 / ropesPatch12. to nie działa dobrze. Czy masz rozwiązanie, które może działać z tymi znakami specjalnymi?
Shachar Hamuzim Rajuan
3

Żadne z powyższych rozwiązań nie zadziałało dla mnie. Po wielu, wielu debugowaniu okazuje się, że użycie polecenia „read” nie działa - zamiast tego parsowanie argumentów wiersza poleceń w zwykły sposób działa dobrze.

Oto dokładny haczyk po aktualizacji, który właśnie pomyślnie przetestowałem teraz na 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

AKTUALIZACJA: jeszcze dziwniejsza uwaga, hak przed odbiorem pobiera dane wejściowe przez stdin, dlatego czytaj za pomocą „czytaj” (wow, nigdy nie sądziłem, że to powiem). Haczyk po aktualizacji nadal działa z 1 $ dla mnie.

razvan
źródło
2
Mimo wszystko powyższe rozwiązania mogą nie zadziałać, ponieważ są przeznaczone specjalnie do post-receivehaczyków, a nie post-updatehaczyków. Przyjmują swój wkład na różne sposoby.
pauljz
post-receiveprzyjmuje stdin, jak wspomniano tutaj: git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
h4xnoodle
1

Odpowiedź z @pauljz działa dobrze w przypadku niektórych haków git, takich jak pre-push, ale pre-commitnie ma dostępu do tych zmiennycholdrev newrev refname

Więc stworzyłem tę alternatywną wersję, która działa z pre-commitem lub naprawdę i hookiem. To jest pre-commithaczyk, który uruchomi huskyskrypt, jeśli NIE jesteśmy w mastergałęzi.

#!/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

Mam nadzieję, że to komuś pomoże. Możesz łatwo modyfikować do swoich potrzeb wszystko pomiędzy stwierdzeniami ifi fi.

TetraDev
źródło
0

Napisałem dla siebie skrypt PHP, aby wykonać tę funkcję.

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

Umieść ten plik na swoim serwerze, najlepiej repozytorium root i zdefiniuj adres URL w webhookach github. Zmień 'allcommits' w linii 8 na nazwę swojej gałęzi i dodaj swój kod / funkcję w linii 18.

na przykład

function githubdump($payload_object) {
    // Write your code here.
    exec('git push origin master');
}
fotuzlab
źródło
0

Proste podejście, na git hookpiśmie

read refname
echo $refname

Proste - więcej informacji na temat tego wspaniałego systemu podpinania linków

Haris Krajina
źródło