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-ancestorgiả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-ancestorgiả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 Bcó 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-listnhư 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-ancestorsau 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 novd:git merge-base my-feature-branch --is-ancestor master && echo yes || echo no
git merge-base --is-ancestor -- commit commithoạt động để băm ở bên tôi với git2.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-listlệ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-listsẽ không trả lại gì.
git rev-list --boundary A..B
sẽ kết thúc bởi A, nếu Acó thể truy cập từ B.
Nó giống như:
git rev-list --boundary B --not A
, với Bmột tài liệu tham khảo tích cực , và Amột tài liệu tham khảo tiêu cực .
Nó sẽ bắt đầu tại Bvà 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 Acó thể truy cập trực tiếp từ Bnó, nó sẽ gặp phải (và hiển thị, vì --boundarytù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 logvà 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.
--prettytôi sử dụng --oneline: git log --oneline ce2ee3d | grep ec219cchoạ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
generationvàgraph_poschỉ đượ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_datavà chuyển chúng sang mộtcommit_graph_datatấ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.