Bagaimana cara membedakan komit dengan induknya?

460

Selain menulis alias atau skrip, apakah ada perintah yang lebih pendek untuk mendapatkan diff untuk komit tertentu?

git diff 15dc8^..15dc8

Jika Anda hanya memberikan satu komit git diff 15dc8, itu berbeda dengan komit terhadap HEAD.

Brian L
sumber
Hal paling keren tentang ini adalah bahwa ini akan bekerja dengan "git difftool", menggunakan alat untuk menampilkan diff.
orip
Untuk referensi, jawaban untuk pertanyaan lain ini mengilustrasikan bagaimana Anda dapat membuat alias bash-powered untuk menyederhanakan di atas: stackoverflow.com/questions/3321492/…
Nick

Jawaban:

641

Gunakan git show $COMMIT. Ini akan menunjukkan kepada Anda pesan log untuk komit, dan perbedaan komit tertentu.

mipadi
sumber
45
Sayang sekali tidak bisa menggunakan difftool :(
orip
1
@orip Anda selalu dapat mengatur GIT_EXTERNAL_DIFF ke skrip yang melakukan hal yang sama dengan difftool Anda.
slacy
7
Saya lebih suka jawaban JakubNarebski, karena ekspresi komit yang diberikan di sana akan berfungsi dalam banyak konteks: stackoverflow.com/a/449128/992887
RichVel
1
Jika tidak ada perbedaan yang ditampilkan, mungkin tidak ada perubahan aktual, seperti untuk komit gabungan
Devin G Rhode
6
@ PTWithy: Pertanyaannya adalah, "Apakah ada perintah yang lebih pendek untuk mendapatkan diff untuk komit tertentu?", Yang dijawab pertanyaan ini.
mipadi
439

Menggunakan:

git diff 15dc8^!

seperti yang dijelaskan dalam fragmen manpage git-rev-parse (1) berikut (atau dalam manpage git gvision (7) modern ):

Dua singkatan lainnya untuk penamaan set yang dibentuk oleh komit dan induknya ada. Notasi r1 ^ @ berarti semua orang tua dari r1. r1 ^! termasuk komit r1 tetapi mengecualikan semua orang tuanya.

Ini berarti Anda dapat menggunakan 15dc8^!sebagai singkatan untuk 15dc8^..15dc8di mana saja di git di mana revisi diperlukan. Untuk perintah diffgit diff 15dc8^..15dc8 dipahami sebagai git diff 15dc8^ 15dc8, yang berarti perbedaan antara induk komit ( 15dc8^) dan komit ( 15dc8).

Catatan : deskripsi dalam git-rev-parse(1)pembicaraan manual tentang rentang revisi , di mana ia perlu bekerja juga untuk komitmen gabungan, dengan lebih dari satu orangtua. Maka r1^!" r1 --not r1^@" yaitu " r1 ^r1^1 ^r1^2 ..."


Anda juga dapat menggunakan git show COMMITuntuk mendapatkan deskripsi komit dan diff untuk komit. Jika Anda hanya menginginkan diff, Anda dapat menggunakannyagit diff-tree -p COMMIT

Jakub Narębski
sumber
7
Ini harus menjadi jawaban yang diterima, jauh lebih rapi. Namun, kalimat terakhir dari ekstrak git-rev-parse agak membingungkan - sepertinya itu berarti 'mulai dari induk commit ini hingga commit ini'.
RichVel
1
@RichVel: ini agak membingungkan karena mencoba menjelaskan juga situasi di mana komit memiliki lebih dari satu orangtua (adalah komit gabungan). r1 ^! bekerja seperti yang diharapkan juga.
Jakub Narębski
@ JakubNarębski: poin bagus, mungkin Anda bisa mengedit jawaban Anda untuk merangkum pemahaman Anda tentang kasus orang tua tunggal dan multi-orang tua - pernyataan terpisah pada masing-masing mungkin lebih mudah untuk dipahami.
RichVel
1
@ JakubNarębski: ya, jauh lebih baik! Saya sekarang menggunakan pintasan ini sepanjang waktu - terima kasih.
RichVel
1
The ^!notasi tua singkatan bekerja dengan baik dengan difftool untuk komit normal tetapi diff dibalik untuk komit merge. Kenapa begitu?
hIpPy
56

Jika Anda tahu seberapa jauh ke belakang, Anda dapat mencoba sesuatu seperti:

# Current branch vs. parent
git diff HEAD^ HEAD

# Current branch, diff between commits 2 and 3 times back
git diff HEAD~3 HEAD~2

Komit sebelumnya berfungsi seperti ini:

# Parent of HEAD
git show HEAD^1

# Grandparent
git show HEAD^2

Ada banyak cara untuk menentukan komit:

# Great grandparent
git show HEAD~3

Lihat halaman ini untuk detailnya .

Paul Vincent Craven
sumber
2
KEPALA ^ 2 bukan kakek-nenek, jika KEPALA ^ 1 adalah ayah, maka KEPALA ^ 2 adalah ibu. Gunakan HEAD ~ 2 untuk ayah ayah.
Binarian
11

Seperti @mipadi tunjukkan, Anda dapat menggunakan git show $COMMIT, tetapi ini juga menunjukkan beberapa tajuk dan pesan komit. Jika Anda ingin perbedaan lurus, gunakan git show --pretty=format:%b $COMMIT.

Ini jelas bukan tugas yang singkat, jadi saya menyimpan alias ini di .gitconfig saya

    [alias]
      sd = show --pretty=format:%b

Ini memungkinkan saya untuk menggunakan git sd $COMMITuntuk menampilkan diff .

Øystein Steimler
sumber
1
Alias ​​ini dapat menyertakan --color yang membuatnya lebih mudah dibaca: sd = show --color --pretty = format:% b
RichVel
@RichVel Memang! Poin yang sangat bagus. Jika Anda memiliki warna yang diaktifkan secara default di git, Anda tidak perlu beralih ini. Itu yang biasanya saya lakukan.
Øystein Steimler
5

Banyak contoh yang disebutkan (misalnya git diff 15dc8^!, atau git diff 15dc8^..15dc8) tidak berfungsi jika Anda menggunakan zsh dan memiliki extendedglobset opsi. Anda dapat memperbaikinya dengan salah satu dari tiga cara berikut:

  1. unsetopt extendedglob (dan / atau hapus dari .zshrc)

  2. setopt NO_NOMATCH (dan / atau atur dalam .zshrc)

  3. melarikan diri dari caret dan bang setiap kali dengan backslash, mis git diff 15dc8\^\!

Ville
sumber
3
git diff 15dc8 15dce~1

~ 1 berarti 'orangtua', ~ 2 'kakek-nenek, dll.

John Lawrence Aspden
sumber
2

Solusi Paul di atas melakukan apa yang saya harapkan.

$ git diff HEAD^1

Juga, berguna untuk menambahkan alias seperti hobs yang disebutkan, jika Anda meletakkan yang berikut di bagian [alias] file ~ / .gitconfig Anda, maka Anda dapat menggunakan tangan-pendek untuk melihat perbedaan antara head dan sebelumnya.

[alias]
    diff-last = diff HEAD^1

Kemudian menjalankan $ git diff-last akan memberi Anda hasil. Perhatikan bahwa ini juga akan mencakup setiap perubahan yang belum Anda lakukan serta perbedaan antar komitmen. Jika Anda ingin mengabaikan perubahan yang belum Anda lakukan, maka Anda dapat menggunakan diff untuk membandingkan KEPALA dengan induknya secara langsung:

$ git diff HEAD^1 HEAD
Graham R. Armstrong
sumber
0

Menggunakan alias, jadi tidak menjawab pertanyaan Anda dengan tepat, tetapi saya menemukan ini berguna untuk melakukan apa yang Anda inginkan ...

alias gitdiff-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"

alias gitlog-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
hobs
sumber