Saya memiliki repositori dengan cabang master dan A dan banyak aktivitas penggabungan antara keduanya. Bagaimana saya bisa menemukan komit di repositori saya ketika cabang A dibuat berdasarkan master?
Repositori saya pada dasarnya terlihat seperti ini:
-- X -- A -- B -- C -- D -- F (master)
\ / \ /
\ / \ /
G -- H -- I -- J (branch A)
Saya mencari revisi A, yang bukan yang git merge-base (--all)
ditemukan.
Jawaban:
Saya mencari hal yang sama, dan saya menemukan pertanyaan ini. Terima kasih telah menanyakannya!
Namun, saya menemukan bahwa jawaban yang saya lihat di sini tampaknya tidak cukup memberikan jawaban yang Anda minta (atau yang saya cari) - mereka tampaknya memberikan
G
komit, bukanA
komit.Jadi, saya telah membuat pohon berikut (surat-surat yang diberikan dalam urutan kronologis), sehingga saya dapat menguji berbagai hal:
Ini terlihat sedikit berbeda dari milik Anda, karena saya ingin memastikan bahwa saya mendapat (mengacu pada grafik ini, bukan milik Anda) B, tetapi bukan A (dan bukan D atau E). Berikut adalah surat-surat yang dilampirkan pada awalan SHA dan komit pesan (repo saya dapat dikloning dari sini , jika itu menarik bagi siapa pun):
Jadi, tujuan: menemukan B . Berikut adalah tiga cara yang saya temukan, setelah sedikit mengutak-atik:
1. secara visual, dengan gitk:
Anda harus melihat secara visual pohon seperti ini (seperti yang dilihat dari master):
atau di sini (dilihat dari topik):
dalam kedua kasus, saya telah memilih komit yang ada
B
di grafik saya. Setelah Anda mengkliknya, SHA lengkapnya disajikan dalam bidang input teks tepat di bawah grafik.2. secara visual, tetapi dari terminal:
git log --graph --oneline --all
(Edit / catatan tambahan: menambahkan
--decorate
juga bisa menarik; menambahkan indikasi nama cabang, tag, dll. Tidak menambahkan ini ke baris perintah di atas karena output di bawah ini tidak mencerminkan penggunaannya.)yang menunjukkan (dengan asumsi
git config --global color.ui auto
):Atau, dalam teks langsung:
dalam kedua kasus, kita melihat 6aafd7f komit sebagai titik umum terendah, yaitu
B
di grafik saya, atauA
di Anda.3. Dengan shell magic:
Anda tidak menentukan dalam pertanyaan Anda apakah Anda menginginkan sesuatu seperti di atas, atau satu perintah yang hanya akan membuat Anda satu revisi, dan tidak ada yang lain. Nah, ini yang terakhir:
Yang juga bisa Anda masukkan ke ~ / .gitconfig Anda (catatan: trailing dash itu penting; terima kasih Brian karena telah memperhatikan itu) :
Yang dapat dilakukan melalui baris perintah berikut (berbelit-belit dengan mengutip):
Catatan:
zsh
bisa saja dengan mudahbash
, tetapi tidaksh
akan berfungsi - sintaksisnya tidak ada di vanilla . (Sekali lagi terima kasih, @conny, karena membuat saya menyadarinya dalam komentar tentang jawaban lain di halaman ini!)<()
sh
Catatan: Versi alternatif di atas:
Berkat liori untuk menunjukkan bahwa di atas bisa jatuh ketika membandingkan cabang identik, dan muncul dengan bentuk diff alternatif yang menghilangkan bentuk sed dari campuran, dan membuat ini "lebih aman" (yaitu mengembalikan hasil (yaitu, komit terbaru) bahkan ketika Anda membandingkan master ke master):
Sebagai baris .git-config:
Dari shell:
Jadi, di pohon tes saya (yang tidak tersedia untuk sementara waktu, maaf; sudah kembali), yang sekarang bekerja pada master dan topik (masing-masing memberikan komit G dan B). Terima kasih lagi, liori, untuk formulir alternatif.
Jadi, itulah yang saya [dan liori] buat. Tampaknya bekerja untuk saya. Itu juga memungkinkan beberapa alias tambahan yang mungkin berguna:
Selamat git!
sumber
diff
's if-then-else modus dan menghapus berubah / dihapus baris dari output bukannya menghitung pada memiliki konteks yang cukup besar, oleh.:diff --old-line-format='' --new-line-format='' <(git rev-list …) <(git rev-list …)|head -1
.git log -n1 --format=format:%H $(git log --reverse --format=format:%H master..topic | head -1)~
akan bekerja juga, saya pikirgit merge-base --fork-point ...
memberi commit B (commit6aafd7f
) untuk pohon ini? Saya sedang sibuk dengan hal-hal lain ketika Anda memposting itu, dan itu terdengar bagus, tapi akhirnya saya mencobanya, dan saya tidak membuatnya berfungsi ... Saya juga mendapatkan sesuatu yang lebih baru, atau hanya gagal diam (tidak ada kesalahan) pesan, namun status keluar 1), berusaha argumen sepertigit co master; git merge-base --fork-point topic
,git co topic; git merge-base --fork-point master
,git merge-base --fork-point topic master
(baik untuk checkout), dll Apakah ada sesuatu yang saya lakukan salah atau hilang?--fork-point
didasarkan pada reflog, jadi itu hanya akan berfungsi jika Anda membuat perubahan secara lokal. Meskipun begitu, entri reflog dapat kedaluwarsa. Ini berguna tetapi tidak dapat diandalkan sama sekali.Anda mungkin mencari
git merge-base
:sumber
--all
opsi untuk "git merge-base
"git merge-base
lima jam setelah jawaban saya diposting (mungkin sebagai jawaban atas jawaban saya). Namun demikian, saya akan membiarkan jawaban ini apa adanya karena mungkin masih bermanfaat bagi orang lain yang menemukan pertanyaan ini melalui pencarian.Saya sudah terbiasa
git rev-list
dengan hal semacam ini. Misalnya, (perhatikan 3 titik)akan memuntahkan titik cabang. Sekarang, itu tidak sempurna; karena Anda telah menggabungkan master ke cabang A beberapa kali, itu akan membagi beberapa kemungkinan poin cabang (pada dasarnya, titik cabang asli dan kemudian setiap titik di mana Anda menggabungkan master ke cabang A). Namun, setidaknya harus mempersempit kemungkinan.
Saya telah menambahkan perintah itu ke alias saya
~/.gitconfig
sebagai:jadi saya bisa menyebutnya sebagai:
sumber
G
bukanA
, per grafik dalam pertanyaan asli.) Saya punya jawaban yang didapatA
, bahwa saya akan memposting saat ini.git checkout topic
kemudian menjalankannya dengantopic
di tempatbranch-a
), ia mencantumkan648ca357b946939654da12aaf2dc072763f3caee
dan37ad15952db5c065679d7fc31838369712f0b338
- keduanya37ad159
dan648ca35
berada dalam leluhur cabang saat ini (yang terakhir adalah kepala KEPALA saat initopic
), tetapi tidak ada titik sebelum percabangan terjadi. Apakah Anda mendapatkan sesuatu yang berbeda?Jika Anda suka perintah singkat,
Berikut penjelasannya.
Perintah berikut memberi Anda daftar semua komit di master yang terjadi setelah branch_name dibuat
Karena Anda hanya peduli tentang komitmen paling awal, Anda ingin baris terakhir dari output:
Induk dari komit paling awal yang bukan nenek moyang dari "branch_name" adalah, menurut definisi, dalam "branch_name," dan berada di "master" karena itu merupakan leluhur dari sesuatu dalam "master." Jadi, Anda memiliki komit paling awal yang ada di kedua cabang.
Perintah
hanyalah cara untuk menunjukkan referensi komit induk. Anda bisa menggunakannya
atau terserah.
PS: Saya tidak setuju dengan argumen bahwa tatanan leluhur tidak relevan. Tergantung pada apa yang Anda inginkan. Misalnya, dalam hal ini
masuk akal untuk menghasilkan C2 sebagai komit "percabangan". Ini terjadi ketika pengembang keluar dari "master." Ketika dia bercabang, cabang "B" bahkan tidak bergabung di cabangnya! Inilah yang diberikan oleh solusi dalam posting ini.
Jika yang Anda inginkan adalah komit C terakhir sehingga semua jalur dari asal ke komit terakhir di cabang "A" melewati C, maka Anda ingin mengabaikan urutan leluhur. Itu murni topologi dan memberi Anda ide sejak saat Anda memiliki dua versi kode yang berjalan pada saat yang sama. Saat itulah Anda akan menggunakan pendekatan berbasis gabungan, dan itu akan mengembalikan C1 dalam contoh saya.
sumber
git rev-list commit^^!
dapat disederhanakan sebagaigit rev-parse commit^
git rev-list --first-parent ^branch_name master
dengangit rev-list --first-parent branch_name ^master
karena jika cabang master 0 berkomitmen di depan cabang lain (fast-forwardable untuk itu), tidak ada output yang akan dibuat. Dengan solusi saya, tidak ada output yang dibuat jika master benar-benar di depan (yaitu cabang telah sepenuhnya digabung), itulah yang saya inginkan.git rev-list --first-parent ^topic master
hanya akan membawa Anda kembali ke komit pertama setelah penggabungan terakhir darimaster
ketopic
(jika itu ada).Mengingat begitu banyak jawaban di utas ini tidak memberikan jawaban yang ditanyakan oleh pertanyaan itu, berikut adalah ringkasan hasil dari setiap solusi, bersama dengan skrip yang saya gunakan untuk mereplikasi repositori yang diberikan dalam pertanyaan.
Log
Membuat repositori dengan struktur yang diberikan, kita mendapatkan log git dari:
Satu-satunya tambahan saya, adalah tag yang membuatnya eksplisit tentang titik di mana kami membuat cabang dan dengan demikian komit yang ingin kami temukan.
Solusi yang berhasil
Satu-satunya solusi yang berfungsi adalah yang disediakan oleh lindes dengan benar mengembalikan
A
:Seperti yang ditunjukkan Charles Bailey , solusi ini sangat rapuh.
Jika Anda
branch_A
ke dalammaster
dan kemudian menggabungkanmaster
ke dalambranch_A
tanpa intervensi komit maka solusi Lindes' hanya memberi Anda terbaru pertama divergance .Itu berarti bahwa untuk alur kerja saya, saya pikir saya harus tetap dengan menandai titik cabang dari cabang yang sudah berjalan lama, karena saya tidak dapat menjamin bahwa mereka dapat ditemukan nanti.
Ini benar-benar semua bermuara
git
s kurang dari apa yanghg
disebutnya bernama cabang . Blogger jhw menyebut garis keturunan ini vs. keluarga dalam artikelnya Why I Like Mercurial More Than Git dan artikel lanjutannya More On Mercurial vs. Git (dengan Grafik!) . Saya akan merekomendasikan orang membaca mereka untuk melihat mengapa beberapa mualaf lincah rindu tidak memiliki nama cabang digit
.Solusi yang tidak berhasil
Solusi yang diberikan oleh mipadi menghasilkan dua jawaban,
I
danC
:Solusi yang diberikan oleh Greg Hewgill kembali
I
Solusi yang diberikan oleh Karl kembali
X
:Naskah
Saya ragu versi git membuat banyak perbedaan untuk ini, tetapi:
Terima kasih kepada Charles Bailey karena telah menunjukkan kepada saya cara yang lebih ringkas untuk membuat skrip contoh repositori.
sumber
diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1
. Terima kasih telah memberikan instruksi untuk membuat repo :)Secara umum, ini tidak mungkin. Dalam sejarah cabang, cabang-dan-merger sebelum cabang bernama bercabang dan cabang perantara dari dua cabang bernama terlihat sama.
Di git, cabang hanyalah nama terkini dari ujung bagian sejarah. Mereka tidak benar-benar memiliki identitas yang kuat.
Ini biasanya bukan masalah besar karena basis gabungan (lihat jawaban Greg Hewgill) dari dua commit biasanya jauh lebih bermanfaat, memberikan komit terbaru yang dibagikan oleh kedua cabang.
Solusi yang mengandalkan urutan orang tua dari komit jelas tidak akan berfungsi dalam situasi di mana cabang telah sepenuhnya terintegrasi pada beberapa titik dalam sejarah cabang.
Teknik ini juga jatuh jika gabungan integrasi telah dibuat dengan orang tua terbalik (misalnya cabang sementara digunakan untuk melakukan uji gabungan menjadi master dan kemudian diteruskan ke cabang fitur untuk membangun lebih jauh).
sumber
git
memilikihg
cabang yang setara dengan yang bernama, itu akan membuat mengelola cabang pemeliharaan yang berumur panjang jadi lebih mudah.Bagaimana dengan sesuatu seperti
sumber
diverges = !bash -c 'git rev-parse $(diff <(git log --pretty=oneline ${1}) <(git log --pretty=oneline ${2}) | tail -1 | cut -c 3-42)^'
(tanpa file sementara)G
bukanA
, per grafik dalam pertanyaan asli.) Saya pikir saya telah menemukan jawaban, yang akan saya posting saat ini.diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1
pasti saya melewatkan sesuatu, tetapi IMO, semua masalah di atas disebabkan karena kami selalu berusaha menemukan titik cabang kembali dalam sejarah, dan itu menyebabkan semua jenis masalah karena kombinasi penggabungan yang tersedia.
Alih-alih, saya telah mengikuti pendekatan yang berbeda, berdasarkan fakta bahwa kedua cabang memiliki banyak sejarah, persis semua sejarah sebelum bercabang adalah 100% sama, jadi alih-alih kembali, proposal saya adalah tentang maju (dari tanggal 1). commit), mencari perbedaan pertama di kedua cabang. Titik cabang akan, sederhananya, induk dari perbedaan pertama yang ditemukan.
Dalam praktek:
Dan itu menyelesaikan semua kasus saya yang biasa. Tentu ada perbatasan yang tidak tertutup tapi ... ciao :-)
sumber
comm --nocheck-order -1 -2 <(git rev-list --reverse --topo-order topic) <(git rev-list --reverse --topo-order master) | head -1
Saya baru-baru ini perlu menyelesaikan masalah ini juga dan akhirnya menulis skrip Ruby untuk ini: https://github.com/vaneyckt/git-find-branching-point
sumber
Setelah banyak penelitian dan diskusi, jelas tidak ada peluru ajaib yang akan berfungsi dalam semua situasi, setidaknya tidak dalam versi Git saat ini.
Itu sebabnya saya menulis beberapa tambalan yang menambahkan konsep
tail
cabang. Setiap kali cabang dibuat, pointer ke titik awal juga dibuat,tail
ref. Ref ini diperbarui setiap kali cabang ditata ulang.Untuk mengetahui titik cabang dari cabang devel, yang harus Anda lakukan adalah menggunakan
devel@{tail}
, itu saja.https://github.com/felipec/git/commits/fc/tail
sumber
Berikut ini adalah versi perbaikan dari jawaban sebelumnya saya jawaban sebelumnya . Itu bergantung pada pesan komit dari gabungan untuk menemukan di mana cabang pertama kali dibuat.
Ini bekerja pada semua repositori yang disebutkan di sini, dan saya bahkan telah membahas beberapa yang rumit yang muncul di milis . Saya juga menulis tes untuk ini.
sumber
Perintah berikut akan mengungkapkan SHA1 dari Komit A
git merge-base --fork-point A
sumber
Saya sepertinya senang
Baris terakhir yang Anda dapatkan adalah komit pertama di cabang, jadi itu masalah mendapatkan induk dari itu. Begitu
Tampaknya bekerja untuk saya dan tidak perlu diff dan sebagainya (yang membantu karena kami tidak memiliki versi diff)
Koreksi: Ini tidak berfungsi jika Anda berada di cabang master, tapi saya melakukan ini dalam skrip sehingga itu tidak menjadi masalah
sumber
Untuk menemukan komit dari titik percabangan, Anda bisa menggunakan ini.
sumber
Kadang-kadang secara efektif tidak mungkin (dengan beberapa pengecualian di mana Anda mungkin beruntung memiliki data tambahan) dan solusi di sini tidak akan berfungsi.
Git tidak menyimpan riwayat referensi (termasuk cabang). Hanya menyimpan posisi saat ini untuk setiap cabang (kepala). Ini berarti Anda dapat kehilangan beberapa sejarah cabang di git seiring waktu. Setiap kali Anda bercabang misalnya, segera hilang cabang mana yang asli. Semua yang dilakukan cabang adalah:
Anda mungkin berasumsi bahwa komitmen pertama adalah cabang. Ini cenderung menjadi masalah tetapi tidak selalu demikian. Tidak ada yang menghentikan Anda dari melakukan ke salah satu cabang terlebih dahulu setelah operasi di atas. Selain itu, cap waktu git tidak dijamin dapat diandalkan. Tidak sampai Anda berkomitmen untuk keduanya bahwa mereka benar-benar menjadi cabang secara struktural.
Sementara dalam diagram kita cenderung melakukan angka secara konseptual, git tidak memiliki konsep sekuens yang stabil ketika pohon komit bercabang. Dalam hal ini Anda dapat menganggap angka-angka (urutan menunjukkan) ditentukan oleh cap waktu (mungkin menyenangkan untuk melihat bagaimana UI git menangani hal-hal ketika Anda mengatur semua cap waktu menjadi sama).
Inilah yang manusia harapkan secara konseptual:
Inilah yang sebenarnya Anda dapatkan:
Anda akan menganggap B1 sebagai cabang asli tetapi itu bisa benar-benar menjadi cabang mati (seseorang melakukan checkout -b tetapi tidak pernah berkomitmen untuk itu). Baru setelah Anda berkomitmen untuk keduanya Anda mendapatkan struktur cabang yang sah dalam git:
Anda selalu tahu bahwa C1 datang sebelum C2 dan C3 tetapi Anda tidak pernah andal tahu jika C2 datang sebelum C3 atau C3 datang sebelum C2 (karena Anda dapat mengatur waktu di workstation Anda dengan apa pun misalnya). B1 dan B2 juga menyesatkan karena Anda tidak tahu cabang mana yang lebih dulu. Anda dapat membuat tebakan yang sangat bagus dan biasanya akurat dalam banyak kasus. Ini agak seperti trek balap. Semua hal umumnya sama dengan mobil maka Anda dapat mengasumsikan bahwa mobil yang datang di pangkuan mulai pangkuan di belakang. Kami juga memiliki konvensi yang sangat andal, misalnya master akan hampir selalu mewakili cabang yang paling lama hidup meskipun sayangnya saya telah melihat kasus di mana bahkan ini tidak terjadi.
Contoh yang diberikan di sini adalah contoh pelestarian sejarah:
Nyata di sini juga menyesatkan karena kita sebagai manusia membacanya dari kiri ke kanan, root to leaf (ref). Git tidak melakukan itu. Di mana kita melakukan (A-> B) di kepala kita git (A <-B atau B-> A). Bunyinya dari ref ke root. Ac bisa di mana saja tetapi cenderung daun, setidaknya untuk cabang aktif. Seorang ref menunjuk ke sebuah komit dan melakukan hanya berisi suka kepada orang tua mereka, bukan untuk anak-anak mereka. Ketika komit adalah gabungan komit, komit akan memiliki lebih dari satu orangtua. Orang tua pertama selalu merupakan komit asli yang digabungkan. Orang tua lain selalu melakukan komitmen yang digabungkan ke dalam komitmen asli.
Ini bukan representasi yang sangat efisien, melainkan ekspresi dari semua jalur yang dapat diambil git dari setiap referensi (B1 dan B2).
Penyimpanan internal Git lebih mirip seperti ini (bukan berarti A sebagai orangtua muncul dua kali):
Jika Anda membuang komit git mentah, Anda akan melihat nol atau lebih bidang induk. Jika ada nol, itu berarti tidak ada orang tua dan komit adalah root (Anda sebenarnya dapat memiliki beberapa root). Jika ada satu, itu berarti tidak ada penggabungan dan itu bukan komit root. Jika ada lebih dari satu itu berarti komit adalah hasil penggabungan dan semua orang tua setelah yang pertama adalah gabungan komit.
Ketika keduanya mengenai A rantai mereka akan sama, sebelum itu rantai mereka akan sama sekali berbeda. Komitmen pertama yang dimiliki dua komitmen lainnya adalah leluhur yang sama dan dari mana mereka menyimpang. mungkin ada beberapa kebingungan di sini antara istilah commit, branch, dan ref. Anda sebenarnya bisa menggabungkan komit. Inilah yang sebenarnya dilakukan penggabungan. Seorang ref hanya menunjuk ke sebuah komit dan sebuah cabang tidak lebih dari sebuah ref dalam folder .git / refs / head, lokasi folder adalah yang menentukan bahwa ref adalah cabang daripada sesuatu yang lain seperti sebuah tag.
Di mana Anda kehilangan sejarah adalah penggabungan akan melakukan satu dari dua hal tergantung pada keadaan.
Mempertimbangkan:
Dalam hal ini gabungan di kedua arah akan membuat komit baru dengan induk pertama sebagai komit yang ditunjukkan oleh cabang yang dicentang saat ini dan induk kedua sebagai komit di ujung cabang yang Anda gabungkan ke cabang Anda saat ini. Itu harus membuat komitmen baru karena kedua cabang memiliki perubahan sejak nenek moyang mereka yang harus digabungkan.
Pada titik ini D (B1) sekarang memiliki kedua set perubahan dari kedua cabang (itu sendiri dan B2). Namun cabang kedua tidak memiliki perubahan dari B1. Jika Anda menggabungkan perubahan dari B1 ke B2 sehingga mereka disinkronkan maka Anda mungkin mengharapkan sesuatu yang terlihat seperti ini (Anda dapat memaksa git merge untuk melakukannya seperti ini dengan --no-ff):
Anda akan mendapatkannya meskipun B1 memiliki komitmen tambahan. Selama tidak ada perubahan dalam B2 yang tidak dimiliki B1, kedua cabang akan digabungkan. Itu melakukan fast forward yang seperti rebase (rebases juga memakan atau linearisasi sejarah), kecuali tidak seperti rebase karena hanya satu cabang yang memiliki set perubahan, ia tidak harus menerapkan perubahan dari satu cabang di atas itu dari yang lain.
Jika Anda berhenti bekerja pada B1 maka banyak hal baik untuk menjaga sejarah dalam jangka panjang. Hanya B1 (yang mungkin master) yang akan maju secara khusus sehingga lokasi B2 dalam riwayat B2 berhasil menunjukkan titik bahwa ia digabungkan ke dalam B1. Inilah yang git harapkan Anda lakukan, untuk bercabang B dari A, maka Anda dapat menggabungkan A menjadi B sebanyak yang Anda suka dengan perubahan yang terakumulasi, namun ketika menggabungkan B kembali ke A, tidak diharapkan bahwa Anda akan bekerja pada B dan selanjutnya . Jika Anda terus bekerja pada cabang Anda setelah maju cepat menggabungkannya kembali ke cabang yang Anda kerjakan maka menghapus riwayat B sebelumnya setiap kali. Anda benar-benar membuat cabang baru setiap kali setelah komit maju cepat ke sumber lalu komit ke cabang.
1 sampai 3 dan 5 hingga 8 adalah cabang struktural yang muncul jika Anda mengikuti sejarah untuk 4 atau 9. Tidak ada cara di git untuk mengetahui mana dari cabang struktural yang tidak disebutkan namanya dan tidak direferensikan milik dengan cabang bernama dan referensi sebagai ujung struktur. Anda mungkin berasumsi dari gambar ini bahwa 0 hingga 4 milik B1 dan 4 hingga 9 milik B2 tetapi selain dari 4 dan 9 tidak dapat mengetahui cabang mana yang dimiliki cabang mana, saya hanya menggambarnya dengan cara yang memberikan ilusi itu. 0 mungkin milik B2 dan 5 mungkin milik B1. Ada 16 kemungkinan yang berbeda dalam hal ini yang dinamai cabang masing-masing cabang struktural milik.
Ada sejumlah strategi git yang mengatasi hal ini. Anda dapat memaksa git merge untuk tidak pernah maju cepat dan selalu membuat cabang gabungan. Cara mengerikan untuk melestarikan sejarah cabang adalah dengan tag dan / atau cabang (tag sangat direkomendasikan) menurut beberapa konvensi yang Anda pilih. Saya benar-benar tidak akan merekomendasikan komit kosong boneka di cabang tempat Anda bergabung. Konvensi yang sangat umum adalah untuk tidak bergabung ke cabang integrasi sampai Anda ingin benar-benar menutup cabang Anda. Ini adalah praktik yang harus dipatuhi oleh orang-orang karena Anda sedang berusaha untuk memiliki cabang. Namun di dunia nyata ideal tidak selalu berarti praktis melakukan hal yang benar tidak layak untuk setiap situasi. Jika apa yang Anda
sumber
man git-reflog
dan bagian tentang tanggal: "master@{one.week.ago} berarti" di mana master menunjuk satu minggu yang lalu di repositori lokal ini "". Atau diskusi di<refname>@{<date>}
dalamman gitrevisions
. Dancore.reflogExpire
diman git-config
.Tidak cukup solusi untuk pertanyaan itu tetapi saya pikir itu layak untuk mencatat pendekatan yang saya gunakan ketika saya memiliki cabang yang tahan lama:
Pada saat yang sama saya membuat cabang, saya juga membuat tag dengan nama yang sama tetapi dengan
-init
akhiran, misalnyafeature-branch
danfeature-branch-init
.(Agak aneh bahwa ini adalah pertanyaan yang sulit dijawab!)
sumber
Cara sederhana untuk membuatnya lebih mudah untuk melihat titik percabangan
git log --graph
adalah dengan menggunakan opsi--first-parent
.Misalnya, ambil repo dari jawaban yang diterima :
Sekarang tambahkan
--first-parent
:Itu membuatnya lebih mudah!
Perhatikan jika repo memiliki banyak cabang yang ingin Anda tentukan 2 cabang yang Anda bandingkan daripada menggunakan
--all
:sumber
Masalahnya adalah menemukan potongan terbaru, komit tunggal antara kedua cabang di satu sisi, dan yang paling awal leluhur bersama yang di sisi lain (mungkin komit awal repo). Ini sesuai dengan intuisi saya tentang titik "percabangan" itu.
Yang perlu diingat, ini sama sekali tidak mudah untuk dihitung dengan perintah normal git shell, karena
git rev-list
- alat kami yang paling kuat - tidak membiarkan kami membatasi jalur yang digunakan untuk mencapai komit. Yang paling dekat yang kita miliki adalahgit rev-list --boundary
, yang dapat memberi kita satu set semua komitmen yang "menghalangi jalan kita". (Catatan:git rev-list --ancestry-path
menarik tetapi saya tidak tahu bagaimana membuatnya berguna di sini.)Ini skripnya: https://gist.github.com/abortz/d464c88923c520b79e3d . Ini relatif sederhana, tetapi karena satu lingkaran itu cukup rumit untuk menjamin inti.
Perhatikan bahwa sebagian besar solusi lain yang diusulkan di sini tidak mungkin dapat berfungsi di semua situasi karena alasan sederhana:
git rev-list --first-parent
tidak dapat diandalkan dalam membuat linierisasi sejarah karena mungkin ada penggabungan dengan salah satu pemesanan.git rev-list --topo-order
, di sisi lain, sangat berguna - untuk komit berjalan dalam urutan topografi - tetapi melakukan diff adalah rapuh: ada beberapa urutan topografi yang mungkin untuk grafik yang diberikan, jadi Anda bergantung pada stabilitas tertentu dari urutan tersebut. Yang mengatakan, solusi strongk7 mungkin bekerja dengan sangat baik sebagian besar waktu. Namun lebih lambat milikku karena harus berjalan sepanjang sejarah repo ... dua kali. :-)sumber
Berikut ini mengimplementasikan git yang setara dengan svn log --stop-on-copy dan juga dapat digunakan untuk menemukan asal cabang.
Pendekatan
Seperti semua sungai mengalir ke laut, semua cabang berlari untuk menguasai dan oleh karena itu kami menemukan gabungan antara cabang-cabang yang tampaknya tidak berhubungan. Ketika kita berjalan kembali dari kepala cabang melalui leluhur, kita dapat berhenti di pangkalan gabungan potensial pertama karena secara teori itu harus menjadi titik asal cabang ini.
Catatan
detail: https://stackoverflow.com/a/35353202/9950
sumber
Anda bisa menggunakan perintah berikut untuk mengembalikan komit tertua di branch_a, yang tidak dapat dijangkau dari master:
Mungkin dengan pemeriksaan kewarasan tambahan bahwa orang tua dari komit tersebut sebenarnya dapat dijangkau dari master ...
sumber
Anda dapat memeriksa reflog cabang A untuk menemukan komit mana yang diciptakannya, serta sejarah lengkap yang dilakukan oleh cabang tersebut. Reflog ada di
.git/logs
.sumber
Saya percaya saya telah menemukan cara yang berhubungan dengan semua kasus sudut yang disebutkan di sini:
Charles Bailey cukup benar bahwa solusi berdasarkan urutan leluhur hanya memiliki nilai terbatas; pada akhir hari Anda membutuhkan semacam catatan "komit ini berasal dari cabang X", tetapi catatan tersebut sudah ada; secara default 'git merge' akan menggunakan pesan komit seperti "Gabung cabang 'branch_A' menjadi master", ini memberitahu Anda bahwa semua komit dari induk kedua (komit ^ 2) berasal dari 'branch_A' dan digabungkan ke yang pertama parent (commit ^ 1), yang merupakan 'master'.
Berbekal informasi ini, Anda dapat menemukan gabungan pertama 'branch_A' (saat itulah 'branch_A' benar-benar ada), dan menemukan basis-gabungan, yang akan menjadi titik cabang :)
Saya sudah mencoba dengan repositori Mark Booth dan Charles Bailey dan solusinya berhasil; bagaimana tidak bisa? Satu-satunya cara ini tidak akan berhasil adalah jika Anda telah secara manual mengubah pesan komit default untuk penggabungan sehingga informasi cabang benar-benar hilang.
Untuk kegunaan:
Maka kamu bisa melakukan '
git branch-point branch_A
'.Nikmati ;)
sumber
git merge -m
untuk mengatakan apa yang telah saya gabungkan daripada nama cabang yang berpotensi singkat (mis. "Gabungkan perubahan arus utama menjadi fitur xyz refactor"). Misalkan saya kurang membantu dengan-m
contoh saya? Masalahnya sama sekali tidak larut secara umum karena saya dapat membuat sejarah yang sama dengan satu atau dua cabang sementara dan tidak ada cara untuk membedakannya.