Bagaimana cara "git show" menggabungkan komit dengan output diff gabungan bahkan ketika setiap file yang diubah setuju dengan salah satu dari orang tua?


186

Setelah melakukan penggabungan "sederhana" (satu tanpa konflik), git show biasanya hanya menunjukkan sesuatu seperti

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

Ini karena, untuk penggabungan, git showmenggunakan format diff gabungan yang menghilangkan file yang setuju dengan salah satu versi induk.

Apakah ada cara untuk memaksa git untuk tetap menunjukkan semua perbedaan dalam mode diff gabungan?

Melakukan git show -makan menunjukkan perbedaan (masing-masing menggunakan perbedaan berpasangan antara versi baru dan semua induk) tapi saya lebih suka memilikinya dengan perbedaan ditandai dengan +/- di kolom masing-masing seperti dalam mode gabungan.


1
@ Tilman Vogel: tolong tinjau jawaban yang diterima - Sepertinya ada jawaban yang lebih baik
Jayan

1
@ Jay Sementara jawaban lain lebih populer karena mengandung petunjuk yang bermanfaat, mereka sebenarnya tidak semakin dekat dengan masalah saya karena hanya melakukan diff dua arah. Saya mencari perbedaan tiga arah.
Tilman Vogel

Jawaban:


-3

Tidak, tidak ada cara untuk melakukan ini git show. Tapi kadang-kadang tentu akan menyenangkan, dan mungkin akan relatif mudah diimplementasikan dalam kode sumber git (setelah semua, Anda hanya perlu mengatakannya untuk tidak memangkas apa yang dianggapnya sebagai output asing), sehingga patch untuk melakukannya mungkin akan diterima oleh pengelola git.

Berhati-hatilah dengan apa yang Anda inginkan; menggabungkan cabang dengan perubahan satu baris yang bercabang tiga bulan yang lalu masih akan memiliki perbedaan besar versus jalur utama, sehingga perbedaan penuh seperti itu hampir sepenuhnya tidak membantu. Itu sebabnya git tidak menunjukkannya.


12
Tolong jangan katakan "tidak ada cara untuk melakukan ini" karena itu jelas mungkin - lihat jawaban lain. Ini sangat menyesatkan untuk dikatakan.
kgadek

1
git tunjukkan KEPALA ^ ... KEPALA; Solusi # per @ hesham_EE.
Michael Dimmitt

git show HEAD ~ 1 ... HEAD ~ 0 --name-only; # sintaks yang lebih baik. Untuk iterasi pr's.
Michael Dimmitt

256

Lihatlah pesan komit:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

perhatikan garis:

Merge: fc17405 ee2de56

ambil kedua id tersebut dan balikkan. jadi untuk mendapatkan diff yang Anda inginkan, Anda akan melakukan:

git diff ee2de56..fc17405

untuk hanya menampilkan nama file yang diubah:

git diff --name-only ee2de56..fc17405

dan untuk mengekstraknya, Anda dapat menambahkan ini ke gitconfig Anda:

exportfiles = !sh -c 'git diff $0 --name-only | "while read files; do mkdir -p \"$1/$(dirname $files)\"; cp -vf $files $1/$(dirname $files); done"'

kemudian gunakan dengan melakukan:

git exportfiles ee2de56..fc17405 /c/temp/myproject

Terima kasih atas sarannya tetapi saya pikir itu tidak menyelesaikan masalah saya. Karena markup dan format komentar terbatas, saya menambahkan komentar saya ke jawaban Anda. Maaf untuk itu! Perlu ditinjau sejawat sampai terlihat.
Tilman Vogel

6
Sepertinya, edit saya ditolak. Singkatnya: Perbedaan Anda tidak menunjukkan penambahan mana yang berasal dari cabang mana. Dan Anda tidak dapat membedakan apakah perubahan ditambahkan di cabang kedua atau dihapus di cabang pertama.
Tilman Vogel

45
Solusi yang lebih baik adalah git diff fc17405...ee2de56- ini akan menunjukkan semua perubahan pada ee2de56 yang dapat dijangkau dari commit di fc17405, yang saya percaya adalah yang Anda inginkan. Perhatikan 3 titik, bukan dua.
Kris Nuttycombe

1
@KrisNuttycombe 3 titik dan urutannya. Dan komentar Anda adalah apa yang saya cari, yang saya pikir lebih seperti apa yang diinginkan OP.
Izkata

@KrisNuttycombe Entah bagaimana ini tidak berhasil git log, yang masih menunjukkan semua commit, seperti ..varian. ..dan ...melakukan hal yang sama untuk log, tetapi karena diffmereka berbeda !? Bagaimana cara saya mendapatkan daftar komitmen yang digabung ke cabang ini?
Rudie

77

Solusi yang lebih baik (disebutkan oleh @KrisNuttycombe):

git diff fc17405...ee2de56

untuk komit gabungan:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

untuk menampilkan semua perubahan ee2de56yang dapat dicapai dari komitmen pada fc17405. Perhatikan urutan hash komit - sama seperti yang ditunjukkan pada info gabungan:Merge: fc17405 ee2de56

Perhatikan juga 3 titik, ...bukan dua !

Untuk daftar file yang diubah, Anda dapat menggunakan:

git diff fc17405...ee2de56 --name-only

Inilah yang saya inginkan setelah +1.
geedoubleya

Ini sebenarnya menunjukkan hasil dari konflik gabungan, sedangkan jawaban lainnya tidak.
Pod

12

Anda bisa membuat cabang dengan HEAD diatur ke satu komit sebelum digabung. Kemudian, Anda dapat melakukan:

git merge --squash testing

Ini akan bergabung, tetapi tidak berkomitmen. Kemudian:

git diff

5

Sepertinya dijawab di sini: https://public-inbox.org/git/7vd392ezhx.fsf@alter.siamese.dyndns.org/

Jadi dengan cara yang sama, berlari

$ git diff --cc $ M $ M ^ 1 $ M ^ 2 $ (git merge-base $ M ^ 1 $ M ^ 2)

harus memperlihatkan tambalan gabungan yang menjelaskan status pada $ M relatif terhadap status yang dicatat pada orang tuanya dan pangkalan gabungan.


apakah Anda tahu jika ada alat yang dapat dikonfigurasi untuk menampilkan perbedaan berdampingan, berpotensi dalam beberapa kolom (seperti di jendela resolusi konflik gabungan IntelliJ)? Jawaban Anda tepat yang saya cari
Max

@ Max Tidak, aku takut tidak. Googling "n-way visual diff" memang menyediakan beberapa tautan, jadi saya sudah mencobanya.
max630

4

Saya pikir Anda hanya perlu 'git show -c $ ref'. Mencoba ini di repositori git pada a8e4a59 menunjukkan diff gabungan (karakter plus / minus di salah satu dari 2 kolom). Seperti yang disebutkan dalam manual git-show, cukup banyak delegasi untuk 'git diff-tree' sehingga opsi-opsi itu terlihat berguna.


3
Tidak, untuk gabungan "sederhana", git show -c $refmenunjukkan output yang sama seperti yang saya kutip, yaitu tidak ada perbedaan. -cmemilih mode diff gabungan yang sangat mirip dengan mode default untuk gabungan komit yaitu '--cc', lihat git help showdan git help diff-tree. Keduanya sama sekali menghilangkan file yang setuju dengan salah satu versi induk dari file itu.
Tilman Vogel

a8e4a59memang tidak termasuk dalam kategori gabungan komit, maksud saya. Ini menggabungkan komit memang berisi satu file yang berbeda dari kedua versi induknya. Documentation/git-fast-import.txtmemiliki beberapa hal ditambahkan dari satu orangtua dan beberapa dari yang lain. Ini menghasilkan keluaran non-kosong dari git diff-tree --cc. Namun, hanya perubahan dalam kasus "konflik" ini yang ditampilkan. Semua hasil gabungan "bersih", lihat git show -m a8e4a59, tidak ditampilkan sama sekali.
Tilman Vogel

1
@ TilmanVogel: Terima kasih telah menunjukkan bahwa gabungan file "tidak menarik" tidak disertakan dalam git show -coutput. ( man git-diff-treememang mengatakan "Lebih jauh, ini hanya berisi daftar file yang dimodifikasi dari semua orangtua." tetapi saya tentu saja tidak melihatnya.)
Paul Whittaker

3

dalam kasus Anda, Anda hanya perlu

git diff HEAD^ HEAD^2

atau hanya hash untuk Anda komit:

git diff 0e1329e55^ 0e1329e55^2

4
Tidak, ini hanya perbedaan dua arah antara kedua orang tua. Apa yang saya minta adalah mode yang secara bersamaan menunjukkan perbedaan antara git merge-base HEAD^ HEAD^2dan HEAD^dan HEAD^2dengan gaya yang sama seperti yang dilakukan untuk file yang digabungkan dengan konflik.
Tilman Vogel

3

Jika komit gabungan Anda adalah kom 0e1329e5, seperti di atas, Anda bisa mendapatkan perbedaan yang terkandung dalam gabungan ini dengan:

git diff 0e1329e5^..0e1329e5

Saya harap ini membantu!


3

Jika Anda duduk di komit gabungan maka ini menunjukkan diffs:

git diff HEAD~1..HEAD

Jika Anda tidak bergabung dengan komit gabungan, ganti saja HEAD dengan komit gabungan. Metode ini sepertinya paling sederhana dan paling intuitif.


1
Ini bukan output "gabungan diff". Mendapatkan perbedaan antara setiap pasangan orang tua dan KEPALA bukan masalah di sini.
Tilman Vogel

2

Anda dapat menggunakan perintah diff-tree dengan flag -c. Perintah ini menunjukkan kepada Anda file apa yang telah berubah di komit gabungan.

git diff-tree -c {merged_commit_sha}

Saya mendapatkan deskripsi -c flag dari Git-Scm :

Bendera ini mengubah cara komit gabungan ditampilkan (yang berarti ini hanya berguna ketika perintah diberikan, atau --stdin). Ini menunjukkan perbedaan dari masing-masing orang tua ke hasil gabungan secara bersamaan alih-alih menunjukkan perbedaan berpasangan antara orang tua dan hasil satu per satu (yang merupakan opsi-m yang dilakukan). Selain itu, daftar hanya file yang dimodifikasi dari semua orang tua.


2
Sepertinya artikel yang bagus tentang topik ini: haacked.com/archive/2014/02/21/reviewing-merge-commits dan mungkin ini juga: longair.net/blog/2009/04/16/git-fetch-and-merge
Devin G Rhode

1

Saya membangun pendekatan tujuan umum untuk melakukan berbagai operasi berdasarkan komitmen gabungan.

Langkah Satu : Tambahkan alias ke git dengan mengedit ~/.gitconfig:

[alias]
  range = "!. ~/.githelpers && run_on_merge_range"

Langkah Dua : Di ~/.githelpers, tentukan fungsi bash:

run_on_merge_range() {
  cmd=$1; shift
  commit=$1; shift
  range=$(git show $commit | grep Merge: | awk '{print $2 "..." $3}')
  echo "git $cmd $range $@"
  if [ -z $range ]; then
    echo "No merge detected"
    exit 1
  fi
  git $cmd $range $@
}

Langkah Tiga : Untung!

git range log <merge SHA> --oneline
git range diff <merge SHA> --reverse -p
git range diff <merge SHA> --name-only

Mungkin ada BANYAK ruang untuk perbaikan di sini, saya hanya mencoba ini bersama untuk melewati situasi yang menjengkelkan. Jangan ragu untuk mengejek sintaks dan / atau logika bash saya.


Perhatikan bahwa Anda mungkin ingin mengubah "..." menjadi ".." di bit "awk", tergantung pada apa yang Anda butuhkan dan perintah apa yang Anda jalankan: stackoverflow.com/questions/462974/…
Nerdmaster
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.