(สิ่งนี้เริ่มเป็นคำตอบสำหรับคำถามที่ซ้ำกันฉันได้ทำการแก้ไขเล็กน้อยเพื่อทำความสะอาดแล้ว)
ลูกศรภายในของ Git ทั้งหมดเป็นทางเดียวชี้ไปทางด้านหลัง ดังนั้นจึงไม่มีไวยากรณ์ที่สะดวกสั้น ๆ สำหรับการย้ายไปข้างหน้า: เป็นไปไม่ได้
มีความเป็นไปได้ที่จะ "เคลื่อนตัวเข้าหาลูกศร" แต่วิธีที่จะทำนั้นน่าประหลาดใจหากคุณไม่เคยเห็นมาก่อนและจากนั้นก็เห็นได้ชัดในภายหลัง สมมติว่าเรามี:
A <-B <-C <-D <-E <-- last
^
|
\--------- middle
ใช้middle~2
ต่อไปนี้ลูกศรสองครั้งจากการกลับไปC
A
แล้วเราจะย้ายจากC
ไปยังD
อย่างไร คำตอบคือเราเริ่มต้นที่E
ใช้ชื่อlast
และถอยหลังทำงานจนกว่าเราจะได้รับการmiddle
, การบันทึกจุดที่เราแวะไปพร้อมกัน จากนั้นเราก็ย้ายไปเท่าที่เราต้องการในทิศทางของlast
: ย้ายขั้นตอนหนึ่งไปหรือสองD
E
สิ่งนี้สำคัญอย่างยิ่งเมื่อเรามีสาขา:
D--E <-- feature1
/
...--B--C <-- master
\
F--G <-- feature2
ซึ่งกระทำการเป็นหนึ่งในขั้นตอนหลังจากที่C
? ไม่มีคำตอบที่ถูกต้องจนกว่าคุณจะเพิ่มคำถาม: ในทิศทางของ feature___ (เติมในช่องว่าง)
ในการระบุการกระทำระหว่างC
(ไม่รวมC
) ตัวเองและ, พูดG
, เราใช้:
git rev-list --topo-order --ancestry-path master..feature2
--topo-order
ทำให้แน่ใจว่าแม้ในที่ที่มีความซับซ้อนแตกแขนงและผสานการกระทำออกมาเพื่อทอพอโลยีเรียง สิ่งนี้จำเป็นเฉพาะในกรณีที่โซ่ไม่เป็นเชิงเส้น --ancestry-path
จำกัด หมายความว่าเมื่อเราทำงานย้อนกลับจากfeature2
เราเท่านั้นที่กระทำรายการที่มีการกระทำC
เป็นหนึ่งในบรรพบุรุษของตัวเอง นั่นคือถ้ากราฟ - หรืออันที่เกี่ยวข้องของมัน - จริง ๆ แล้วมีลักษณะเช่นนี้:
A--B--C <-- master
\ \
\ F--G--J <-- feature2
\ /
H-------I <-- feature3
คำขอที่เรียบง่ายของแบบฟอร์มfeature2..master
ระบุกระทำJ
, G
และI
และF
และH
ในการสั่งซื้อบางส่วน ด้วย--ancestry-path
เราเคาะออกH
และI
พวกเขาไม่ได้เป็นลูกหลานของเพียงของC
A
ด้วย--topo-order
เราให้แน่ใจว่าการสั่งการแจงนับจริงJ
แล้วนั้นG
F
git rev-list
คำสั่งรั่วไหลรหัสกัญชาเหล่านี้ออกจากการส่งออกมาตรฐานของตนต่อหนึ่งบรรทัด หากต้องการเลื่อนไปหนึ่งก้าวไปข้างหน้าตามทิศทางของfeature2
เราก็แค่ต้องการบรรทัดสุดท้าย
เป็นไปได้ (และดึงดูดและมีประโยชน์) ในการเพิ่ม--reverse
เพื่อให้git rev-list
พิมพ์คำสั่งในลำดับที่กลับรายการหลังจากสร้างพวกเขา มันใช้งานได้ แต่ถ้าคุณใช้มันในไปป์ไลน์แบบนี้:
git rev-list --topo-order --ancestry-path --reverse <id1>...<id2> | head -1
เพื่อให้ได้รับ "ส่งมอบครั้งต่อไปในทิศทางของ id2" และมีรายการที่ยาวมากของgit rev-list
คำสั่งคำสั่งสามารถรับไปป์ที่ขาดเมื่อพยายามเขียนhead
ซึ่งหยุดอ่านอินพุตและออก เนื่องจากโดยปกติแล้วเชลล์จะละเว้นข้อผิดพลาดที่ขาดไปจึงมักใช้งานได้ เพียงตรวจสอบให้แน่ใจว่ามันถูกละเว้นในการใช้งานของคุณ
นอกจากนี้ยังดึงดูดให้เพิ่ม-n 1
ไปที่คำสั่งพร้อมกับgit rev-list
--reverse
อย่าทำมัน! ที่ทำให้git rev-list
หยุดชะงักหลังจากที่เดินหนึ่งก้าวกลับมาแล้วกลับรายการ (ขาเข้า) ของกระทำเยี่ยมชม ดังนั้นนี่ผลิตออกมา<id2>
ทุกครั้ง
ข้อความด้านที่สำคัญ
โปรดทราบว่าด้วยส่วนของกราฟ "diamond" หรือ "benzene ring":
I--J
/ \
...--H M--... <-- last
\ /
K--L
ย้ายหนึ่งกระทำ "ไปข้างหน้า" จากH
ที่มีต่อlast
คุณจะได้รับอย่างใดอย่างหนึ่ง หรือI
K
ไม่มีอะไรที่คุณสามารถทำได้เกี่ยวกับสิ่งนั้น: การกระทำทั้งสองเป็นขั้นตอนเดียว ถ้าคุณเริ่มจากการกระทำที่เกิดขึ้นและไปอีกขั้นตอนหนึ่งตอนนี้คุณต้องยอมรับว่าคุณเริ่มต้นเส้นทางไหน
การรักษานี้คือการหลีกเลี่ยงการย้ายทีละขั้นตอนและล็อคเข้ากับโซ่ขึ้นอยู่กับเส้นทาง แต่ถ้าคุณวางแผนที่จะเยี่ยมชมโซ่ของเส้นทางบรรพบุรุษทั้งหมดก่อนที่จะทำอะไรให้ทำรายการทั้งหมดของพันธะสัญญาทั้งหมด:
git rev-list --topo-order --reverse --ancestry-path A..B > /tmp/list-of-commits
จากนั้นไปที่แต่ละการกระทำในรายการนี้ทีละครั้งและคุณจะได้รับห่วงโซ่ทั้งหมด --topo-order
จะให้แน่ใจว่าคุณจะตีI
โทโพโลยีJ
ในการสั่งซื้อนั้นและK
โทโพโลยีL
ในลำดับที่ (แม้ว่าจะไม่มีวิธีที่ง่ายต่อการคาดการณ์ว่าคุณจะทำคู่ IJ ก่อนหรือหลังคู่ KL)