Pertanyaan Cara membalikkan `git log --grep = ` atau Cara menampilkan git logs yang tidak cocok dengan pola


Saya ingin menggunakannya git log untuk menampilkan semua commit yang tidak cocok dengan pola yang diberikan. Saya tahu saya dapat menggunakan yang berikut ini untuk menampilkan semua commit yang cocok dengan sebuah pola:

git log --grep=<pattern>

Bagaimana cara membalikkan rasa kecocokan?

Saya mencoba mengabaikan komit yang "bermasalah dengan versi ..." dalam pesan.

EDIT: Saya ingin hasil akhir saya cukup verbose. misalnya git log --pretty --stat. Jadi keluarannya git log --format=oneline tidak akan bekerja untukku.


32
2018-04-09 01:05


asal


Jawaban:


Buat daftar semua commit, kurangi yang pesan lognya berisi pola yang menyinggung, dan berikan hasilnya git log dengan opsi yang Anda inginkan. Di tahap akhir, beberapa opsi untuk git log berguna:

--stdin
  Selain itu melakukan terdaftar di baris perintah, baca dari input standar.

--no-walk
  Hanya menunjukkan revs yang diberikan, tetapi tidak melintasi leluhur mereka.

Anda dapat melakukannya dengan satu jalur pipa dan substitusi proses.

#! /bin/bash

if (( $# < 1 )); then
  echo >&2 "Usage: $0 pattern [<since>..<until>]"
  exit 1
fi

pattern=$1
shift

git log --format=%H $@ |
  grep -v -f <(git log --format=%H "--grep=$pattern" $@) |
  git log --pretty --stat --stdin --no-walk

Jika Anda tidak ingin menggunakan bash, Anda bisa melakukannya dengan Perl.

#! /usr/bin/env perl

use strict;
use warnings;
no warnings "exec";

sub usage { "Usage: $0 pattern\n" }

sub commits_to_omit {
  my($pattern) = @_;

  open my $fh, "-|", "git", "log", "--grep=$pattern", "--format=%H", @ARGV
    or die "$0: exec: $!";
  my %omit = map +($_ => 1), <$fh>;
  %omit;
}

die usage unless @ARGV >= 1;
my $pattern = shift;

my %omit = commits_to_omit $pattern;

open my $all, "-|", "git", "log", "--format=%H", @ARGV
  or die "$0: exec: $!";

open my $out, "|-", "git", "log", "--pretty", "--stat", "--stdin", "--no-walk"
  or die "$0: exec: $!";

while (<$all>) {
  print $out $_ unless $omit{$_};
}

Dengan asumsi salah satu di atas adalah di PATH Anda sebagai git-log-vgrep dan dengan sejarah bentuk

$ git lola
* b0f2a28 (tmp, feature1) D
* 68f87b0 C
* d311c65 B
* a092126 A
| * 83052e6 (HEAD, origin / master, master) Z
| * 90c3d28 Y
| * 4165a42 X
| * 37844cb W
| /
* f8ba9ea V

kita bisa katakan

$ git log-vgrep X

untuk mendapatkan Z, Y, W, dan V.

Anda juga dapat mencatat cabang lain, jadi

$ git log-vgrep Sebuah tmp

memberikan D, C, B, dan V; dan

$ git log-vgrep C tmp ~ 2..tmp

menghasilkan hanya D.

Salah satu batasan dari implementasi di atas adalah jika Anda menggunakan pola yang cocok dengan semua commit, misalnya, . atau ^, maka Anda akan mendapatkan KEPALA. Begini caranya git log bekerja:

$ git log --stdin --no-walk --pretty = oneline </ dev / null
83052e62f0dc1c6ddfc1aff3463504a4bf23e3c4 Z

15
2018-04-09 17:02



Ini akan dimungkinkan dengan Git 2.4+ (Q2 2015): Lihat komit 22dfa8a oleh Christoph Junghans (junghans):

log: mengajar --invert-grep pilihan

"git log --grep=<string>"menunjukkan hanya melakukan dengan pesan yang cocok dengan string yang diberikan, tetapi kadang-kadang berguna untuk dapat menunjukkan hanya commit yang dilakukan tidak memiliki pesan tertentu (mis. "tunjukkan pada saya yang bukan merupakan FIXUP commit").

Awalnya, kami punya invert-grep bendera masuk grep_opt, tapi karena "git grep --invert-grep"Tidak masuk akal kecuali dalam hubungannya dengan"--files-with-matches", yang sudah ditutupi oleh"--files-without-matches", dipindahkan ke struktur revisi.
  Untuk memiliki bendera ada yang menyatakan fungsi ke fitur lebih baik.

Ketika dua tes yang baru disisipkan berjalan, sejarah akan melakukan dengan pesan "initial","second","third","fourth","fifth","sixth"   dan "Second", berkomitmen dalam urutan ini.
  Komit yang tidak cocok "th" atau "Sec" aku s "second"dan"initial". Untuk kasus tidak sensitif huruf"initial"cocok.

--invert-grep

Batasi keluaran commit ke yang dengan pesan log yang tidak sesuai dengan pola yang ditentukan --grep=<pattern>.

Contoh:

Saya pesan grep pertama dengan "sequencer" di dalamnya:

vonc@voncm C:\Users\vonc\prog\git\git

> git log -2 --pretty="tformat:%s" --grep=sequencer
Merge branch 'js/sequencer-wo-die'
sequencer: ensure to release the lock when we could not read the index

Jika saya ingin pesan dengan tidak sequencer:

> git log -2 --pretty="tformat:%s" --grep=sequencer --invert-grep
Second batch for 2.11
Merge branch 'js/git-gui-commit-gpgsign'

21
2018-02-15 04:47



Metode yang relatif sederhana dengan banyak fleksibilitas adalah menggunakan git log dengan opsi -z disalurkan ke awk. Opsi -z menambahkan null di antara catatan commit, dan membuatnya lebih mudah di-parse dengan awk:

git log --color=always -z | awk -v RS=\\0

(warna = selalu diperlukan untuk terus mewarnai ketika output adalah pipa). Kemudian, sederhana untuk menambahkan ekspresi boolean apa pun yang Anda inginkan yang berfungsi di setiap bidang. Sebagai contoh, ini akan mencetak semua entri di mana email penulis tidak dari fugly.com, dan hari komit itu adalah hari Minggu:

git log --color=always -z | awk -v RS=\\0 '!/Author:.*fugly.com>/ && /Date:.* Sun /'

Hal lain yang menyenangkan adalah Anda dapat menambahkan opsi pemformatan atau rentang revisi ke git log, dan masih berfungsi.

Satu hal lagi, jika Anda ingin nomor halaman, gunakan "less -r" untuk menyimpan warna.

EDIT: diubah untuk digunakan -v di awk untuk membuatnya sedikit lebih sederhana.


8
2017-10-19 18:44



dapatkan daftar semua commit yang berisi hasil Anda, lalu saring hash mereka.

git log --format=oneline | grep -v `git log --grep="bumped to version" --format="%h"`

1
2018-04-09 01:26



Seperti halnya jawaban thebriguy, grep juga memiliki opsi -z untuk mengaktifkannya dengan string null yang diakhiri alih-alih garis. Ini akan sesederhana membalikkan pertandingan:

git log -z --color | grep -vz "bumped to version"

Untuk keamanan, Anda mungkin ingin mencocokkan hanya dalam pesan commit. Untuk melakukan ini dengan grep, Anda perlu menggunakan ekspresi mutiara untuk mencocokkan baris baru dalam string yang diakhiri null. Untuk melewati header:

git log -z | grep -Pvz '^commit.*\nAuthor:.*\nDate:.*\n[\S\s]*bumped to version'

Atau dengan warna:

git log -z --color | \
  grep -Pvz '^.....commit.*\nAuthor:.*\nDate:.*\n[\S\s]*bumped to version'

Akhirnya, jika menggunakan --stat, Anda juga dapat mencocokkan awal dari output ini untuk menghindari nama file yang cocok yang berisi string commit. Jadi jawaban penuh untuk pertanyaan itu akan terlihat seperti:

log -z --color --pretty --stat | \
  grep -Pvz '^.....commit.*\nAuthor:.*\nDate:.*\n[\S\s]*?bumped to version[\S\s]*?\n [^ ]'

Perhatikan itu grep -P digambarkan sebagai 'sangat eksperimental' di halaman manual saya. Mungkin lebih baik digunakan pcregrep alih-alih yang menggunakan libpcre, lihat Bagaimana cara memberikan pola untuk baris baru di grep?. Meskipun grep -P berfungsi dengan baik untuk saya dan saya tidak tahu jika pcregrep memiliki opsi -z atau yang setara.


1
2017-09-21 11:10



Sejauh yang saya tahu, ini tidak mungkin dilakukan secara langsung dengan satu baris perintah; Anda harus melakukan sesuatu seperti yang disarankan Justin Lilly dan kemudian jalankan 'git log' pada daftar hash yang dihasilkan, misalnya,

git log --format="%h" | grep -v `git log -1 --grep="bumped to version" --format="%h"` > good-hashes
for h in `cat good-hashes`; do
    PAGER=cat git log -1 --pretty --stat $h
done

harus melakukan trik.


0
2018-04-09 02:45



Seperti yang disebutkan oleh VonC, opsi terbaik adalah jika Anda dapat memperbarui ke Git 2.4.0 (yang saat ini ada di RC2). Tetapi bahkan jika Anda tidak dapat melakukannya, tidak ada alasan untuk skrip yang rumit. A (gnu) awk one-liner harus melakukannya. git log memiliki yang berguna -z opsi untuk memisahkan komit oleh karakter NUL yang membuatnya mudah untuk menguraikannya:

git log -z --pretty --stat | awk 'BEGIN{ RS="\0"; FS="\n\n" } !match($2, /<pattern>/)'

Jika Anda tidak memiliki gnu awk, Anda mungkin setidaknya harus menginstalnya. Atau port skrip ini ke versi awk khusus Anda, yang saya tinggalkan sebagai latihan untuk pembaca ;-).


0
2018-04-21 09:11



git log --pretty --stat | grep -v "bumped to version"

-1
2018-04-09 01:39