การเขียนเบ็ดหลังรับคอมไพล์เพื่อจัดการกับสาขาเฉพาะ


107

นี่คือตะขอปัจจุบันของฉันใน repo เปล่าที่อาศัยอยู่ในเซิร์ฟเวอร์ของ บริษัท : git push origin master ตะขอนี้จะส่งไปยัง Assembla สิ่งที่ฉันต้องการคือการผลักดันสาขาเพียงสาขาเดียว (ตามหลักการแล้ว) เมื่อมีคนผลักดันการเปลี่ยนแปลงไปยังสาขานั้นบนเซิร์ฟเวอร์ของเราและไม่สนใจการส่งไปยังสาขาอื่น เป็นไปได้ไหมที่จะเลือกสาขาจาก repo เปล่าและส่งเฉพาะสาขานั้นไปที่ Assembla


คุณหมายถึงอะไร? git push origin masterจะผลักmasterสาขาไปที่originรีโมตเท่านั้นซึ่งฉันถือว่าถูกกำหนดให้เป็น Assembla คุณกำลังบอกว่าคุณต้องเรียกเบ็ดก็ต่อเมื่อมีคนผลักmasterตรงข้ามfeature1หรืออะไรทำนองนั้น?
Stefan Kendall

@ สเตฟานเป๊ะเลย ฉันหาคำไม่เจอฮิฮิ
Jorge Guberte

คำตอบ:


386

โพสต์ได้รับเบ็ดได้รับข้อโต้แย้งจาก stdin <oldrev> <newrev> <refname>ในรูปแบบ เนื่องจากอาร์กิวเมนต์เหล่านี้มาจาก stdin ไม่ใช่จากอาร์กิวเมนต์บรรทัดคำสั่งคุณจึงต้องใช้readแทน$1 $2 $3.

เบ็ดหลังรับสามารถรับหลายสาขาพร้อมกัน (เช่นถ้ามีคนทำ a 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
"==" ใช้ไม่ได้สำหรับฉัน ด้วย single "=" ใช้ได้ผลดีกับฉัน
Ray

1
ขออภัยที่ต้องเปิดกระทู้เก่า แต่ฉันพบข้อผิดพลาดที่คำสั่ง if ร้ายแรง: ปลายรีโมทวางสายโดยไม่คาดคิด ข้อผิดพลาด: ข้อผิดพลาดในตัวถอดรหัสสัญญาณด้านข้าง มันจะสะท้อนสาขา $ นอกคำสั่ง if
gin93r

5
@ เรยมี#!/bin/shแทน#!/bin/bashมั้ย?
รถรับส่ง 87

2
ความเสี่ยงอย่างหนึ่งที่ฉันคิดได้คือแท็กเนื่องจากชื่อของพวกเขาสามารถทับซ้อนกับชื่อสาขาได้ ถ้าคุณมองหาrefs/heads/masterแทนคุณrefs/tags/masterก็น่าจะโอเค อาจมีกรณีอื่น ๆ เช่นนี้ที่ฉันคิดไม่ถึง อาจเป็นคำถาม StackOverflow ที่ดีในตัวของมันเอง
pauljz

1
@pauljz ฉันใช้if branch=$(git rev-parse --symbolic --abbrev-ref $refname 2>/dev/null); thenเพื่อให้คอมไพล์ไม่บ่นเมื่อฉันลบสาขา
Jérôme

8

พารามิเตอร์สุดท้ายที่ post-receiver hook ได้รับบน stdin คือสิ่งที่ ref ถูกเปลี่ยนดังนั้นเราจึงสามารถใช้ค่านั้นเพื่อตรวจสอบว่าค่านั้นเป็น "refs / head / master" หรือไม่ ทับทิมคล้ายกับที่ฉันใช้ในเบ็ดหลังรับ:

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

โปรดทราบว่ามันได้รับบรรทัดสำหรับการอ้างอิงแต่ละรายการที่ถูกพุชดังนั้นหากคุณผลักดันมากกว่าหลักก็จะยังใช้งานได้


ขอบคุณสำหรับตัวอย่าง Ruby ผมจะทำคล้าย ๆ กับสิ่งนี้
Leif

6

คำตอบของ Stefan ไม่ได้ผลสำหรับฉัน แต่สิ่งนี้ทำได้:

#!/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 มันไม่ได้ผลดี คุณมีวิธีแก้ไขที่สามารถทำงานร่วมกับอักขระพิเศษเหล่านั้นได้หรือไม่?
Shachar Hamuzim Rajuan

3

วิธีแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน หลังจากนั้นการดีบักจำนวนมากปรากฎว่าการใช้คำสั่ง 'อ่าน' ไม่ได้ผล แต่การแยกวิเคราะห์อาร์กิวเมนต์บรรทัดคำสั่งตามปกติจะใช้งานได้ดี

นี่คือเบ็ดหลังการอัปเดตที่แน่นอนที่ฉันเพิ่งทดสอบสำเร็จใน 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 ดังนั้นจึงอ่านด้วย 'read' (ว้าวไม่เคยคิดว่าจะพูดอย่างนั้น) เบ็ดหลังการอัปเดตยังคงใช้งานได้กับ $ 1 สำหรับฉัน


2
สำหรับสิ่งที่คุ้มค่าโซลูชันข้างต้นอาจไม่ได้ผลเนื่องจากมีไว้สำหรับpost-receiveตะขอโดยเฉพาะไม่ใช่post-updateตะขอ พวกเขารับข้อมูลในรูปแบบต่างๆ
pauljz

post-receiveใช้ stdin ตามที่ระบุไว้ที่นี่: git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
h4xnoodle

1

คำตอบจาก @pauljz ใช้งานได้ดีสำหรับ git hook บางตัวเช่น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

โฮสต์ไฟล์นี้บนเซิร์ฟเวอร์ของคุณโดยเฉพาะอย่างยิ่ง repo root และกำหนด url ใน github webhooks เปลี่ยน 'allcommits' ในบรรทัดที่ 8 ด้วยชื่อสาขาของคุณและเพิ่มรหัส / ฟังก์ชันของคุณที่บรรทัด 18

เช่น

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

0

วิธีง่ายๆในการgit hookเขียน

read refname
echo $refname

ง่าย - ข้อมูลเพิ่มเติมเกี่ยวกับระบบเชื่อมโยงที่ยอดเยี่ยมนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.