(Ini dimulai sebagai jawaban untuk pertanyaan rangkap. Saya telah melakukan sedikit penyuntingan ringan untuk membersihkannya.)
Semua panah internal Git adalah satu arah, menunjuk ke belakang. Karena itu tidak ada sintaks yang mudah digunakan untuk bergerak maju: itu tidak mungkin.
Hal ini dimungkinkan untuk "bergerak melawan panah", tetapi cara untuk melakukannya adalah mengejutkan jika Anda belum melihat itu sebelumnya, dan kemudian jelas sesudahnya. Katakanlah kita memiliki:
A <-B <-C <-D <-E <-- last
^
|
\--------- middle
Menggunakan middle~2mengikuti panah dua kali dari Cbelakang ke A. Jadi bagaimana kita beralih dari Cke D? Jawabannya adalah: kita mulai dari E, menggunakan nama last, dan bekerja mundur sampai kita sampai middle, mencatat poin yang kita kunjungi di sepanjang jalan . Kemudian kita hanya bergerak sejauh yang kita inginkan ke arah last: pindah satu langkah ke D, atau dua ke E.
Ini sangat penting ketika kita memiliki cabang:
D--E <-- feature1
/
...--B--C <-- master
\
F--G <-- feature2
Komit mana yang merupakan satu langkah setelahnya C? Tidak ada jawaban yang benar sampai Anda menambahkan pertanyaan: ke arah fitur___ (isi bagian yang kosong).
Untuk menghitung komit antara C(tidak termasuk C) itu sendiri dan, katakanlah G, kami menggunakan:
git rev-list --topo-order --ancestry-path master..feature2
The --topo-ordermerek yakin bahwa bahkan di hadapan kompleks percabangan-dan-penggabungan, komit keluar agar topologically-diurutkan. Ini hanya diperlukan jika rantai tidak linier. The --ancestry-pathberarti kendala bahwa ketika kita bekerja mundur dari feature2, kita hanya daftar commit yang memiliki komit Csebagai salah satu nenek moyang mereka sendiri. Yaitu, jika grafik — atau potongan yang relevan — sebenarnya terlihat seperti ini:
A--B--C <-- master
\ \
\ F--G--J <-- feature2
\ /
H-------I <-- feature3
permintaan sederhana dari formulir feature2..mastermenyebutkan melakukan J, Gdan I, Fdan Hdalam urutan tertentu. Dengan --ancestry-pathkita tersingkir Hdan I: mereka bukan keturunan C, hanya dari A. Dengan --topo-orderkami pastikan bahwa urutan enumerasi yang sebenarnya adalah J, lalu G, kemudian F.
The git rev-listperintah tumpahan ID hash ini keluar pada output standar, satu per baris. Untuk bergerak satu langkah maju ke arah feature2, maka, kami hanya ingin baris terakhir .
Itu mungkin (dan menggoda dan dapat bermanfaat) untuk menambahkan --reversesehingga git rev-listmencetak komit dalam urutan terbalik setelah membuatnya. Ini berfungsi, tetapi jika Anda menggunakannya dalam pipa seperti ini:
git rev-list --topo-order --ancestry-path --reverse <id1>...<id2> | head -1
hanya untuk mendapatkan "komit berikutnya ke arah id2", dan ada daftar komit yang sangat panjang, git rev-listperintah tersebut bisa mendapatkan pipa yang rusak ketika mencoba untuk menulis headyang telah berhenti membaca inputnya dan keluar. Karena kesalahan pipa rusak biasanya diabaikan oleh shell, ini sebagian besar bekerja. Pastikan mereka diabaikan dalam penggunaan Anda .
Itu juga menggoda untuk menambahkan -n 1ke git rev-listperintah, bersama dengan --reverse. Jangan lakukan itu! Itu membuat git rev-listberhenti setelah berjalan satu langkah ke belakang , dan kemudian membalikkan daftar (satu entri) dari komitmen yang dikunjungi. Jadi ini hanya menghasilkan <id2>setiap waktu.
Catatan penting
Perhatikan bahwa dengan fragmen grafik "berlian" atau "cincin benzena":
I--J
/ \
...--H M--... <-- last
\ /
K--L
memindahkan satu komit "maju" dari Hmenuju lastakan membuat Anda baik I atau K . Tidak ada yang dapat Anda lakukan tentang itu: kedua komitmen itu selangkah lebih maju! Jika Anda kemudian mulai dari komit yang dihasilkan dan melangkah ke langkah lain, Anda sekarang berkomitmen pada jalur mana pun yang Anda mulai.
Obat untuk ini adalah menghindari bergerak satu langkah pada satu waktu dan terkunci di rantai yang tergantung jalan. Sebaliknya, jika Anda berencana untuk mengunjungi seluruh rantai jalur leluhur, sebelum melakukan hal lain , buat daftar lengkap semua komitmen dalam rantai:
git rev-list --topo-order --reverse --ancestry-path A..B > /tmp/list-of-commits
Kemudian, kunjungi setiap komit dalam daftar ini, satu per satu, dan Anda akan mendapatkan seluruh rantai. The --topo-orderakan memastikan anda menekan I-dan- Jagar, dan K-dan- Lagar (meskipun tidak ada cara mudah untuk memprediksi apakah Anda akan melakukan pasangan IJ sebelum atau setelah pasangan KL).