ใส่ git hooks ลงในที่เก็บ


198

มันถือว่าเป็นแนวปฏิบัติที่ไม่ดีหรือไม่ - ใส่.git/hooksลงในที่เก็บโครงการ (ใช้ symlink เป็นต้น) ถ้าใช่เป็นวิธีที่ดีที่สุดในการส่ง hooks แบบเดียวกันกับผู้ใช้ git ที่แตกต่างกันคืออะไร

คำตอบ:


143

โดยทั่วไปฉันเห็นด้วยกับ Scytale พร้อมคำแนะนำเพิ่มเติมสองสามคำว่าคุ้มค่ากับคำตอบที่แยกต่างหาก

ขั้นแรกคุณควรเขียนสคริปต์ที่สร้าง symlink ที่เหมาะสมโดยเฉพาะหาก hooks เหล่านี้เกี่ยวกับการบังคับใช้นโยบายหรือการสร้างการแจ้งเตือนที่มีประโยชน์ ผู้คนจะมีแนวโน้มที่จะใช้ hooks หากพวกเขาสามารถพิมพ์ได้bin/create-hook-symlinksมากกว่าที่พวกเขาต้องทำเอง

ประการที่สองการเชื่อมโยง hooks โดยตรงป้องกันผู้ใช้จากการเพิ่ม hooks ส่วนตัวของพวกเขาเอง ตัวอย่างเช่นฉันชอบ hook pre-commit ตัวอย่างซึ่งทำให้แน่ใจว่าฉันไม่มีข้อผิดพลาดในช่องว่าง วิธีที่ยอดเยี่ยมในการทำเช่นนี้ก็คือการวางสคริปต์ของฮุกเกอร์ใน repo ของคุณและเชื่อมโยงhooks ทั้งหมดเข้ากับมัน wrapper สามารถตรวจสอบ$0(สมมติว่ามันเป็นสคริปต์ทุบตี; เทียบเท่าเหมือนargv[0]อย่างอื่น) ที่จะคิดว่าเบ็ดมันถูกเรียกว่าเป็นแล้วเรียกเบ็ดที่เหมาะสมภายใน repo ของคุณเช่นเดียวกับเบ็ดของผู้ใช้ที่เหมาะสมซึ่งจะต้องเปลี่ยนชื่อ ผ่านการขัดแย้งทั้งหมดไปยังแต่ละ ตัวอย่างด่วนจากหน่วยความจำ:

#!/bin/bash
if [ -x $0.local ]; then
    $0.local "$@" || exit $?
fi
if [ -x tracked_hooks/$(basename $0) ]; then
    tracked_hooks/$(basename $0) "$@" || exit $?
fi

สคริปต์การติดตั้งจะย้าย hooks ที่มีอยู่ล่วงหน้าทั้งหมดไปที่ด้านข้าง (ต่อท้าย.localชื่อ) และเชื่อมโยงชื่อ hook ที่รู้จักทั้งหมดไปยังสคริปต์ด้านบน:

#!/bin/bash
HOOK_NAMES="applypatch-msg pre-applypatch post-applypatch pre-commit prepare-commit-msg commit-msg post-commit pre-rebase post-checkout post-merge pre-receive update post-receive post-update pre-auto-gc"
# assuming the script is in a bin directory, one level into the repo
HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks

for hook in $HOOK_NAMES; do
    # If the hook already exists, is executable, and is not a symlink
    if [ ! -h $HOOK_DIR/$hook -a -x $HOOK_DIR/$hook ]; then
        mv $HOOK_DIR/$hook $HOOK_DIR/$hook.local
    fi
    # create the symlink, overwriting the file if it exists
    # probably the only way this would happen is if you're using an old version of git
    # -- back when the sample hooks were not executable, instead of being named ____.sample
    ln -s -f ../../bin/hooks-wrapper $HOOK_DIR/$hook
done

6
ฉันเพิ่มchmod +x .git/hooks/*ให้คุณbin/create-hook-symlinks ทำงาน
guneysus

6
@guneysus คุณไม่จำเป็นต้องทำเช่นนั้นเพราะ hooks ควรใช้งานได้แล้ว (ควรทำการตรวจสอบด้วยวิธีนี้) และลิงก์ไม่ต้องการการอนุญาตพิเศษใด ๆ เพียงแค่ไฟล์ที่พวกเขาเชื่อมโยงไปถึง
Cascabel

13
HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooksวิธีที่ดีกว่าที่จะได้รับผบเบ็ดคือ
อาร์โนลด์แดเนียลส์

2
ฉันได้รวบรวมระบบที่เรียบง่ายโดยใช้สิ่งนี้เพื่อจัดการ hooks ในโครงการของฉัน: ell.io/tt$Paws.js/blob/Master/Scripts/install-git-hooks.sh
ELLIOTTCABLE

6
ฉันเอาของจำเป็นมาใส่ไว้ใน repo github.com/sjungwirth/githooks
Scott Jungwirth

111

ไม่การวางลงในพื้นที่เก็บข้อมูลเป็นเรื่องปกติฉันขอแนะนำให้ทำเช่นนั้น (หากมีประโยชน์สำหรับผู้อื่นเช่นกัน) ผู้ใช้ต้องเปิดใช้งานอย่างชัดเจน (ดังที่คุณพูดเช่นโดยการเชื่อมโยง) ซึ่งอยู่ในมือข้างหนึ่งของความเจ็บปวดเล็กน้อย แต่ปกป้องผู้ใช้ในอีกทางหนึ่งจากการใช้รหัสโดยพลการโดยไม่ได้รับความยินยอม


13
จะเกิดอะไรขึ้นถ้ามันเป็นนโยบายของ บริษัท รหัสก็ไม่ได้ "โดยพลการ" นี่เป็นรหัสที่จำเป็นดังนั้นนี่จะถือว่าเป็นข้อ จำกัด ใน GIT เนื่องจากไม่มีไดเรกทอรีอื่น (ที่กำหนดไว้ล่วงหน้า) ซึ่งถูกติดตามซึ่งยังได้รับ ดำเนินการพร้อมกับ hooks ปกติ
Tobias Hagenbeek

14
การนำเสนอ hooks โดยอัตโนมัติเป็นปัญหาด้านความปลอดภัยฉันดีใจที่ Git ไม่ทำโดยตรง - เพื่อบังคับใช้นโยบายของทีม / บริษัท ใช้ hooks ด้านเซิร์ฟเวอร์หรือให้ผู้ใช้ตัดสินใจเปิดใช้งานด้วยตนเองตามที่ @scy อธิบาย :)
ทำเครื่องหมาย K Cowan

4
"ปกป้องผู้ใช้ [... ] จากการเรียกใช้รหัสโดยอำเภอใจโดยไม่ได้รับความยินยอม" หากผู้พัฒนาอยากแนะนำให้คุณแนะนำ (symlinking) ผู้อื่นสามารถเปลี่ยน hook ได้และเรียกใช้ "รหัสที่กำหนดเองโดยไม่ได้รับความยินยอม"
MiniGod

24
MiniGod: แน่นอน หากคุณหวาดระแวงอย่างเพียงพอคุณสามารถคัดลอก hooks แทนที่จะทำการเชื่อมโยงจากนั้นตรวจสอบพวกเขาแล้วเปิดใช้งานพวกเขาเท่านั้น อย่างไรก็ตามที่เก็บ Git ส่วนใหญ่จะต้องมีซอร์สโค้ดซึ่งจะถูกเรียกใช้บนเครื่องของผู้ใช้ดังนั้นคุณมีแนวโน้มที่จะเรียกใช้การเปลี่ยนแปลงอย่างต่อเนื่องและไม่ได้ตรวจสอบโค้ด แต่ใช่คุณมีประเด็น ;)
scy

47

ทุกวันนี้คุณสามารถทำสิ่งต่อไปนี้เพื่อตั้งค่าไดเรกทอรีที่อยู่ภายใต้การควบคุมเวอร์ชันให้เป็นไดเรกทอรี git hooks ของคุณเช่นMY_REPO_DIR/.githooksจะเป็น

git config --local core.hooksPath .githooks/

ยังไม่สามารถบังคับใช้ได้โดยตรง แต่ถ้าคุณเพิ่มบันทึกย่อใน README ของคุณ (หรืออะไรก็ตาม) สิ่งนี้ต้องการความพยายามขั้นต่ำในส่วนของนักพัฒนาแต่ละคน


3
เคล็ดลับหนึ่งที่ฉันพบในviget.com/articles/two-ways-to-share-git-hooks-with-your-teamคือการตั้งค่าตัวเลือกจาก Makefile / CMake config / อะไรก็ตาม
Julius Bullinger

6

จากhttp://git-scm.com/docs/git-init#_template_directoryคุณสามารถใช้หนึ่งในกลไกเหล่านี้เพื่ออัปเดต. git / hooks dir ของ repo git แต่ละรายการที่สร้างขึ้นใหม่:

ไดเรกทอรีแม่แบบมีไฟล์และไดเรกทอรีที่จะถูกคัดลอกไปยัง $ GIT_DIR หลังจากสร้างแล้ว

ไดเรกทอรีเทมเพลตจะเป็นหนึ่งในสิ่งต่อไปนี้ (เรียงตามลำดับ):

  • อาร์กิวเมนต์ที่กำหนดด้วยตัวเลือก - เทมเพลท;

  • เนื้อหาของตัวแปรสภาพแวดล้อม $ GIT_TEMPLATE_DIR

  • ตัวแปรการกำหนดค่า init.templateDir หรือ

  • ไดเรกทอรีแม่แบบเริ่มต้น: / usr / share / git-core / templates


5

เก็บในโครงการและติดตั้งในบิลด์

ตามที่คนอื่น ๆ ระบุไว้ในคำตอบหากตะขอของคุณมีความเฉพาะเจาะจงสำหรับโครงการเฉพาะของคุณให้รวมพวกเขาไว้ในโครงการด้วยตัวเองจัดการโดย git ฉันจะใช้สิ่งนี้ให้ดียิ่งขึ้นและบอกว่าเนื่องจากเป็นแนวปฏิบัติที่ดีในการสร้างโปรเจ็กต์ของคุณโดยใช้สคริปต์หรือคำสั่งเดียวตะขอของคุณควรถูกติดตั้งระหว่างการ build

ฉันเขียนบทความเกี่ยวกับการจัดการ hooks gitหากคุณสนใจที่จะอ่านเกี่ยวกับเรื่องนี้ในเชิงลึกมากขึ้น

Java & Maven

ข้อจำกัดความรับผิดชอบฉบับเต็ม; ฉันเขียนปลั๊กอิน Maven ตามที่อธิบายไว้ด้านล่าง

หากคุณจัดการการจัดการการสร้างด้วย Maven สำหรับโครงการ Java ของคุณปลั๊กอิน Maven ต่อไปนี้จะจัดการติดตั้ง hooks จากตำแหน่งในโครงการของคุณ

https://github.com/rudikershaw/git-build-hook

ใส่ตะขอ Git ของคุณทั้งหมดลงในไดเรกทอรีในโครงการของคุณจากนั้นกำหนดค่าpom.xmlให้รวมการประกาศปลั๊กอินเป้าหมายและการกำหนดค่าต่อไปนี้

<build>
  <plugins>
    <plugin>
      <groupId>com.rudikershaw.gitbuildhook</groupId>
      <artifactId>git-build-hook-maven-plugin</artifactId>
      <configuration>
        <gitConfig>
          <!-- The location of the directory you are using to store the Git hooks in your project. -->
          <core.hooksPath>hooks-directory/</core.hooksPath>
        </gitConfig>
      </configuration>
      <executions>
        <execution>
          <goals>       
            <!-- Sets git config specified under configuration > gitConfig. -->
            <goal>configure</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
      <!-- ... etc ... -->
  </plugins>
</build>

เมื่อคุณเรียกใช้งานบิลด์โปรเจ็กต์ของคุณปลั๊กอินจะกำหนดค่า git เพื่อให้ hooks ออกจากไดเรกทอรีที่ระบุ นี่จะเป็นการตั้งค่า hooks ในไดเรกทอรีนั้นอย่างมีประสิทธิภาพสำหรับทุกคนที่ทำงานในโครงการของคุณ

JavaScript & NPM

สำหรับ NPM มีการขึ้นต่อกันเรียกว่าฮัสกี้ซึ่งอนุญาตให้คุณติดตั้ง hooks รวมถึงที่เขียนใน JavaScript

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "npm test",
      "pre-push": "npm test",
      "...": "..."
    }
  }
}

คนอื่น ๆ

นอกจากนี้ยังมีการคอมมิตล่วงหน้าสำหรับโครงการ Python, Overcommitสำหรับโครงการ Ruby และLefthookสำหรับโครงการRuby หรือ Node


1
ขอบคุณที่สร้างปลั๊กอินนี้มันทำให้การรวมไฟล์การคอมมิทล่วงหน้าของฉันง่ายมาก
Michiel Bugher


1

นี่คือสคริปต์ add-git-hook.sh ซึ่งคุณสามารถจัดส่งเป็นไฟล์ปกติในที่เก็บและสามารถดำเนินการต่อท้าย git hook ไปยังไฟล์สคริปต์ได้ ปรับ hook ที่จะใช้ (pre-commit, post-commit, pre-push, ฯลฯ ) และคำจำกัดความของ hook ใน cat heredoc

#!/usr/bin/bash
# Adds the git-hook described below. Appends to the hook file
# if it already exists or creates the file if it does not.
# Note: CWD must be inside target repository

HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks
HOOK_FILE="$HOOK_DIR"/post-commit

# Create script file if doesn't exist
if [ ! -e "$HOOK_FILE" ] ; then
        echo '#!/usr/bin/bash' >> "$HOOK_FILE"
        chmod 700 "$HOOK_FILE"
fi

# Append hook code into script
cat >> "$HOOK_FILE" <<EOF

########################################
# ... post-commit hook script here ... #
########################################

EOF

สคริปต์นี้อาจเหมาะสมที่จะมีสิทธิ์ใช้งานหรือผู้ใช้สามารถเรียกใช้โดยตรง ฉันใช้สิ่งนี้เพื่อดึงคอมไพล์บนเครื่องอื่นโดยอัตโนมัติหลังจากที่ฉันยืนยัน

แก้ไข - ฉันตอบคำถามง่ายขึ้นซึ่งไม่ใช่สิ่งที่ถูกถามและไม่ใช่สิ่งที่ OP กำลังมองหา ฉันเลือกใช้กรณีและข้อโต้แย้งสำหรับการจัดส่งสคริปต์เบ็ดใน repo กับการจัดการพวกเขาภายนอกในความคิดเห็นด้านล่าง หวังว่าจะเป็นสิ่งที่คุณกำลังมองหา


ฉันซาบซึ้งในความพยายามของคุณและเชื่อว่ามีข้อมูลที่มีค่าอยู่ที่นี่ - ไม่ตอบคำถามที่ระบุ
shabunc

ในความคิดของฉันหาก hooks เป็นพิเศษสำหรับพื้นที่เก็บข้อมูลเฉพาะหรือเป็นส่วนประกอบสำคัญของเวิร์กโฟลว์ที่ใช้แล้วพวกเขาอยู่ในพื้นที่เก็บข้อมูลเป็นไฟล์ มันยากที่จะนำพวกเขาไปที่อื่นโดยไม่สร้างปัญหามากกว่าที่จะแก้ปัญหา คุณสามารถจัดเก็บ hooks ทั่วไปในที่เก็บของมันเองหรือบนไดรฟ์ที่ใช้ร่วมกันซึ่งสามารถทำให้โครงการ repo ส่งเสียงดังเอี้ยสะอาด แต่ค่าใช้จ่ายของการปฏิบัติน้อยมาก ฉันเห็นด้วยกับผู้ใช้รายอื่นในการบอกว่าขอเพิ่มต้องง่าย ลิงก์สัญลักษณ์อาจสร้างการพึ่งพาที่ไม่จำเป็นในระบบหรือโครงสร้างของไฟล์
mathewguest

นอกจากนี้ลิงก์สัญลักษณ์ยังทำลายความสามารถของผู้ใช้ในการเพิ่มตะขอของตัวเอง ไดเรกทอรี. git / hooks ไม่ได้รับการติดตามดังนั้นแหล่งที่มาควรเริ่มต้นในที่เก็บและทำให้เป็นวิธีในสคริปต์ hooks ไม่ใช่วิธีอื่น ฉันคิดว่าการโต้แย้งจะเป็นไปได้ว่า hooks git นั้นเกี่ยวข้องกับเวิร์กโฟลว์หรือทีมมากกว่าโครงการดังนั้นจึงไม่ได้อยู่ในที่เก็บ ขึ้นอยู่กับกรณีการใช้งานเฉพาะของคุณคุณโอเคมากขึ้นด้วยที่อาจก่อให้เกิดมลพิษในที่เก็บ git ที่มี hooks ที่เกี่ยวข้องน้อยหรือคุณต้องการนำความซับซ้อนมาวางไว้ที่อื่นหรือไม่
mathewguest

1

สำหรับโปรเจ็กต์ PHP ที่ใช้ Composer คุณสามารถแจกจ่ายให้กับวิศวกรโดยอัตโนมัติ นี่คือตัวอย่างสำหรับ hooks การผูกมัดล่วงหน้าและ commit-msg

สร้างhooksโฟลเดอร์จากนั้นใน composer.json ของคุณ:

 },
 "scripts": {
     "post-install-cmd": [
         "cp -r 'hooks/' '.git/hooks/'",
         "php -r \"copy('hooks/pre-commit', '.git/hooks/pre-commit');\"",
         "php -r \"copy('hooks/commit-msg', '.git/hooks/commit-msg');\"",
         "php -r \"chmod('.git/hooks/pre-commit', 0777);\"",
         "php -r \"chmod('.git/hooks/commit-msg', 0777);\"",
     ],

จากนั้นคุณสามารถอัปเดตพวกเขาขณะที่โครงการดำเนินต่อไปเนื่องจากทุกคนทำงานcomposer installเป็นประจำ


0

คุณสามารถใช้วิธีการแก้ปัญหาการจัดการก่อนกระทำการจัดการเบ็ดเหมือนก่อนกระทำ หรือวิธีการแก้ปัญหาที่ส่วนกลางในฝั่งเซิร์ฟเวอร์คอมไพล์ตะขอเช่นDatree.io มันมีนโยบายในตัวเช่น:

  1. ตรวจจับและป้องกันการรวมความลับการผสานความลับ
  2. บังคับใช้การกำหนดค่าผู้ใช้ Gitที่เหมาะสมการกำหนดค่าใช้
  3. บังคับใช้การรวมตั๋ว Jira - พูดถึงหมายเลขตั๋วในชื่อคำขอดึง / ส่งข้อความ

มันจะไม่แทนที่ hooks ทั้งหมดของคุณ แต่อาจช่วยให้นักพัฒนาของคุณเห็นได้ชัดเจนที่สุดโดยไม่ต้องมีการกำหนดค่าให้ติดตั้ง hooks ลงในคอมพิวเตอร์ / นักพัฒนาทุกคน

ข้อจำกัดความรับผิดชอบ: ฉันเป็นหนึ่งในผู้ก่อตั้ง Datrees


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