Đưa ra một id xác nhận, làm thế nào để xác định xem nhánh hiện tại có chứa cam kết không?


154

Những gì tôi đang cố gắng làm là kiểm tra phiên bản. Tôi muốn đảm bảo mã nằm trên một phiên bản tối thiểu. Vì vậy, tôi cần một cách để biết liệu nhánh hiện tại có chứa một xác nhận đã chỉ định hay không.



10
Xem bản sao được đề xuất để biết cách tìm tất cả các nhánh có chứa một xác nhận đã chỉ định. Để tìm hiểu xem nhánh hiện tại có chứa C cam kết hay không , hãy sử dụng lệnh "ống nước" git merge-base --is-ancestor. Nhánh hiện tại chứa C nếu C là tổ tiên của HEAD, vì vậy:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
torek

1
Xin chào, vui lòng gửi câu hỏi này dưới dạng câu trả lời để có thể được chọn là câu trả lời đúng =)
Ben

1
@Ben - Tôi đã thêm nó dưới dạng câu trả lời wiki cộng đồng.
Zitrax

1
@Remover: trong các kịch bản shell, zero là true, nonzero là false: mặt trái của quy ước C. /bin/trueban đầu được thực hiện như exit 0/bin/falsenhư exit 1. (Vỏ hiện đại sau đó đã được chế tạo.)
torek

Câu trả lời:


216

Có nhiều cách để đạt được kết quả này. Tùy chọn ngây thơ đầu tiên là sử dụng git logvà tìm kiếm một cam kết cụ thể bằng cách sử dụng grep, nhưng điều đó không phải lúc nào cũng chính xác

git log | grep <commit_id>

Bạn nên sử dụng git branchtrực tiếp để tìm tất cả các nhánh có chứa COMMIT_IDbằng cách sử dụng

git branch --contains $COMMIT_ID

Bước tiếp theo là tìm ra chi nhánh hiện tại có thể được thực hiện kể từ khi git 1.8.1sử dụng

git symbolic-ref --short HEAD

Và kết hợp với nhau như

git branch $(git symbolic-ref --short HEAD) --contains $COMMIT_ID

Nhưng lệnh trên không trả về true hoặc false và có một phiên bản ngắn hơn trả về mã thoát 0 nếu xác nhận nằm trong nhánh hiện tại HOẶC mã thoát 1 nếu không

git merge-base --is-ancestor $COMMIT_ID HEAD

Mã thoát là tốt, nhưng khi bạn muốn chuỗi truehoặc falsenhư câu trả lời, bạn cần thêm một chút nữa và sau đó kết hợp với iftừ bash bạn nhận được

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi

9
Điều đó không đúng; điều grepnày có thể dẫn đến kết quả dương tính giả nếu git logđề cập đến SHA cam kết vì các lý do khác, ví dụ: nó được đề cập trong thông báo cam kết là kết quả của một cổng từ chi nhánh khác.
Adam Spiers

1
Đã sửa (hoặc thêm một tùy chọn khác).
JiriS

3
Vui lòng xem bình luận về câu hỏi, sử dụng bộ công cụ git tích hợp. stackoverflow.com/questions/43535132/ cường
Ben

2
Tôi thích tùy chọn đầu tiên, nhưng để loại trừ sự phản đối của Adam, tôi sẽ thêm tùy chọn này --format=format:%Hvào git log.
PJSCopeland

71

Lấy một danh sách các chi nhánh có chứa các cam kết cụ thể.

# get all the branches where the commit exists
$ git branch --contains <commit-id>

Kiểm tra nếu một chi nhánh có cam kết cụ thể.

# output the branch-name if the commit exists in that branch
$ git branch --contains <commit-id> | grep <branch-name>

Tìm kiếm chi nhánh (nói, feature) với kết hợp chính xác .

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

ví dụ Nếu bạn có 3 chi nhánh địa phương gọi là feature, feature1, feature2sau đó

$ git branch --contains <commit-id> | grep 'feature'

# output
feature
feature1
feature2

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

# output
feature     

Bạn cũng có thể tìm kiếm trong cả hai localremotecác nhánh (sử dụng -a) hoặc chỉ trong remotecác nhánh (sử dụng -r).

# search in both 'local' & 'remote' branches  
$ git branch -a --contains <commit-id> | grep -E '(^|\s)feature$'

# search in 'remote' branches  
$ git branch -r --contains <commit-id> | grep -E '(^|\s)feature$'

1
grepđây cũng có thể dẫn đến kết quả dương tính giả nếu có các nhánh khác chứa cam kết có tên cũng chứa <branch-name>dưới dạng chuỗi con.
Adam Spiers

1
Có @AdamSpiers, Đã cập nhật câu trả lời khớp chính xác với tên chi nhánh củagrep -E '(^|\s)branchname$'
Sajib Khan

1
Mỗi nhận xét này về vấn đề có liên quan nó có thể hữu ích để thêm -r( "remote") hoặc -a( "tất cả") tùy chọn để git branchtìm kiếm các chi nhánh có thể không được sao chép trong clone repo địa phương.
sxc731

Điều này không hiệu quả với tôi, tôi cần git branch --all --contains <commit-id>
Arthur Tacca

7

Trích xuất nhận xét của @torek dưới dạng câu trả lời:

Xem bản sao được đề xuất để biết cách tìm tất cả các nhánh có chứa một xác nhận đã chỉ định.

Để tìm hiểu xem nhánh hiện tại có chứa C cam kết hay không, hãy sử dụng lệnh "ống nước" git merge-base --is-ancestor. Nhánh hiện tại chứa C nếu C là tổ tiên của HEAD, vì vậy:

if git merge-base --is-ancestor $hash HEAD; then
    echo I contain commit $hash
else
    echo I do not contain commit $hash
fi

(Lưu ý bên lề: trong các tập lệnh shell, một lệnh thoát 0 là "true" trong khi một lệnh thoát ra khác không là "false".)


4

Để liệt kê các chi nhánh địa phương có chứa commit:

git branch --contains <commit-id>

và để liệt kê tất cả các chi nhánh, bao gồm chỉ từ xa, có chứa cam kết:

git branch -a --contains <commit-id>

Tương tự để kiểm tra nếu cam kết là trong chi nhánh cụ thể:

git log <branch> | grep <commit_id>

và nếu nhánh không tồn tại tên nhánh tiền tố cục bộ với origin/


Bình chọn cho nhận xét trên -a. Cảm ơn lời khuyên đó!
Thorkil Værge

3

Vâng thay thế khác:

git rev-list <branch name> | grep `git rev-parse <commit>`

Điều này hoạt động tốt nhất đối với tôi vì nó cũng sẽ hoạt động trên các nhánh từ xa được lưu trong bộ nhớ cache cục bộ remotes/origin/master, như trên đó git branch --containssẽ không hoạt động.

Điều này bao gồm nhiều hơn câu hỏi của OP về "chi nhánh hiện tại" nhưng tôi thấy thật ngu ngốc khi hỏi phiên bản "bất kỳ chi nhánh" nào của câu hỏi này vì vậy tôi quyết định đăng ở đây.


1
git branch --contains <commit-id> --points-at <target branch name>

Nó sẽ trả về tên nhánh đích nếu id xác thực tồn tại trong nhánh đó. Nếu không lệnh sẽ thất bại.


Không ...error: malformed object name 'branch-name'
bbodenmiller 20/07/18

1
Bạn có thể gặp lỗi đó trong 2 trường hợp 1. Khi <tên chi nhánh> đã cho không chứa <commit id> đã cho <thanh toán <tên chi nhánh> không phải là <tên chi nhánh> đã cho
DreamUth

0

Vì câu hỏi này có một số câu trả lời hay, nên tôi thêm vào mục yêu thích của mình.

Điều này sẽ cho bạn thấy, cho các $ncam kết cuối cùng trong $brđó các nhánh chứa mỗi:

br=mybranch
n=10
git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'

Cái này tương tự nhưng làm tương tự cho một danh sách các nhánh:

br="mybranch yourbranch herbranch"
n=4
for br in $brs; do git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'; done
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.