2010-03-26 3 views
23

CVS에서 가져온 커밋 메시지에는 버그 번호 (간단한 접미사 "... [9999]")가 있어야합니다. CVS 스크립트는 커밋 중에 이것을 확인하고 메시지가 맞지 않으면 커밋을 거부합니다.푸시에 대한 커밋 메시지를 확인하는 방법은 무엇입니까?

git hook commit-msg는 개발자 측에서이 작업을 수행하지만 자동화 된 시스템을 확인하고이를 상기시키는 것이 도움이된다는 것을 알게되었습니다.

git 푸시 중에 commit-msg가 실행되지 않습니다. 푸시 중에 커밋 메시지를 확인할 수있는 또 다른 훅이 있습니까?

git 푸시 중에 커밋 메시지를 확인하는 방법은 무엇입니까?

답변

23

업데이트 후크 당신은 후크에 대해 알고

사용 - 그들에 대한 documentation을 읽어주십시오! 원하는 훅 (hook)은 업데이트 (ref) 일 ​​때마다 실행되는 업데이트입니다. (pre-receive 후크는 전체 푸쉬에 대해 한 번 실행됩니다.) 이미 이러한 후크에 대한 많은 질문과 답변이 있습니다. 원하는 작업에 따라 필요할 때마다 훅을 작성하는 방법에 대한 지침을 찾을 수 있습니다.

이 정말로 문서에서 인용이 가능하다는 것을 강조하기 :

이 후크는 개체 이름이있는 커밋 객체임을 확인하여 특정 심판에 강제 업데이 트를 방지 할 수 있습니다

이전 오브젝트 이름으로 명명 된 확약 오브젝트의 하위 오브젝트. 즉, "빨리 감기"정책을 시행하는 것입니다.

또한 이전 상태를 기록하는 데 사용할 수 있습니다. 새 상태.

그리고 특성 :

후크 갱신 각 REF 번씩 실행하고, 세 파라미터 취 심판의 이름을 업데이트되는

  • 을 ref에 저장된 이전 객체 이름
  • 및 ref에 저장할 새 objectname

따라서, 예를 들어, 당신은 커밋 주제 것도 이상 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 

, 즉 A의 장난감 예; 일반적인 경우 전체 커밋 메시지가 포함 된 로그 출력을 사용하고 커밋마다 분할하고 개별 커밋 메시지마다 인증 코드를 호출합니다. 당신이이 의견/토론 명확히하고있다

업데이트 후크를 원하는 이유

; 여기에 요약이 있습니다.

업데이트 후크는 ref마다 한 번 실행됩니다. ref는 객체에 대한 포인터입니다. 이 경우 우리는 가지와 태그에 대해 말하고 일반적으로 분기 만합니다. 사람들은 태그를 자주 표시하기 때문에 태그를 자주 푸시하지 않습니다.사용자가 두 가지, 마스터와 실험에 대한 업데이트를 밀어 경우

지금, :

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

는 X가 커밋 MSG 후크를 실패 "나쁜"커밋, 즉 하나라고 가정하자. 분명히 우리는 압박을 받아들이는 것을 받아들이고 싶지 않습니다. 따라서 업데이트 후크는이를 거부합니다. 그러나 실험에 대한 커밋에는 아무런 문제가 없습니다! 업데이트 훅은이를 받아들입니다. 따라서, 원산지/마스터가 변경되지 않고 유지하지만, 원/실험이 업데이트 될 때 :

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

사전 수신 한 번만, 시작은 심판을 업데이트하기 직전에 (처음 전에 업데이트 후크가 실행)를 실행 후크를. 만약 당신이 그것을 사용한다면, 당신은 전체 밀어 내기를 실패하게해야 할 것입니다. 따라서 마스터에게 나쁜 커밋 메시지가 있었기 때문에 더 이상 그들의 메시지가 훌륭하더라도 실험에 대한 커밋이 더 이상 신뢰되지 않습니다.

+0

커밋 메시지에 따라 전체 밀어 내기를 거부하기 때문에 OP가 찾고있는 후크가 사전 수신이라고 생각합니다. 그러나 AFAIK는 사전 수신도 업데이트도 커밋 메시지를 입력으로받지 않습니다. 따라서 commit-msg를 사용하는 것이 가장 좋은 해결책 일 것입니다. –

+0

@Can : OP가 업데이트 받기를 원하며 미리 수신하지 않을 것이라고 확신합니다. "전체 추진"은 모든 가지에 대한 추진을 의미합니다. 사용자가 세 가지 분기로 업데이트를 푸시하려고 시도하고 하나만 유효하지 않은 커밋 메시지를 포함하면 다른 두 가지는 여전히 허용되어야합니다! – Cascabel

+0

@Can : 그리고 커밋 메시지는 입력의 일부가 아니지만 이전 및 새 개체 (커밋) 이름 (SHA1)은 있습니다. 업데이트 훅은 ref가 업데이트되기 전에 (커밋 객체가 수신 된 후) 실행된다는 점에 유의하십시오. 따라서 hook은 git log를 사용하여 커밋 메시지를 포함하여 old와 new 사이의 커밋에 대해 조사 할 수 있습니다. – Cascabel

1

사전 수신시 스크립트를 작성해야합니다.

이 스크립트에서는 이전 및 새 버전을 받게됩니다. 모든 커밋을 검사하고이 중 하나가 잘못된 경우 false를 반환 할 수 있습니다.

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의 파이썬 버전은, 희망 그것은 다른 사람들을 도울 수 있습니다. 주로 Trac에서 사용하지만 다른 목적으로 쉽게 수정할 수 있습니다.

이전의 커밋 메시지를 수정하기위한 지침을 내려 놓았습니다. 이는 생각했던 것보다 조금 복잡합니다.

#!/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을 지명했다.

커밋 메시지가 정규식과 일치해야하는 커밋 조건을 설정할 수 있습니다. 그렇지 않으면 푸시가 거부되고 개발자는 커밋 메시지를 수정 (수정) 한 다음 다시 밀어 넣어야합니다.

관련 문제