ref^
mengacu pada komit sebelumnya ref
, bagaimana dengan mendapatkan komit setelah ref
?
Misalnya, jika saya git checkout 12345
bagaimana cara memeriksa komit berikutnya?
Terima kasih.
PS Ya, git adalah pohon pointer DAG pointer struct apa pun. Bagaimana saya menemukan komit setelah ini?
git
version-control
Schwern
sumber
sumber
git children-of
"!Jawaban:
Untuk membuat daftar semua komit, mulai dari yang sekarang, dan kemudian anaknya, dan seterusnya - pada dasarnya git log standar, tetapi sebaliknya, gunakan sesuatu seperti
di mana 894e8b4e93d8f3 adalah komit pertama yang ingin Anda tunjukkan.
sumber
HEAD^
untuk894e8b4e93d8f3^
....
,^..
gagal diamfatal: unrecognized argument: --ancestry-path
git versi 1.7.1master
berada di jalur leluhur dari komit saat ini. Lihat cuplikan kode kedua jawaban saya untuk solusi yang akan berfungsi dalam semua kasus.Pembuat Hudson (sekarang Jenkins) Kohsuke Kawaguchi baru saja menerbitkan (November 2013):
kohsuke / git-children-of :
Seperti yang diilustrasikan oleh utas ini , dalam VCS berdasarkan pada sejarah yang diwakili oleh DAG (Directed Acyclic Graph) , tidak ada "satu orangtua" atau "satu anak".
Pemesanan komit dilakukan oleh "topo-order" atau "date-order" (lihat buku GitPro )
Tetapi sejak Git1.6.0 , Anda dapat mendaftar anak-anak dari sebuah komit.
Catatan: untuk komit induk , Anda memiliki masalah yang sama, dengan akhiran
^
ke parameter revisi yang berarti induk pertama dari objek komit tersebut.^<n>
berarti<n>
induk th (yaiturev^
setara denganrev^1
).Jika Anda berada di cabang
foo
dan mengeluarkan "git merge bar
" makafoo
akan menjadi orang tua pertama.Yaitu: Orang tua pertama adalah cabang tempat Anda bergabung saat Anda bergabung, dan yang kedua adalah komit di cabang tempat Anda bergabung.
sumber
git rev-list --children
tentu terlihat seperti apa yang saya inginkan, tetapi tidak DWIM. Tampaknya daftar semua orang tua dan anak-anak mereka. Saya kira saya bisa daftar mereka semua dan menguraikannya ... bleh, tapi itu sesuatu.git rev-list --children
bukan untuk daftar anak-anak saja, tetapi untuk daftar orang tua dengan anak-anak mereka ... Anda selalu perlu menguraikan.$ git children0of 9dd5932
fatal: No annotated tags can describe '71d7b5dd89d241072a0a078ff2c7dfec05d52e1f'.
However, there were unannotated tags: try --tags.
Output apa yang Anda dapatkan?git-children-of
itu menggunakan git menggambarkan bahwa upaya untuk memformat SHA sebagai yang dapat dibaca manusia, yang dapat gagal dengan kesalahan @ TomHale, dan memberikan hasil sepertiv1.0.4-14-g2414721
yang membingungkan jika Anda mengharapkan SHA. Menggantinya dengan yang sederhanaecho
menjadikan alat ini luar biasa, terima kasih!apa yang saya temukan adalah
di mana saya menetapkan
commit1
sebagai komit saat ini dancommit2
ke kepala saat ini. Ini mengembalikan saya daftar semua komit yang membangun jalur antaracommit1
dancommit2
.Baris terakhir dari output adalah anak dari commit1 (di jalan menuju commit2).
sumber
| tail -1
untuk mendapatkan anak.Aku tahu apa yang kamu maksud. Sangat frustasi memiliki sintaks yang berlimpah untuk pergi ke komit sebelumnya, tetapi tidak ada yang pergi ke yang berikutnya. Dalam sejarah yang kompleks, masalah "apa komitmen selanjutnya" menjadi agak sulit, tetapi kemudian dalam penggabungan yang rumit kekerasan yang sama muncul dengan komitmen 'sebelumnya' juga. Dalam kasus sederhana, di dalam cabang tunggal dengan sejarah linier (bahkan hanya secara lokal untuk beberapa komit) akan lebih baik dan masuk akal untuk maju dan mundur.
Masalah sebenarnya dengan ini, bagaimanapun, adalah bahwa anak-anak yang melakukan tidak dirujuk, itu hanya daftar yang terhubung ke belakang. Menemukan komit anak membutuhkan pencarian, yang tidak terlalu buruk, tetapi mungkin bukan sesuatu yang git ingin masukkan ke dalam logika refspec.
Bagaimanapun, saya menemukan pertanyaan ini karena saya hanya ingin melangkah maju dalam sejarah satu komitmen pada satu waktu, melakukan tes, dan kadang-kadang Anda harus melangkah maju dan tidak mundur. Nah, dengan lebih banyak pemikiran saya datang dengan solusi ini:
Pilih komitmen di depan di mana Anda berada. Ini mungkin bisa menjadi kepala cabang. Jika Anda berada di cabang ~ 10, maka "git checkout branch ~ 9" lalu "git checkout branch ~ 8" untuk mendapatkan yang berikutnya setelah itu, kemudian "git checkout branch ~ 7" dan seterusnya.
Mengurangi angka harus benar-benar mudah dalam sebuah skrip jika Anda membutuhkannya. Jauh lebih mudah daripada mem-parsing daftar git.
sumber
BRANCH=master; git co $BRANCH~$[ $(git rev-list HEAD..$BRANCH | wc -l) - 1 ]
" Anda harus pergi ke cabang, tidak ada jalan lain.Dua jawaban praktis:
Satu anak
Berdasarkan jawaban @ Michael , saya meretas
child
alias di blog saya.gitconfig
.Ini berfungsi seperti yang diharapkan pada case default, dan juga serbaguna.
Secara default memberikan anak HEAD (kecuali argumen komit-ish lain diberikan) dengan mengikuti leluhur satu langkah menuju ujung cabang saat ini (kecuali komit-ish lain diberikan sebagai argumen kedua).
Gunakan
%h
sebagai ganti%H
jika Anda menginginkan bentuk hash pendek.Banyak anak
Dengan KEPALA terpisah (tidak ada cabang) atau untuk mendapatkan semua anak terlepas dari cabang:
Ubah
$1
ke$*
untuk mencetak semua anak.Anda juga dapat mengubah
--all
ke komit untuk menampilkan hanya anak-anak yang merupakan leluhur dari komit itu - dengan kata lain, untuk menampilkan hanya anak-anak "ke arah" komit yang diberikan. Ini dapat membantu Anda mempersempit hasil dari banyak anak menjadi hanya satu.sumber
Tidak ada "komitmen berikutnya" yang unik. Karena sejarah di Git adalah DAG, dan bukan garis, banyak komit dapat memiliki induk (cabang) yang sama, dan komit dapat memiliki lebih dari satu induk (gabungan).
Jika Anda memiliki cabang tertentu, Anda dapat melihat log-nya dan melihat komit mana yang mencantumkan yang sekarang sebagai induknya.
sumber
<rev>^
adalah "parent commit" ('parent pertama' untuk gabungan komit).Saya sudah mencoba berbagai solusi dan tidak ada yang berhasil untuk saya. Harus datang dengan milikku.
temukan komit berikutnya
temukan komit sebelumnya
sumber
Dalam kasus di mana Anda tidak memiliki "tujuan" komit tertentu dalam pikiran, tetapi alih-alih ingin melihat commit anak yang mungkin ada di cabang mana pun , Anda dapat menggunakan perintah ini:
Jika Anda ingin melihat semua anak dan cucu , Anda harus menggunakan
rev-list --children
secara rekursif, seperti:(Versi yang hanya memberi cucu akan menggunakan yang lebih kompleks
sed
dan / ataucut
.)Akhirnya, Anda bisa memasukkannya ke dalam
log --graph
perintah untuk melihat struktur pohon, seperti:Catatan : semua perintah di atas menganggap bahwa Anda telah menetapkan variabel shell
${COMMIT}
ke beberapa referensi (cabang, tag, sha1) dari commit yang anak-anaknya Anda minati.sumber
${COMMIT}
tidak esist, tetapi Anda bisa menggunakan$(git rev-parse HEAD)
sebagai gantinya${COMMIT}
.(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:
Menggunakan
middle~2
mengikuti panah dua kali dariC
belakang keA
. Jadi bagaimana kita beralih dariC
keD
? Jawabannya adalah: kita mulai dariE
, menggunakan namalast
, dan bekerja mundur sampai kita sampaimiddle
, mencatat poin yang kita kunjungi di sepanjang jalan . Kemudian kita hanya bergerak sejauh yang kita inginkan ke arahlast
: pindah satu langkah keD
, atau dua keE
.Ini sangat penting ketika kita memiliki cabang:
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 termasukC
) itu sendiri dan, katakanlahG
, kami menggunakan:The
--topo-order
merek yakin bahwa bahkan di hadapan kompleks percabangan-dan-penggabungan, komit keluar agar topologically-diurutkan. Ini hanya diperlukan jika rantai tidak linier. The--ancestry-path
berarti kendala bahwa ketika kita bekerja mundur darifeature2
, kita hanya daftar commit yang memiliki komitC
sebagai salah satu nenek moyang mereka sendiri. Yaitu, jika grafik — atau potongan yang relevan — sebenarnya terlihat seperti ini:permintaan sederhana dari formulir
feature2..master
menyebutkan melakukanJ
,G
danI
,F
danH
dalam urutan tertentu. Dengan--ancestry-path
kita tersingkirH
danI
: mereka bukan keturunanC
, hanya dariA
. Dengan--topo-order
kami pastikan bahwa urutan enumerasi yang sebenarnya adalahJ
, laluG
, kemudianF
.The
git rev-list
perintah tumpahan ID hash ini keluar pada output standar, satu per baris. Untuk bergerak satu langkah maju ke arahfeature2
, maka, kami hanya ingin baris terakhir .Itu mungkin (dan menggoda dan dapat bermanfaat) untuk menambahkan
--reverse
sehinggagit rev-list
mencetak komit dalam urutan terbalik setelah membuatnya. Ini berfungsi, tetapi jika Anda menggunakannya dalam pipa seperti ini:hanya untuk mendapatkan "komit berikutnya ke arah id2", dan ada daftar komit yang sangat panjang,
git rev-list
perintah tersebut bisa mendapatkan pipa yang rusak ketika mencoba untuk menulishead
yang 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 1
kegit rev-list
perintah, bersama dengan--reverse
. Jangan lakukan itu! Itu membuatgit rev-list
berhenti 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":
memindahkan satu komit "maju" dari
H
menujulast
akan membuat Anda baikI
atauK
. 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:
Kemudian, kunjungi setiap komit dalam daftar ini, satu per satu, dan Anda akan mendapatkan seluruh rantai. The
--topo-order
akan memastikan anda menekanI
-dan-J
agar, danK
-dan-L
agar (meskipun tidak ada cara mudah untuk memprediksi apakah Anda akan melakukan pasangan IJ sebelum atau setelah pasangan KL).sumber
Saya memiliki alias ini di
~/.gitconfig
sumber
f()
? Dan itu harushead -1
menjadi anak pertama, kalau tidak ini hanya akan melaporkan KEPALA.f()
. Ya,head -1
itu dugaan berani.nextref = "!f() { git log --reverse --ancestry-path --pretty=%H $1..HEAD | head -${2:-1} | tail -1; }; f"
sehingga Anda dapat memilih seberapa jauh ke depan, secara opsionalSaya berhasil menemukan anak berikutnya dengan cara berikut:
sumber
Jika anak melakukan semua pada beberapa cabang, Anda dapat menggunakan
gitk --all commit^..
, di mana "komit" adalah sesuatu yang mengidentifikasi komit. Misalnya, jika komit yang disingkat SHA-1 adalah c6661c5, maka ketikkangitk --all c6661c5^..
Anda mungkin perlu memasukkan SHA-1 lengkap ke dalam sel "SHA1 ID:" gitk. Anda memerlukan SHA-1 lengkap, yang untuk contoh ini dapat diperoleh via
git rev-parse c6661c5
Atau,
git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d'
akan menghasilkan garis yang berisi semua anak dari komit ini, mungkin apakah ada cabang yang terlibat atau tidak.sumber
Setiap komit menyimpan pointer ke induknya (orang tua, jika komit gabungan (standar)).
Jadi, tidak ada cara untuk menunjuk ke seorang anak melakukan (jika ada) dari orang tua.
sumber
Posting ini ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 ) menunjukkan cara yang rapi jika melakukannya jika Anda dapat membuat tag yang terdefinisi dengan baik di akhir tumpukan komit Anda. Pada dasarnya di
git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`'
mana "demo-end" adalah tag terakhir.sumber
Jawaban yang ada mengasumsikan bahwa Anda memiliki cabang yang berisi komit yang Anda cari.
Dalam kasus saya, komit yang saya cari tidak ada
git rev-list --all
karena tidak ada cabang yang memuatnya.Saya akhirnya mencari
gitk --reflog
secara manual.Jika Anda tidak dapat menemukan komit Anda di reflog, cobalah:
git fsck --full
untuk membuat daftar dangling (mis. tidak di cabang mana pun) berkomitmen, ataugit fsck --lost-found
untuk membuat referensi yang menunjuk ke menggantung komitmen untuk menerapkan teknik di jawaban lain.sumber