Bagaimana cara melihat komit di satu cabang tidak di yang lain?

180

Saya punya dua cabang develdan next. Dalam perkembangan saya memiliki jumlah komitmen yang sedikit banyak. Beberapa dari komit dipilih next. Saya juga menambahkan beberapa komit ke berikutnya yang digabung ke devel.

Sekarang saya ingin melihat apa yang hilang next, jadi saya bisa menguji perubahan secara detail sebelum membawanya next. Pertanyaan saya sekarang, bagaimana saya bisa melihat komit yang masuk develtetapi tidak di berikutnya?

Upaya Sascha
sumber
judul Anda agak menyesatkan, karena yang ingin Anda bandingkan adalah ujung dari kedua cabang. dan saya datang ke sini mencari solusi dua membandingkan komitmen spesifik (berbeda) dari dua cabang
thebugfinder
Gandakan ?: stackoverflow.com/questions/1710894/…
reinierpost

Jawaban:

210

Perintah yang jarang digunakan git cherrymenunjukkan kepada Anda komit yang belum dipilih secara ceri. Dokumentasi untuk git cherryada di sini , tetapi, singkatnya, Anda hanya dapat melakukan:

git checkout devel
git cherry next

... dan lihat outputnya sedikit seperti ini:

+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9

Komit yang dimulai dengan +akan menjadi komitmen yang belum Anda pilih next. Dalam hal ini, sejauh ini saya hanya memilih satu koma. Anda mungkin ingin menambahkan -vparameter ke git cherryperintah, sehingga juga menampilkan baris subjek dari setiap komit.

Mark Longair
sumber
Hebat, ini yang saya butuhkan. Akan bagus juga untuk mendapatkan deskripsi singkat dari tes, tapi saya bisa skrip ini.
Sascha Effert
29
Anda tidak perlu git checkout devel, Anda bisa melakukannya git cherry next devel.
Robin Winslow
21
"Mungkin ingin menambahkan -v" ? Cherry tanpa a -vseperti lstanpa -la. ; -J
Slipp D. Thompson
1
Dan Anda tidak akan tahu cara cherryuntuk menandai atau mengecualikan komitmen yang setara, bukan? cherrysepertinya perintah plumbing, tetapi tidak (tampaknya) menawarkan banyak opsi. Untuk apa saya saat ini di tengah-tengah, git cherrymemberi saya positif palsu, tetapi @ sehe git log --cherry-pickdengan benar mengecualikan komitmen yang sebelumnya diambil / diubah.
Slipp D. Thompson
Dokumentasi tersebut memberikan contoh nyata: git-scm.com/docs/git-cherry#_concrete_example
ams
107

Anda juga bisa menggunakannya

git log --left-right --graph --cherry-pick --oneline devel...next

untuk mendapatkan daftar bagus dari berbagai komitmen aktual yang tidak dibagikan di antara cabang-cabang.

Kata operasinya adalah --cherry-pick

--cherry-pick

Abaikan setiap komit yang memperkenalkan perubahan yang sama seperti komit lain di "sisi lain" ketika set komit dibatasi dengan perbedaan simetris. Misalnya, jika Anda memiliki dua cabang, A dan B, cara yang biasa untuk mencantumkan semua komit hanya pada satu sisi adalah dengan - kiri-kanan, seperti contoh di atas dalam deskripsi opsi itu. Namun itu menunjukkan komit yang dipetik dari cabang lain (misalnya, "ke-3 pada b" mungkin dipetik dari cabang A). Dengan opsi ini, pasangan komit semacam itu dikecualikan dari output.

Perbarui Seperti disebutkan dalam komentar, git versi terbaru ditambahkan --cherry-mark:

--cherry-mark

Seperti --cherry-pick (lihat di bawah) tetapi tandai komit dengan = daripada menghilangkannya, dan yang tidak sama dengan +.

lihat
sumber
1
Ini tidak berhasil untuk saya. Versi git saya tidak tahu --one-line, oleh karena itu saya menghapusnya. Kemudian saya harus bertukar devel dan berikutnya dan itu berhasil. Sangat bagus!
Sascha Effert
@ SaschaEffert: Anda tidak perlu beralih devel dan berikutnya (perhatikan TIGA titik, bukan DUA). Yang mengatakan, hal-hal mungkin berbeda jika Anda menggunakan versi kuno dari git (?) Tetapi dalam kasus itu Anda seharusnya mendapatkan kesalahan rev-parse pada tiga titik.
sehe
2
Untuk bersenang-senang, saya mengetahui bahwa sintaks rev-parse '...' (perbedaan simetris) ditambahkan pada Juli 2006 , dan dokumentasi untuknya diperbarui pada Juni 2008 . Kegembiraan open source!
sehe
1
'gls --first-parent --cherry-mark --left-only develop ... next' di mana gls adalah alias log git saya dengan semua format yang cantik. cherry-mark menunjukkan cherry pick dan non-cherry pick berkomitmen untuk dikembangkan, tetapi menandai mereka secara berbeda.
angularsen
1
tambahkan --tidak ada gabungan mungkin lebih baik
MervynYang
51

Anda mungkin dapat mencoba melakukan subset git log:

git log --oneline devel ^next
Bryan Buckley
sumber
4
Ini adalah solusi terbaik menurut pendapat saya (jawaban @hehe juga menunjukkan komit selanjutnya yang tidak bertingkat - dalam konteks OP, tidak ada, tetapi di tambang ada - menggunakan --left-onlyakan lebih baik). Namun, yang ini dapat sedikit ditingkatkan dengan menambahkan --no-mergesuntuk menghilangkan komit gabungan (misalnya jika fitur atau cabang perbaikan terbaru digabungkan (secara terpisah) menjadi devel dan berikutnya). Sebenarnya, resolusi konflik dalam penggabungan dapat menciptakan perbedaan lain, tetapi biasanya tidak demikian. The --no-mergespilihan dapat berguna diterapkan pada jawaban lain juga.
Alex Dupuy
27

Bagaimana tentang

git log next..devel

Hasilnya mirip dengan jawaban Byran (urutan komit berbeda) tetapi kedua jawaban kami akan menghasilkan komit yang berbeda di antara cabang-cabang, alih-alih hanya menunjukkan apa yang ada di satu cabang dan tidak di yang lain.

justingordon
sumber
4
Anda juga dapat menghilangkan cabang kedua jika saat ini Anda berada di cabang itu. yaitugit log next..
jmaxyz
btw 'git log next..devel' berbeda dari 'git log devel..next'
Eugene Kaurov
1

Untuk mendapatkan daftar komit yang tidak terintegrasi ke dalam cabang rilis (selanjutnya) Anda dapat menggunakan:

git rev-list --reverse --pretty="TO_TEST %h (<%ae>) %s" --cherry-pick --right-only origin/release_branch...origin/development_branch | grep "^TO_TEST " > NotIntegratedYet.txt

Periksa git-rev-list untuk info lebih lanjut.

Mihai
sumber
perintah jawaban ini tidak memiliki cabang sebenarnya yang dimaksud, yaitunext...devel
Alex Dupuy
@AlexDupuy Yah, itu adalah jawaban yang cukup sederhana. Karena ini juga bukan jawaban yang paling sederhana dan tidak menjelaskan mengapa pendekatan ini lebih baik, saya -1- kan.
Slipp D. Thompson
-1

@Mark Longair memakukannya dalam jawabannya di sini , tapi saya ingin menambahkan beberapa wawasan tambahan.

Terkait, dan menjawab pertanyaan tentang cara memecah Permintaan Tarik (PR) besar, terutama ketika menekan komitmen Anda tidak praktis karena satu atau lebih gabungan master ke dalam feature_branch Anda

Situasi saya:
Saya membuat besar feature_branchdengan 30 komitmen dan membuka Permintaan Tarik (PR) pada GitHub untuk menggabungkannya master. Branch mastermengganti satu ton di bawahku, dan menerima 200 komit yang feature_branchtidak kumiliki. Untuk menyelesaikan konflik yang saya lakukan git checkout feature_branchdan git merge masteruntuk menggabungkan masterperubahan ke dalam saya feature_branch. Saya memilih untuk mergedaripada rebasemenjadi master terbaru sehingga saya harus menyelesaikan konflik hanya satu kali daripada berpotensi 30 kali (satu kali untuk setiap komitmen saya). Saya tidak ingin memeras 30 komit saya menjadi 1 terlebih dahulu dan kemudian kembali ke yang terbarumasterkarena itu mungkin menghapus riwayat komentar ulasan GitHub dalam PR. Jadi, saya menggabungkan master ke cabang fitur saya dan menyelesaikan konflik 1 kali. Semuanya baik-baik saja. Namun PR saya terlalu besar untuk ditinjau oleh kolega saya. Saya perlu membaginya. Saya pergi untuk menekan 30 komit saya dan OH TIDAK! DIMANA MEREKA? MEREKA SEMUA YANG TERCANTUM DENGAN master200 komitmen baru-baru ini sekarang karena saya bergabung masterdengan saya feature_branch! APA YANG SAYA LAKUKAN?

git cherrypenggunaan jika Anda ingin mencoba git cherry-pickkomitmen individu:

git cherry untuk menyelamatkan (semacam)!

Untuk melihat semua komitmen yang ada feature_branchtetapi TIDAK dalam, mastersaya dapat melakukannya:

git checkout feature_branch
git cherry master

ATAU, saya dapat memeriksa komit dari cabang APA PUN dengan TIDAK MEMASTIKAN saya sedang feature_branchmelakukan git cherry [upstream_branch] [feature_branch], seperti ini. Sekali lagi, ini memeriksa untuk melihat yang melakukan adalah feature_branchtetapi tidak dalam upstream_branch( masterdalam hal ini):

git cherry master feature_branch

Menambahkan -vjuga menunjukkan baris subjek pesan komit:

git cherry -v master

Memipis ke "jumlah kata" "-line" ( wc -l) menghitung berapa banyak komit yang ada:

git cherry master | wc -l

Anda dapat membandingkan jumlah ini dengan angka komit yang diperlihatkan dalam GithHub PR Anda agar merasa lebih baik karena mengetahui bahwa itu git cherrybenar - benar berfungsi. Anda juga dapat membandingkan hash git satu per satu dan melihatnya cocok di antara git cherrydan GitHub. Perhatikan bahwa git cherryTIDAK akan menghitung setiap komit merge di mana Anda bergabung masterke dalam feature_branch, tapi GitHub WILL. Jadi, jika Anda melihat perbedaan kecil dalam hitungan, cari halaman komit PR GitHub untuk kata "gabung" dan Anda mungkin akan melihat bahwa itulah penyebabnya git cherry. Mis: komit berjudul "Gabungkan 'master' cabang ke feature_branch" akan muncul di PR GitHub tetapi tidak ketika Anda menjalankan git cherry master feature_branch. Ini baik dan diharapkan.

Jadi, sekarang saya memiliki cara untuk mengetahui perbedaan mana yang mungkin ingin saya ceri-pilih ke cabang fitur baru untuk memisahkan perbedaan ini: Saya dapat menggunakan git cherry master feature_branchsecara lokal, atau melihat komitmen di GitHub PR.

Bagaimana squashing bisa membantu - andai saja kita bisa terjepit:

Sebuah alternatif, bagaimanapun, untuk memisahkan diff saya yang besar adalah dengan memecah semua 30 komit saya menjadi satu, menambal yang ke cabang fitur baru, soft reset patch komit, kemudian gunakan git guiuntuk menambahkan potongan file dengan file, potongan demi potongan, atau baris demi baris. Setelah saya mendapatkan satu sub-fitur, saya dapat melakukan apa yang saya tambahkan kemudian memeriksa cabang baru, menambahkan lebih banyak, melakukan, memeriksa cabang baru, dll, sampai saya memiliki fitur besar saya dibagi menjadi beberapa sub-fitur . Masalahnya adalah bahwa 30 komit saya berbaur dengan 200 komit lain dari orang lain karena saya git merge mastermasuk ke dalam saya feature_branch, jadi rebasing karenanya tidak praktis, karena saya harus menyaring 230 komit untuk memesan ulang dan menghancurkan 30 komit saya.

Cara menggunakan file tambalan sebagai pengganti yang lebih mudah untuk terjepit:

Cara mengatasinya adalah dengan hanya mendapatkan file tambalan yang berisi "squash-equivalen" dari semua 30 komit saya, menambalnya ke garpu baru master(cabang-sub-fitur baru), dan bekerja dari sana, sebagai berikut:

git checkout feature_branch
# ensure I have the latest changes from master merged into feature_branch
git merge master 
# Obtain a patch file, which is the equivalent of a squash of my 30 commits into 1 commit:
git diff master..feature_branch > ~/mypatch.patch
git checkout master
# Create a new, sub-feature branch
git checkout -b feature_branch2
# Patch the 30 commit patch file onto it:
git apply ~/mypatch.patch

Sekarang saya memiliki 30-komit patch saya semua diterapkan secara lokal, tetapi tidak dipentaskan dan tidak berkomitmen.

Sekarang gunakan git guiuntuk menambahkan file, potongan, dan / atau baris dan putus PR besar Anda atau "diff":

Perhatikan bahwa jika Anda tidak memilikinya git gui, Anda dapat menginstalnya dengan mudah di Ubuntu sudo apt install git-gui.

Sekarang saya dapat menjalankan git guidan mulai menambahkan file, potongan, dan / atau baris (dengan mengklik kanan pada program GUI Git), dan memecah 30 cabang fitur komit ke dalam sub cabang seperti dijelaskan di atas, berulang kali menambahkan, melakukan, lalu forking cabang fitur baru dan ulangi siklus ini sampai semua perubahan telah ditambahkan ke cabang-sub-fitur dan fitur 30-commit saya berhasil dipecah menjadi 3 atau 4 sub-fitur. Saya dapat membuka PR terpisah untuk masing-masing sub-fitur ini sekarang, dan mereka akan lebih mudah untuk ditinjau oleh tim saya.

Referensi:

  1. Buat tambalan atau file diff dari repositori git dan terapkan ke repositori git lain
Gabriel Staples
sumber
Saya perlu merujuk jawaban ini hari ini, tetapi tidak dapat menemukannya dengan cepat. Untungnya, ada downvote untuk membantu saya menemukannya lebih mudah, jadi klik sederhana pada ikon piala penghargaan di kanan atas layar menunjukkan di mana saya baru saja kehilangan 2 poin, dan mengklik pada itu membawa saya kembali ke sini di mana saya bisa sekarang referensi jawaban saya sendiri di sini! Semoga saya tidak mendapatkan downvotes lagi, tetapi untuk downvoter, terima kasih atas layanan yang secara tidak sengaja membantu saya!
Gabriel Staples