2010-03-26 16 views
23

सीवीएस से आ रहा है, हमारे पास एक नीति है जो संदेशों को एक बग संख्या (सरल प्रत्यय "... [99 99]" ​​के साथ टैग किया जाना चाहिए)। एक सीवीएस स्क्रिप्ट यह जांचता है कि संदेश प्रतिबद्ध नहीं होने पर प्रतिबद्धता को अस्वीकार करता है और अस्वीकार करता है।हम पुश के लिए प्रतिबद्ध संदेश कैसे सत्यापित करते हैं?

गिट हुक प्रतिबद्ध-संदेश डेवलपर पक्ष पर करता है लेकिन हमें स्वचालित सिस्टम जांचने और हमें इसकी याद दिलाने में मदद मिलती है।

एक गिट पुश के दौरान, प्रतिबद्ध-संदेश नहीं चलाया जाता है। क्या धक्का के दौरान कोई और हुक है जो प्रतिबद्ध संदेशों की जांच कर सकता है?

हम गिट पुश के दौरान प्रतिबद्ध संदेश कैसे सत्यापित करते हैं?

उत्तर

23

अद्यतन हुक

आप हुक के बारे में पता का उपयोग करना - कृपया, उनके बारे में documentation पढ़ें! जो हुक आप शायद चाहते हैं वह अद्यतन है, जो एक बार प्रति रेफरी चलाया जाता है। (प्री-प्राप्त हुक पूरे धक्का के लिए एक बार चलाया जाता है) एसओ पर पहले से ही इन हुकों के बारे में बहुत सारे प्रश्न और उत्तर हैं; आप जो करना चाहते हैं उसके आधार पर, शायद आपको हुक लिखने के बारे में मार्गदर्शन मिल सकता है यदि आपको इसकी आवश्यकता है।

बल देने के लिए कि यह वास्तव में संभव, डॉक्स से एक उद्धरण है:

यह हुक सुनिश्चित करें कि ऑब्जेक्ट नाम एक वस्तु के लिए प्रतिबद्ध है कि है एक है बनाने के द्वारा कुछ refs पर मजबूर अद्यतन को रोकने के लिए इस्तेमाल किया जा सकता पुराने ऑब्जेक्ट नाम द्वारा नामित प्रतिबद्ध वस्तु के वंशज। यही है, "केवल फास्ट फॉरवर्ड" नीति को लागू करने के लिए।

इसका उपयोग पुराने .. नई स्थिति को लॉग करने के लिए भी किया जा सकता है।

और बारीकियों:

हुक प्रत्येक रेफरी अद्यतन किया जा करने के लिए एक बार कार्यान्वित करता है, और तीन पैरामीटर लेता है:

  • रेफरी के नाम अपडेट किया जा रहा,
  • पुराने ऑब्जेक्ट नाम को रेफरी में संग्रहीत किया गया है,
  • और नया ऑब्जेक्टनाम रेफरी में संग्रहीत किया जाना है।

तो, उदाहरण के लिए, आप यह सुनिश्चित करें कि प्रतिबद्ध विषयों में से कोई भी 80 वर्ण से अधिक कर रहे हैं करना चाहते हैं, एक बहुत ही मौलिक कार्यान्वयन होगा:

#!/bin/bash 
long_subject=$(git log --pretty=%s $2..$3 | egrep -m 1 '.{81}') 
if [ -n "$long_subject" ]; then 
    echo "error: commit subject over 80 characters:" 
    echo " $long_subject" 
    exit 1 
fi 
बेशक

, कि एक है खिलौना उदाहरण; सामान्य स्थिति में, आप पूर्ण प्रतिबद्ध संदेश वाले लॉग आउटपुट का उपयोग करेंगे, प्रति प्रतिबद्धता को विभाजित करेंगे, और प्रत्येक सत्यापन प्रतिबद्ध संदेश पर अपना सत्यापन कोड कॉल करेंगे।

क्यों आप अद्यतन हुक

यह चर्चा की गई/स्पष्ट टिप्पणी में चाहते हैं; यहां एक सारांश है।

अद्यतन हुक प्रति बार एक बार चलता है। एक रेफरी एक वस्तु के लिए एक सूचक है; इस मामले में, हम शाखाओं और टैगों के बारे में बात कर रहे हैं, और आम तौर पर सिर्फ शाखाएं (लोग टैग को अक्सर धक्का नहीं देते हैं, क्योंकि वे आम तौर पर केवल संस्करणों को चिह्नित करने के लिए होते हैं)।

अब, अगर एक उपयोगकर्ता दो शाखाओं, गुरु और प्रयोगात्मक के लिए अद्यतन धक्का है:

o - o - o (origin/master) - o - X - o - o (master) 
\ 
    o - o (origin/experimental) - o - o (experimental) 

मान लीजिए कि एक्स "बुरा" के लिए प्रतिबद्ध है, यानी एक जो प्रतिबद्ध-msg हुक विफल हो जाएगा है। स्पष्ट रूप से हम मास्टर को धक्का स्वीकार नहीं करना चाहते हैं। तो, अद्यतन हुक उस को अस्वीकार करता है। लेकिन प्रयोगात्मक पर काम करने के साथ कुछ भी गलत नहीं है! अद्यतन हुक उसको स्वीकार करता है। इसलिए, मूल/मास्टर अपरिवर्तित रहता है, लेकिन मूल/प्रयोगात्मक अद्यतन हो जाता है:

o - o - o (origin/master) - o - X - o - o (master) 
\ 
    o - o - o - o (origin/experimental, experimental) 

पूर्व प्राप्त चलाए जाने पर केवल एक बार, शुरुआत refs अद्यतन करने के लिए बस से पहले (पहली बार से पहले अद्यतन हुक चलाया जाता है) हुक। यदि आपने इसका इस्तेमाल किया है, तो आपको पूरे धक्का को असफल होने का कारण बनना होगा, इस प्रकार यह कहकर कि मास्टर पर एक बुरा प्रतिबद्ध संदेश था, आप किसी भी तरह से भरोसा नहीं करते कि प्रयोगात्मक पर काम अच्छा है, भले ही उनके संदेश ठीक हैं!

+0

मुझे लगता है कि ओपी जो हुक ढूंढ रहा है वह पूर्व-प्राप्त है, क्योंकि वह प्रतिबद्ध संदेश के आधार पर पूरे धक्का को अस्वीकार करना चाहता है। हालांकि, AFAIK, न तो पूर्व-प्राप्त और न ही अद्यतन संदेश के रूप में इनपुट संदेश प्राप्त करते हैं। तो प्रतिबद्ध-संदेश का उपयोग शायद सबसे अच्छा समाधान होगा। –

+0

@ कान: मुझे पूरा यकीन है कि ओपी अद्यतन चाहता है, पूर्व-प्राप्त नहीं। "पूरे धक्का" का मतलब सभी शाखाओं के लिए धक्का है। यदि उपयोगकर्ता तीन शाखाओं में अपडेट को धक्का देने का प्रयास करता है, और केवल एक में अमान्य प्रतिबद्ध संदेश होते हैं, तो अन्य दो को अभी भी स्वीकार किया जाना चाहिए! – Cascabel

+0

@ कान: और नहीं, प्रतिबद्ध संदेश इनपुट का हिस्सा नहीं है, लेकिन पुराने और नए ऑब्जेक्ट (प्रतिबद्ध) नाम (SHA1s) हैं। ध्यान दें कि रीफ अपडेट होने से पहले अद्यतन हुक निष्पादित किया जाता है (प्रतिबद्ध वस्तुओं को प्राप्त करने के बाद)। हुक इसलिए गिट लॉग का उपयोग पुराने और नए के बीच जो कुछ भी करना चाहता है उसका निरीक्षण करने के लिए कर सकता है, जिसमें उनके प्रतिबद्ध संदेश भी शामिल हैं। – Cascabel

1

आपको अपने पूर्व-प्राप्त होने पर एक स्क्रिप्ट बनाने की आवश्यकता है।

इस स्क्रिप्ट में आपको पुराना और नया संशोधन प्राप्त होता है। यदि आप इनमें से एक खराब है तो आप सभी प्रतिबद्धताओं की जांच कर सकते हैं और झूठी वापसी कर सकते हैं।

5

आप इसे निम्नलिखित pre-receive hook के साथ कर सकते हैं। जैसा कि अन्य उत्तरों ने ध्यान दिया है, यह एक रूढ़िवादी, सभी या कुछ भी दृष्टिकोण नहीं है। ध्यान दें कि यह केवल मास्टर शाखा की रक्षा करता है और विषय शाखाओं पर प्रतिबद्ध संदेशों पर कोई बाधा नहीं रखता है।

#! /usr/bin/perl 

my $errors = 0; 
while (<>) { 
    chomp; 
    next unless my($old,$new) = 
    m[^([0-9a-f]+) \s+ # old SHA-1 
     ([0-9a-f]+) \s+ # new SHA-1 
     refs/heads/master # ref 
     \s* $ ]x; 

    chomp(my @commits = `git rev-list $old..$new`); 
    if ($?) { 
    warn "git rev-list $old..$new failed\n"; 
    ++$errors, next; 
    } 

    foreach my $sha1 (@commits) { 
    my $msg = `git cat-file commit $sha1`; 
    if ($?) { 
     warn "git cat-file commit $sha1 failed"; 
     ++$errors, next; 
    } 

    $msg =~ s/\A.+? ^$ \s+//smx; 
    unless ($msg =~ /\[\d+\]/) { 
     warn "No bug number in $sha1:\n\n" . $msg . "\n"; 
     ++$errors, next; 
    } 
    } 
} 

exit $errors == 0 ? 0 : 1; 

यह सभी को अपने संबंधित प्रतिबद्ध संदेशों में कहीं भी एक टिप संख्या रखने के लिए धक्का में काम करने की आवश्यकता होती है, केवल टिप नहीं।

$ git log --pretty=oneline origin/master..HEAD 
354d783efd7b99ad8666db45d33e30930e4c8bb7 second [123] 
aeb73d00456fc73f5e33129fb0dcb16718536489 no bug number 

$ git push origin master 
Counting objects: 6, done. 
Delta compression using up to 2 threads. 
Compressing objects: 100% (4/4), done. 
Writing objects: 100% (5/5), 489 bytes, done. 
Total 5 (delta 0), reused 0 (delta 0) 
Unpacking objects: 100% (5/5), done. 
No bug number in aeb73d00456fc73f5e33129fb0dcb16718536489: 

no bug number 

To file:///tmp/bare.git 
! [remote rejected] master -> master (pre-receive hook declined) 
error: failed to push some refs to 'file:///tmp/bare.git'

हम दो प्रतिबद्ध एक साथ कुचलने और परिणाम धक्का द्वारा इस समस्या को ठीक कहते हैं: उदाहरण के लिए:

$ git rebase -i origin/master 
[...] 

$ git log --pretty=oneline origin/master..HEAD 
74980036dbac95c97f5c6bfd64a1faa4c01dd754 second [123] 

$ git push origin master 
Counting objects: 4, done. 
Delta compression using up to 2 threads. 
Compressing objects: 100% (2/2), done. 
Writing objects: 100% (3/3), 279 bytes, done. 
Total 3 (delta 0), reused 0 (delta 0) 
Unpacking objects: 100% (3/3), done. 
To file:///tmp/bare.git 
    8388e88..7498003 master -> master
2

यह pre-receive की एक अजगर संस्करण है, जो मुझे कुछ समय लिया खत्म करने के लिए, आशा है यह दूसरों की मदद कर सकता है। मैं मुख्य रूप से इसे ट्रैक के साथ उपयोग करता हूं, लेकिन इसे अन्य उद्देश्यों के लिए आसानी से संशोधित किया जा सकता है।

मैंने ऐतिहासिक प्रतिबद्ध संदेश को वापस संशोधित करने के निर्देश भी दिए हैं, जो मैंने सोचा था उससे थोड़ा अधिक जटिल है।

#!/usr/bin/env python 
import subprocess 

import sys 
import re 

def main(): 
    input = sys.stdin.read() 
    oldrev, newrev, refname = input.split(" ") 
    separator = "----****----" 


    proc = subprocess.Popen(["git", "log", "--format=%H%n%ci%n%s%b%n" + separator, oldrev + ".." + newrev], stdout=subprocess.PIPE) 
    message = proc.stdout.read() 
    commit_list = message.strip().split(separator)[:-1] #discard the last line 

    is_valid = True 

    print "Parsing message:" 
    print message 

    for commit in commit_list: 
     line_list = commit.strip().split("\n") 
     hash = line_list[0] 
     date = line_list[1] 
     content = " ".join(line_list[2:]) 
     if not re.findall("refs *#[0-9]+", content): #check for keyword 
      is_valid = False 

    if not is_valid: 
     print "Please hook a trac ticket when commiting the source code!!!" 
     print "Use this command to change commit message (one commit at a time): " 
     print "1. run: git rebase --interactive " + oldrev + "^" 
     print "2. In the default editor, modify 'pick' to 'edit' in the line whose commit you want to modify" 
     print "3. run: git commit --amend" 
     print "4. modify the commit message" 
     print "5. run: git rebase --continue" 
     print "6. remember to add the ticket number next time!" 
     print "reference: http://stackoverflow.com/questions/1186535/how-to-modify-a-specified-commit" 

     sys.exit(1) 

main() 
1

आप अपने बग ट्रैकर है क्या जिक्र नहीं किया था, लेकिन अगर यह JIRA है, तो ऐड-ऑन Commit Policy नामित किसी भी प्रोग्रामिंग के बिना के लिए ऐसा कर सकते हैं।

आप एक प्रतिबद्ध शर्त स्थापित कर सकते हैं जिसके लिए एक नियमित अभिव्यक्ति से मेल खाने के लिए प्रतिबद्ध संदेश की आवश्यकता होती है। यदि ऐसा नहीं होता है, तो पुश अस्वीकार कर दिया जाता है, और डेवलपर को प्रतिबद्ध संदेश में संशोधन (ठीक) करना होगा, फिर पुन: दबाएं।

संबंधित मुद्दे