(Điều này bắt đầu như một câu trả lời cho một câu hỏi trùng lặp. Tôi đã thực hiện một chút chỉnh sửa ánh sáng để làm sạch nó.)
Tất cả các mũi tên bên trong của Git là một chiều, chỉ về phía sau. Do đó, không có cú pháp thuận tiện ngắn để di chuyển về phía trước: điều đó là không thể.
Đó là khả năng "động thái chống lại các mũi tên", nhưng cách để làm điều đó là ngạc nhiên nếu bạn chưa nhìn thấy nó trước đây, và sau đó hiển nhiên sau đó. Hãy nói rằng chúng ta có:
A <-B <-C <-D <-E <-- last
^
|
\--------- middle
Sử dụng middle~2theo mũi tên hai lần từ Ctrở lại A. Vậy làm thế nào để chúng ta di chuyển từ Cđến D? Câu trả lời là: chúng tôi bắt đầu E, sử dụng tên lastvà làm việc ngược lại cho đến khi chúng tôi đến middle, ghi lại các điểm chúng tôi ghé thăm trên đường đi . Sau đó, chúng tôi chỉ cần di chuyển xa như chúng tôi muốn theo hướng last: di chuyển một bước tới D, hoặc hai đếnE .
Điều này đặc biệt quan trọng khi chúng ta có các chi nhánh:
D--E <-- feature1
/
...--B--C <-- master
\
F--G <-- feature2
Cam kết nào là một bước sau C? Không có câu trả lời đúng cho đến khi bạn thêm vào câu hỏi: theo hướng của tính năng ___ (điền vào chỗ trống).
Để liệt kê các cam kết giữa C(không bao gồm C) chính nó và, giả sử G, chúng tôi sử dụng:
git rev-list --topo-order --ancestry-path master..feature2
Điều --topo-orderchắc chắn rằng ngay cả khi có sự phân nhánh và hợp nhất phức tạp, các cam kết được đưa ra theo thứ tự cấu trúc liên kết. Điều này chỉ được yêu cầu nếu chuỗi không tuyến tính. Các --ancestry-pathphương tiện hạn chế rằng khi chúng tôi làm việc ngược từ feature2, chúng tôi chỉ danh sách cam kết có cam kết Clà một trong những tổ tiên của mình. Đó là, nếu đồ thị xếp hạng hay phần có liên quan của nó thì dù sao thì thực tế thì trông giống như thế này:
A--B--C <-- master
\ \
\ F--G--J <-- feature2
\ /
H-------I <-- feature3
một yêu cầu đơn giản của mẫu feature2..masterliệt kê các cam kết J, Gvà I, Fvà Htheo một số thứ tự. Với --ancestry-pathchúng tôi loại ra Hvà I: họ không phải là hậu duệ của C, chỉ của A. Với --topo-orderchúng tôi đảm bảo rằng thứ tự liệt kê thực tế là J, sau đó G, sau đóF .
Các git rev-listlệnh tràn các ID băm ra trên đầu ra tiêu chuẩn của nó, mỗi dòng một. Để tiến lên một bước theo hướng feature2, sau đó, chúng tôi chỉ muốn cuối cùng dòng .
Có thể (và hấp dẫn và có thể hữu ích) để thêm vào --reverseđể git rev-listin các cam kết theo thứ tự đảo ngược sau khi tạo chúng. Điều này không hoạt động, nhưng nếu bạn sử dụng nó trong một đường ống như thế này:
git rev-list --topo-order --ancestry-path --reverse <id1>...<id2> | head -1
để chỉ nhận "cam kết tiếp theo theo hướng id2" và có một danh sách các cam kết rất dài, git rev-listlệnh có thể nhận được một đường ống bị hỏng khi nó cố gắng ghi vào headđó đã ngừng đọc đầu vào và thoát. Do lỗi đường ống thường bị bỏ qua bởi vỏ, điều này chủ yếu hoạt động. Chỉ cần đảm bảo rằng chúng bị bỏ qua trong việc sử dụng của bạn .
Nó cũng hấp dẫn để thêm -n 1vào git rev-listlệnh, cùng với --reverse. Đừng làm thế! Điều đó làm cho git rev-listdừng lại sau khi đi một bước trở lại , và sau đó đảo ngược danh sách (một mục) các cam kết được truy cập. Vì vậy, điều này chỉ sản xuất <id2>mỗi lần.
Lưu ý bên quan trọng
Lưu ý rằng với các mảnh đồ thị "kim cương" hoặc "vòng benzen":
I--J
/ \
...--H M--... <-- last
\ /
K--L
di chuyển một cam kết "chuyển tiếp" từ Hđối lastsẽ giúp bạn có một trong hai I hoặc K . Không có gì bạn có thể làm về điều đó: cả hai cam kết là một bước tiến! Nếu sau đó bạn bắt đầu từ cam kết kết quả và đi thêm một bước nữa, thì bây giờ bạn đã cam kết với bất kỳ con đường nào bạn đã bắt đầu.
Cách chữa trị cho điều này là tránh di chuyển từng bước một và bị khóa vào các chuỗi phụ thuộc vào đường dẫn. Thay vào đó, nếu bạn có kế hoạch đến thăm toàn bộ chuỗi đường dẫn tổ tiên, trước khi làm bất cứ điều gì khác , hãy tạo một danh sách đầy đủ tất cả các cam kết trong chuỗi:
git rev-list --topo-order --reverse --ancestry-path A..B > /tmp/list-of-commits
Sau đó, truy cập từng cam kết trong danh sách này, từng lần một và bạn sẽ nhận được toàn bộ chuỗi. Điều --topo-ordernày sẽ đảm bảo bạn đạt được - Ivà - Jtheo thứ tự đó, và - Kvà Ltheo thứ tự đó (mặc dù không có cách nào dễ dàng để dự đoán liệu bạn sẽ thực hiện cặp IJ trước hay sau cặp KL).