2010-08-18 33 views
26

Tôi gặp sự cố với móc 'cập nhật'. Trong trường hợp của một chi nhánh mới, nó nhận được một 0000000000000000000000000000000000000000 là 'oldrev'. Và tôi không biết cách xử lý trường hợp đó.Móc nhận/cập nhật Git và chi nhánh mới

Chúng tôi có yêu cầu, mọi thông báo cam kết đều tham chiếu đến vấn đề Jira hợp lệ. Vì vậy, tôi đã cài đặt một móc "cập nhật" trên kho lưu trữ trung tâm của chúng tôi. Cái móc đó có chữ "oldrev" và "newrev". sau đó tôi vượt qua những để "git rev-list" như thế này:

git rev-list $oldrev..$newrev

này mang lại cho tôi danh sách của tất cả các vòng quay, mà tôi sau đó có thể lặp qua, và làm bất cứ điều gì tôi cần phải làm.

Vấn đề là khi người dùng đẩy chi nhánh mới, móc được trả 0000000000000000000000000000000000000000 làm cũ. Và "git rev-list" chỉ đơn giản là phàn nàn với:

fatal: Invalid revision range 0000000000000000000000000000000000000000..21bac83b2

Vậy làm thế nào để tôi có được danh sách của tất cả các vòng quay mà trên đó chi nhánh mới? Tôi đã tìm kiếm trên mạng trong một thời gian và không tìm thấy gì. Các móc ví dụ tôi tìm thấy một trong hai

  • không xử lý được vấn đề, và thất bại với các thông báo lỗi trên
  • sai cố gắng giải quyết vấn đề bằng cách thiết lập oldrev để "", mà trả về kết quả sai từ rev -list
  • chỉ đơn giản là bỏ cuộc khi họ gặp phải cũ đó

Không có âm thanh nào đặc biệt thú vị.

Vậy ai đó có ý tưởng làm thế nào để có được câu trả lời đúng trong trường hợp đó? Tôi đã suy nghĩ về truy vấn git cho "cho tôi tất cả các vòng quay có thể truy cập từ newrev, nhưng không phải từ bất kỳ chi nhánh khác (= tất cả các chi nhánh ngoại trừ một cái mới)". Nhưng ngay cả điều đó sẽ đưa ra câu trả lời sai nếu đã có sự hợp nhất từ ​​nhánh mới với bất kỳ nhánh cũ nào.

Trả lời

14

Thuật ngữ "câu trả lời đúng" hơi mơ hồ trong trường hợp này. Tôi thực sự nghĩ rằng "tất cả các vòng quay có thể truy cập từ newrev nhưng không nơi nào khác" là hoàn toàn chính xác. Điều này đúng ngay cả khi có hợp nhất - trong trường hợp đó, bạn sẽ thấy các cam kết duy nhất đối với ref mới và cam kết hợp nhất, nhưng không phải là các cam kết đã được hợp nhất.

Vì vậy, tôi sẽ nói, kiểm tra xem "oldrev" là tất cả zero, và nếu nó là, hành động phù hợp:

if [ "$oldrev" -eq 0 ]; then 
    # list everything reachable from newrev but not any heads 
    git rev-list $(git for-each-ref --format='%(refname)' refs/heads/* | sed 's/^/\^/') "$newrev" 
else 
    git rev-list "$oldrev..$newrev" 
fi 
+2

Tôi không chắc chắn nếu nó là một cái gì đó kỳ lạ với môi trường của tôi hoặc cập nhật để git, nhưng phủ định là loại bỏ refs trên nhánh hiện tại. Tôi phải làm một cái gì đó như thế này: 'git rev-list $ (git cho-mỗi-ref -format = '% (refname)'" refs/heads/* "| grep -v '$ ref' | sed 's/^/\^/') "$ newrev" ' – mmalone

+1

Để sử dụng trong móc' update' (và 'pre-receive'), như được chỉ định trong câu hỏi, những câu trả lời này phức tạp và tốn kém hơn. Câu trả lời của Joseph dưới đây là câu trả lời đơn giản và hiệu quả nhất; đó phải là câu trả lời đã chọn IMO. – MadScientist

+0

@mmalone bạn nói đúng. Tôi đã phải thêm "| grep -v '$ rev'". Nếu không tôi luôn luôn có kết quả empy – dritan

7

tôi chỉ figured it out bản thân mình.

git log newref --not otherheads

là chìa khóa để có được tất cả các bản ghi của một chi nhánh mà không phải là trên bất kỳ chi nhánh khác. Dưới đây là kịch bản python của tôi để kiểm tra chiều dài dòng tối đa chính xác của các thông điệp cam kết.

import sys 
import commands 

ref = sys.argv[1] 
old = sys.argv[2] 
new = sys.argv[3] 

x = 0 

# only a tag is pushed to server, nothing to check 
if ref.find('refs/tags/') >= 0: 
    if len(ref.strip('refs/tags/')) > 25: 
    print 'tag name is longer than 25 characters' 
    exit(1) 
    else: 
    exit(0) 
# either a new branch is pushed or an empty repo is being pushed 
if old == '0000000000000000000000000000000000000000': 
    heads = commands.getoutput("git for-each-ref --format='%(refname)' 'refs/heads/*'") 
    heads = heads.replace(ref+'\n','').replace('\n',' ') 
    hashes = commands.getoutput('git log '+new+' --pretty=%H --not '+heads).split('\n') 
else: 
    hashes = commands.getoutput('git log '+old+'..'+new+' --pretty=%H').split('\n') 

for hash in hashes: 
    subject = commands.getoutput('git show '+hash+' --format=%s --summary').split('\n') 
    body = commands.getoutput('git show '+hash+' --format=%b --summary').split('\n') 

    if len(subject[0]) > 75: 
    print 
    print 'commit: '+hash 
    print 'bad commit message(s): header line is too long or second line is not blank (max 75 chars)' 
    print 'bad line: "%s"' % subject[0] 
    print 'length of header line: %d' % len(subject[0]) 
    print 'try again with correct message format' 
    print 
    x = 1 

    for line in body: 
    if len(line) > 75: 
     print 
     print 'commit: '+hash 
     print 'bad commit message(s): description lines are too long (max 75 chars)' 
     print 'bad line: "%s"' % line 
     print 'length of line: %d' % len(line) 
     print 'try again with correct message format' 
     print 
     x = 1 

if x == 0: 
    exit(0) 
else: 
    exit(1) 
+0

Sử dụng 'refs/heads/*' trong 'for-each-ref' không phải là một ý tưởng tốt. Nó sẽ không khớp với bất kỳ nhánh nào có dấu gạch chéo trong tên (ví dụ: 'foo/bar'). Bạn chỉ nên sử dụng 'refs/heads /' (no '*'). Nhưng, hãy xem câu trả lời của Joseph dưới đây để có một giải pháp thay thế đơn giản hơn. – MadScientist

3

tôi giải quyết này cho móc cập nhật của tôi bằng cách sử dụng sau đây:

if [ "$oldrev" -eq 0 ]; then 
git log "$(git show-branch --merge-base)".."$newrev"; else 
foo; 
fi 
+0

Điều này sẽ không hoạt động nếu bạn đang ở trong một cái móc, đặc biệt nếu bạn có hơn 25 chi nhánh trong kho lưu trữ của bạn. – MadScientist

9

Khi $oldrev là tất cả số không, một git rev-list lệnh khác nhau làm tất cả bạn cần:

git rev-list $newrev --not --branches=* 

sẽ cung cấp cho bạn danh sách các bản sửa đổi có thể truy cập từ $newrev nhưng không phải từ bất kỳ chi nhánh nào.

Lưu ý rằng điều này chắc chắn không không làm điều tương tự như git rev-list $oldrev..$newrev khi oldrev là không tất cả các số không, vì vậy bạn sẽ muốn kiểm tra trường hợp này bạn đang ở và chọn lệnh thích hợp để chạy.

+1

Mặc dù thực tế điều này làm việc _in trước khi nhận và cập nhật hooks_ bởi vì khi những móc đang chạy nhánh mới chưa có! Tốt đẹp! – MadScientist

+0

Điều này cũng không giúp bạn sửa đổi từ trước khi oldrev, trong trường hợp nó không phải là tất cả các số không? – Cascabel

+1

@ Jefromi ý của bạn là gì? Lệnh trên sẽ cung cấp cho bạn danh sách tất cả các cam kết không được tham chiếu từ bất kỳ chi nhánh nào. Trong các bản cập nhật và các trình kích hoạt trước khi nhận, đó là các cam kết mới đang được thêm vào như một phần của push: tên chi nhánh hoặc không tồn tại (nếu mới) hoặc chưa được di chuyển (nếu có). Điều này không làm việc trong một móc sau khi nhận được nhưng đó không phải là những gì câu hỏi đã được về. Tôi không hiểu tại sao điều này lại được bình chọn: đó là câu trả lời đơn giản, gọn gàng nhất đối với CÂU HỎI THƯỜNG GẶP. – MadScientist

Các vấn đề liên quan