Với Git, làm thế nào tôi có thể biết nếu một cam kết trong chi nhánh của tôi là hậu duệ của một cam kết khác?
--is-ancestor
giải pháp.
Với Git, làm thế nào tôi có thể biết nếu một cam kết trong chi nhánh của tôi là hậu duệ của một cam kết khác?
--is-ancestor
giải pháp.
Câu trả lời:
Nếu bạn muốn kiểm tra điều này theo chương trình (ví dụ: trong tập lệnh), bạn có thể kiểm tra xem git merge-base A B
có bằng git rev-parse --verify A
(thì A có thể truy cập từ B) hoặc nếu có git rev-parse --verify B
(thì B có thể truy cập từ A). git rev-parse
ở đây cần thiết để chuyển đổi từ tên cam kết sang cam kết SHA-1 / id id.
Sử dụng git rev-list
như trong câu trả lời VonC cũng có khả năng.
Chỉnh sửa: trong Git hiện đại có hỗ trợ rõ ràng cho truy vấn này ở dạng git merge-base --is-ancestor
.
Nếu một trong những cam kết mà bạn đang hỏi là một mẹo chi nhánh , thì git branch --contains <commit>
hoặc git branch --merged <commit>
có thể là giải pháp phi lập trình tốt hơn.
git checkout -b quickcheck <more-recent-commit-ID>
và sau đó git branch --contains <older-commit-ID>
(và sau đó git branch -D quickcheck
để thoát khỏi nhánh tạm thời).
git merge-base --is-ancestor
sau 2 năm.
git branch --contains <commit>
và git merge-base --is-ancestor ...
: 3m40s so với 0.14s
Từ Git 1.8.0, điều này được hỗ trợ dưới dạng tùy chọn để merge-base
:
git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>
Từ trang người đàn ông:
--is-tổ tiên
Kiểm tra xem cái đầu tiên là tổ tiên của cái thứ hai và thoát với trạng thái 0 nếu đúng hoặc với trạng thái 1 nếu không. Lỗi được báo hiệu bằng trạng thái khác không phải là 1.
Ví dụ:
git merge-base --is-ancestor origin/master master; echo $?
git merge-base THING --is-ancestor OF_THING && echo yes || echo no
vd:git merge-base my-feature-branch --is-ancestor master && echo yes || echo no
git merge-base --is-ancestor -- commit commit
hoạt động để băm ở bên tôi với git
2.1.4 (Debian / Devuan 7.10 jessie) và 1.9.1 (Ubuntu 14.04 đáng tin cậy) hiện khá cổ xưa. Nó hoạt động ngay cả đối với Debian wheezy, nếu bạn làm sudo apt-get install git/wheezy-backports
.
Loại hoạt động này dựa trên khái niệm phạm vi sửa đổi được nêu chi tiết trong câu hỏi SO: " Sự khác biệt trong 'git log origin / master' so với 'git log origin / master ..' ".
git rev-list
sẽ có thể đi bộ trở lại từ một cam kết, cho đến khi khác nếu có thể đạt được.
Vì vậy, tôi sẽ cố gắng:
git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20
(Cam kết ranh giới được bắt đầu bằng -
)
Nếu lần xác nhận cuối cùng được hiển thị giống với lần xác nhận đầu tiên trong git rev-list
lệnh, thì đó là lần xác nhận có thể truy cập được từ lần xác nhận thứ hai.
Nếu cam kết đầu tiên không thể truy cập từ lần thứ hai, git rev-list
sẽ không trả lại gì.
git rev-list --boundary A..B
sẽ kết thúc bởi A
, nếu A
có thể truy cập từ B
.
Nó giống như:
git rev-list --boundary B --not A
, với B
một tài liệu tham khảo tích cực , và A
một tài liệu tham khảo tiêu cực .
Nó sẽ bắt đầu tại B
và quay trở lại qua biểu đồ cho đến khi nó gặp một bản sửa đổi có thể truy cập được A
.
Tôi sẽ lập luận rằng nếu A
có thể truy cập trực tiếp từ B
nó, nó sẽ gặp phải (và hiển thị, vì --boundary
tùy chọn) A
.
-85e54e2...
đoạn trích có một điểm trừ? cũng là một lỗi đánh máy có thể xảy ra: "... giống với lần cam kết đầu tiên ..."
-
có nghĩa là nó là một cam kết ranh giới. Tôi đã chỉnh sửa câu trả lời để làm cho nó rõ ràng hơn, cũng như để làm mới các liên kết doc và sửa lỗi chính tả cho câu trả lời 5 năm tuổi này.
Một cách khác là sử dụng git log
và grep
.
git log --pretty=format:%H abc123 | grep def456
Điều này sẽ tạo ra một dòng đầu ra nếu commit def456 là tổ tiên của commit abc123 hoặc không có đầu ra nào khác.
Bạn thường có thể thoát khỏi việc bỏ qua --pretty
đối số, nhưng nó là cần thiết nếu bạn muốn đảm bảo rằng bạn chỉ tìm kiếm thông qua các băm cam kết thực tế và không thông qua các bình luận nhật ký, v.v.
--pretty
tôi sử dụng --oneline: git log --oneline ce2ee3d | grep ec219cc
hoạt động tuyệt vời
https://stackoverflow.com/a/13526591/895245 đề cập đến nó, bây giờ để làm cho nó thân thiện hơn với con người:
git-is-ancestor() (
if git merge-base --is-ancestor "$1" "$2"; then
echo 'ancestor'
elif git merge-base --is-ancestor "$2" "$1"; then
echo 'descendant'
else
echo 'unrelated'
fi
)
alias giia='git-is-ancestor'
git show-nhánh nhánh-sha1 commit-sha1
Ở đâu:
Nếu bạn đang sử dụng git merge-base --is-ancestor
, hãy đảm bảo sử dụng Git 2.28 (Q3 2020)
Với Git 2.28 (quý 3 năm 2020), một vài trường trong " struct commit
" không phải luôn luôn có mặt đã được chuyển sang cam kết.
Xem cam kết c752ad0 , cam kết c49c82a , cam kết 4844812 , cam kết 6da43d9 (17 tháng 6 năm 2020) của Abhishek Kumar ( abhishekkumar2718
) .
(Được hợp nhất bởi Junio C Hamano - gitster
- trong cam kết d80bea4 , ngày 06 tháng 7 năm 2020)
commit-graph
: giới thiệucommit_graph_data_slab
Đã ký tắt: Abhishek Kumar
Cấu trúc cam kết được sử dụng trong nhiều ngữ cảnh. Tuy nhiên, các thành viên
generation
vàgraph_pos
chỉ được sử dụng cho các hoạt động liên quan đến biểu đồ cam kết và nếu không sẽ lãng phí bộ nhớ.Sự lãng phí này sẽ rõ rệt hơn khi chúng ta chuyển sang số thế hệ v2, sử dụng số thế hệ 64 bit thay vì 32 bit hiện tại.
Vì chúng thường được truy cập cùng nhau, hãy giới thiệu struct
commit_graph_data
và chuyển chúng sang mộtcommit_graph_data
tấm.Trong khi bộ kiểm tra tổng thể chạy nhanh như
master
, (sê-ri: 26m48 ,master
: 27m34, nhanh hơn 2,87%), một số lệnh nhất định nhưgit merge-base --is-ancestor
đã bị làm chậm 40% như được phát hiện bởi Seneder Gábor .
Sau khi giảm thiểu truy cập bản cam kết, tốc độ chậm vẫn tồn tại nhưng gần hơn với 20%.Derrick Stolee tin rằng sự chậm lại là do thuật toán cơ bản chứ không phải là sự chậm chạp của truy cập bản cam kết và chúng tôi sẽ theo dõi trong loạt bài sau.