Git menyalahkan - melakukan sebelumnya?

391

Apakah mungkin untuk melihat siapa yang mengedit baris tertentu sebelum komit dilaporkan oleh git blame, seperti riwayat komit untuk baris tertentu?

Misalnya, saya menjalankan yang berikut (pada uncrustifyproyek hebat ):

$ git blame -L10,+1 src/options.cpp
^fe25b6d (Ben Gardner 2009-10-17 13:13:55 -0500 10) #include "prototypes.h"

Bagaimana saya bisa mengetahui siapa yang mengedit baris itu sebelum melakukan fe25b6d? Dan yang diedit sebelum itu berkomitmen?

Sedate Alien
sumber
7
jika alasan Anda mencari komit sebelumnya adalah perubahan spasi putih gunakan -wopsi. Ada juga -Muntuk kode yang dipindahkan / disalin
brita_
Untuk mencari semua komit yang melibatkan kata tertentu, lihat skrip saya di bawah ini
VonC
Berikut ini adalah skrip yang berguna untuk menambahkan fungsi ini di github greasyfork.org/en/scripts/…
Aaron Hoffman
3
Tidak yakin apa yang tampak seperti github ketika @AaronHoffman memposting, tapi jauh lebih mudah untuk disalahkan - dan mendapatkan menyalahkan untuk versi sebelumnya - di github sekarang .
ruffin

Jawaban:

389
git blame -L 10,+1 fe25b6d^ -- src/options.cpp

Anda dapat menentukan revisi untuk kesalahan git untuk melihat kembali mulai dari (bukan default HEAD); fe25b6d^adalah induk dari fe25b6d.

Amber
sumber
107
Bisakah Anda mendapatkan riwayat lengkap, tanpa harus memasukkan kembali perintah beberapa kali dengan hash yang berbeda?
Anders Zommarin
13
Saya tidak percaya Git memiliki cara bawaan untuk mendapatkan setiap kesalahan yang menyentuh nomor baris (jenis yang masuk akal, karena baris yang diberikan mungkin tidak memiliki nomor baris yang konsisten di sepanjang sejarah file karena penyisipan dan penghapusan garis).
Amber
17
@ Ammber: Cukup yakin Anda benar bahwa fitur tersebut tidak ada, tetapi sepertinya tidak dapat diterapkan secara naif, hanya dengan melakukan apa yang akan dilakukan manusia: salahkan sekali, ambil informasi yang dilaporkan, salahkan bahwa , dan seterusnya.
Cascabel
15
git gui membuatnya cukup mudah untuk memeriksa sejarah suatu baris karena versi dapat diklik.
Zitrax
5
@shadyabhi --biasanya digunakan sebagai pemisah dalam argumen baris perintah - dalam kasus Git, biasanya digunakan untuk memisahkan hal-hal seperti melakukan hash dari daftar nama file.
Amber
192

Anda dapat menggunakan git log -L untuk melihat evolusi berbagai baris.

Sebagai contoh :

git log -L 15,23:filename.txt

berarti "melacak evolusi baris 15 hingga 23 dalam file bernama filename.txt".

Navneet
sumber
12
Ini adalah jawaban yang solid dan menjawab pertanyaan Anders Zommarin di atas tentang cara melihat perubahan pada garis tertentu dari waktu ke waktu.
bigtex777
4
FYI: git log -L <start>, <end>: <file> membutuhkan Git 1.8.4+ lihat: git-scm.com/docs/git-log#git-log--Ltstartgtltendgtltfilegt untuk opsi sintaksis
Neon
30

Jawaban Amber benar tetapi saya merasa tidak jelas; Sintaksnya adalah:

git blame {commit_id} -- {path/to/file}

Catatan: --digunakan untuk memisahkan tree-ish sha1 dari path file relatif. 1

Sebagai contoh:

git blame master -- index.html

Penghargaan penuh untuk Amber karena mengetahui semua hal! :)

ThorSummoner
sumber
1
Saya setuju dengan sentimen Anda. Namun sistem komentar terlalu terbatas untuk menyajikan semua informasi dengan jelas. Saya telah menambahkan konten jawaban ini dalam komentar; Namun, saya bersikeras untuk meninggalkan jawaban ini adalah tempat untuk kemudahan akses.
ThorSummoner
1
Entah itu pos terpisah atau edit. Saya suka ini sebagai jawaban terpisah.
Flimm
27

Anda mungkin ingin memeriksa:

git gui blame <filename>

Memberi Anda tampilan grafis yang bagus dari perubahan seperti "kesalahan git" tetapi dengan tautan yang dapat diklik per baris, untuk beralih ke komitmen sebelumnya. Arahkan kursor ke tautan untuk mendapatkan sembulan dengan detail komit. Bukan kredit saya ... ditemukan di sini:

http://zsoltfabok.com/blog/2012/02/git-blame-line-history/

git guiadalah antarmuka Tcl / Tc grafis untuk git. Tanpa params lain itu memulai aplikasi grafis yang cukup sederhana tetapi berguna untuk melakukan file, bakhil atau bahkan baris tunggal dan perintah serupa lainnya seperti mengubah, mengembalikan, mendorong ... Ini adalah bagian dari paket git stock. Di windows itu termasuk dalam installer. Pada debian - saya tidak tahu tentang sistem * nix lainnya - harus diinstal secara terpisah:

apt-get install git-gui

Dari dokumen:

https://git-scm.com/docs/git-gui

DESKRIPSI

Antarmuka pengguna grafis berbasis Tcl / Tk ke Git. git gui berfokus pada memungkinkan pengguna untuk membuat perubahan pada repositori mereka dengan membuat komit baru, mengubah yang sudah ada, membuat cabang, melakukan penggabungan lokal, dan mengambil / mendorong repositori jarak jauh.

Tidak seperti gitk, git gui berfokus pada pembuatan generasi dan anotasi file tunggal dan tidak menampilkan riwayat proyek. Namun ia menyediakan aksi menu untuk memulai sesi gitk dari dalam git gui.

git gui diketahui bekerja pada semua sistem UNIX yang populer, Mac OS X, dan Windows (di bawah Cygwin dan MSYS). Sejauh memungkinkan pedoman antarmuka pengguna OS tertentu diikuti, membuat git gui antarmuka yang cukup asli untuk pengguna.

PERINTAH

menyalahkan

Mulai penampil menyalahkan pada file yang ditentukan pada versi yang diberikan (atau direktori kerja jika tidak ditentukan).

browser

Mulai browser pohon yang memperlihatkan semua file dalam komit yang ditentukan. File yang dipilih melalui browser dibuka di penampil menyalahkan.

citool

Mulai git gui dan atur untuk membuat persis satu komit sebelum keluar dan kembali ke shell. Antarmuka dibatasi hanya untuk melakukan tindakan, sedikit mengurangi waktu startup aplikasi dan menyederhanakan menubar.

Versi: kapan

Tampilkan versi git gui yang sedang berjalan.

Holger Böhnke
sumber
Itu tidak bekerja untuk saya. Saya bisa mengklik perubahan pada baris yang diberikan, tetapi itu hanya mengubah tampilan untuk komit itu, dan baris saat ini ditampilkan sebagai this: tetapi bagaimana cara melihat versi sebelumnya dari garis dan kapan ditambahkan?
BeeOnRope
Ini adalah kasus sekali pakai yang saya tahu di mana git gui adalah solusi terbaik
cambunctious
17

Membangun dari jawaban sebelumnya, bash one-liner ini akan memberi Anda apa yang Anda cari. Ini menampilkan riwayat menyalahkan git untuk baris tertentu dari file tertentu, melalui 5 revisi terakhir:

LINE=10 FILE=src/options.cpp REVS=5; for commit in $(git rev-list -n $REVS HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done

Dalam output dari perintah ini, Anda mungkin melihat konten dari perubahan baris, atau nomor baris yang ditampilkan bahkan mungkin berubah, untuk komit tertentu.

Ini sering menunjukkan bahwa baris ditambahkan untuk pertama kalinya, setelah komit tertentu. Itu juga bisa menunjukkan baris telah dipindahkan dari bagian lain dari file.

Will Sheppard
sumber
5
Perhatikan bahwa ini adalah revisi $ REVS terakhir di mana $ FILE berubah, daripada revisi $ REVS terakhir di mana $ LINE berubah.
Max Nanasy
Jawaban mana yang Anda maksud?
Flimm
Saya tidak ingat lagi. Mungkin saya bisa membuktikan jawaban saya di masa depan dengan lebih baik.
Will Sheppard
12

Ada juga recursive-blame. Dapat diinstal dengan

npm install -g recursive-blame
Thomas W
sumber
11

Solusi yang sangat unik untuk masalah ini adalah menggunakan git log:

git log -p -M - ikuti --stat - path / ke / file / Anda

Seperti yang dijelaskan oleh Andre di sini

Mannu
sumber
1
Saya membuat alias untuk menggunakan ini: git config --global alias.changes 'log -p -M --follow --stat --'dan kemudian saya cukup mengetikgit changes path/to/your/file
Tizio Fittizio
Sejauh ini, inilah jawaban terbaik dan persis apa yang saya cari. Sederhana dan elegan.
maesk
10

Jika Anda menggunakan JetBrains Idea IDE (dan turunannya) Anda dapat memilih beberapa baris, klik kanan untuk menu konteks, lalu Git -> Tampilkan riwayat untuk seleksi. Anda akan melihat daftar komit yang memengaruhi baris yang dipilih:

masukkan deskripsi gambar di sini

warvariuc
sumber
Ini bekerja lebih baik daripada jawaban lain untuk saya (menggunakan IntelliJ). Butuh beberapa saat untuk memuat semua revisi tetapi sepadan dengan menunggu.
Steve Chambers
2

Pada Git 2.23 Anda dapat menggunakan git menyalahkan --ignore-rev

Untuk contoh yang diberikan dalam pertanyaan ini adalah:

git blame -L10,+1 src/options.cpp --ignore-rev fe25b6d

(Namun ini pertanyaan jebakan karena fe25b6d adalah revisi pertama file!)

Michael Platings
sumber
1

Berdasarkan jawaban Will Shepard, hasilnya akan mencakup garis duplikat untuk komit di mana tidak ada perubahan, sehingga Anda dapat memfilternya sebagai berikut (menggunakan jawaban ini )

LINE=1 FILE=a; for commit in $(git rev-list HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

Perhatikan bahwa saya menghapus argumen REVS dan ini kembali ke komit root. Ini karena pengamatan Max Nanasy di atas.

DavidN
sumber
1

Membangun jawaban DavidN dan saya ingin mengikuti file berganti nama:

LINE=8 FILE=Info.plist; for commit in $(git log --format='%h%%' --name-only --follow -- $FILE | xargs echo | perl -pe 's/\%\s/,/g'); do hash=$(echo $commit | cut -f1 -d ','); fileMayRenamed=$(echo $commit | cut -f2 -d ','); git blame -n -L$LINE,+1 $hash -- $fileMayRenamed; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

ref: dengan baik menampilkan sejarah ganti nama file di git log

Bill Chan
sumber
0

Saya menggunakan skrip bash kecil ini untuk melihat sejarah menyalahkan.

Parameter pertama: file untuk dilihat

Parameter selanjutnya: Lewati untuk menyalahkan git

#!/bin/bash
f=$1
shift
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    echo "--- $hash"
    git blame $@ $hash -- "$f" | sed 's/^/  /'
  done
}

Anda mungkin menyediakan parameter menyalahkan seperti -L 70, + 10 tetapi lebih baik menggunakan pencarian regex git menyalahkan karena nomor baris biasanya "berubah" dari waktu ke waktu.

stangls
sumber
0

Membangun pada stangls 's jawaban , saya menempatkan script ini di PATH saya (bahkan pada Windows) sebagai git-bh:

Itu memungkinkan saya untuk mencari semua komitmen yang melibatkan kata:

git bh path/to/myfile myWord

Naskah:

#!/bin/bash
f=$1
shift
csha=""
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    res=$(git blame -L"/$1/",+1 $hash -- "$f" 2>/dev/null | sed 's/^/  /')
    sha=${res%% (*}
    if [[ "${res}" != "" && "${csha}" != "${sha}" ]]; then
      echo "--- ${hash}"
      echo "${res}"
      csha="${sha}"
    fi
  done
}
VONC
sumber