'Git log' yapmak, belirli yollar için değişiklikleri göz ardı eder


121

git logYalnızca belirlediklerim dışındaki dosyaları değiştiren kayıtları nasıl gösterebilirim?

İle git log, gördüğüm taahhütleri belirli bir yola dokunanlara filtreleyebilirim. İstediğim, o filtreyi tersine çevirmek, böylece yalnızca belirtilenler dışındaki dokunma yollarının listelenmesini sağlamak.

İstediğimi alabilirim

git log --format="%n/%n%H" --name-only | ~/filter-log.pl | git log --stdin --no-walk

nerede filter-log.pl:

#!/usr/bin/perl
use strict;
use warnings;

$/ = "\n/\n";
<>;

while (<>) {
    my ($commit, @files) = split /\n/, $_;

    if (grep { $_ && $_ !~ m[^(/$|.etckeeper$|lvm/(archive|backup)/)] } @files) {
        print "$commit\n";
    }
}

bundan biraz daha zarif bir şey istemem dışında.

Not ben olduğumu değil dosyaları görmezden git nasıl soran. Bu dosyalar izlenmeli ve işlenmelidir. Sadece, çoğu zaman onları görmekle ilgilenmiyorum.

İlgili soru: `git log --grep = <pattern> '' nasıl ters çevrilir veya Bir örüntüyle eşleşmeyen git günlükleri nasıl gösterilir Yollar yerine commit mesajları dışında aynı soru.

2008'den itibaren bu konuyla ilgili forum tartışması: Re: Git-diff'ten dosyalar hariç tutuluyor Bu umut verici görünüyordu ama iş parçacığı kurumuş gibi görünüyor.


Yerleşik bir yol olup olmadığından emin değilim ve perl çözümünüz oldukça iyi görünüyor. Yolları komut satırı argümanları olarak kabul edecek şekilde değiştirirseniz, buna benzer bir takma ad oluşturabilir !f() { git log ... | path/to/filter-log.pl "$@" | git log --stdin --no-walk; f, hatta bu boru hattı bölümünü betiğe sarabilirsiniz.
Cascabel

Çözüm olarak, findkayıtlarını görmek istemediğim dizinleri filtrelemek için kullanıyorum . Kök düzeyindeki dizine yapılan işlemlerden günlük girişlerini göz ardı etmek SiteConfigisteseydim şunu söylerdim:git log `find . -type d -mindepth 1 -maxdepth 1 ! -name *SiteConfig`
Noah Sussman

Git 1.9 / 2.0 (Q1 2014) için, aşağıdaki cevabıma bakın : git log --oneline --format=%s -- . ":!sub"işe yarayacak ( pathspec büyüsü :(exclude)ve kısa biçimi ile:! )
VonC

Yanıtlar:


214

Şimdi giriş ile (git 1.9 / 2.0, Q1 2014) uygulanmaktadır pathspec büyü :(exclude)ve kısa formda:! yer ef79b1f taahhüt ve 1649612 taahhüt tarafından, Nguyen Tay Ngọc Duy ( pclouds) , dokümantasyon bulunabilir burada .

Artık bir alt klasör içeriği dışında her şeyi günlüğe kaydedebilirsiniz:

git log -- . ":(exclude)sub"
git log -- . ":!sub"

Veya bu alt klasördeki belirli öğeleri hariç tutabilirsiniz

  • belirli bir dosya:

      git log -- . ":(exclude)sub/sub/file"
      git log -- . ":!sub/sub/file"
  • içindeki herhangi bir dosya sub:

      git log -- . ":(exclude)sub/*file"
      git log -- . ":!sub/*file"
      git log -- . ":(exclude,glob)sub/*/file"

Hariç tutma durumunu duyarsız hale getirebilirsiniz!

git log -- . ":(exclude,icase)SUB"

As Kenny Evitt kaydetti

Git'i bir Bash kabuğunda çalıştırıyorsanız, hataları önlemek için ':!sub'veya ":\!sub"yerine kullanınbash: ... event not found


Not: Git 2.13 (Q2 2017) eşanlamlısını katacak ^için!

Bkz 859b7f1 işlemek , 42ebeb9 taahhüt tarafından (08 Şubat 2017) Linus Torvalds ( torvalds) .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde 015fba3 tamamlama 2017 27 Şubat)

pathspec sihirli: 'eklemek ^' için takma ad olarak ' !'

!Negatif yol belirtimi için ' ' seçimi, yalnızca revizyonlar için yaptığımızla eşleşmekle kalmaz, aynı zamanda alıntı yapılması gerektiğinden kabuk genişletme için de korkunç bir karakterdir.

Bu nedenle ^, bir yol belirtme girişini hariç tutmak için alternatif bir diğer ad olarak ' ' ekleyin .


Git 2.28'den (Q3 2020) önce, çalışma ağacında izlenmeyenler de dahil olmak üzere yollar toplanırken negatif yol belirtiminin kullanımının kırıldığını unutmayın.

Elijah Newren ( ) tarafından f1f061e (05 Haziran 2020) taahhüdüne bakın . (Göre Birleştirilmiş - Junio Cı Hamano - içinde 64efa11 tamamlama 2020 18 Haz)newren
gitster

dir: olumsuzlanmış yol özelliklerinin tedavisini düzelt

Bildiren: John Millikin
İmza: Elijah Newren

do_match_pathspec()match_pathspec_depth_1()ve doğruluk için sadece çağrılması gerektiği için hayata başladı match_pathspec_depth(). match_pathspec_depth()daha sonra olarak yeniden adlandırıldı match_pathspec(), bu nedenle bugün beklediğimiz değişmez, do_match_pathspec()dışında doğrudan arayan olmamasıdır match_pathspec().

Ne yazık ki, iki işlevin yeniden adlandırılmasıyla bu niyet kayboldu ve 75a6315f74 işlemlerine ek çağrılar do_match_pathspec()eklendi (" : alt modüller için yol belirtimi eşleşmesi ekle", 2016-10-07, Git v2.11.0-rc0 - birleştirme listelenen toplu iş # 11 ) ve 89a1f4aaf7 (" : yol belirtimimiz bir dizin altındaki dosyalarla eşleşebiliyorsa, içinde tekrarlayın", 2019-09-17, Git v2.24.0-rc0).ls-filesdir

Tabii ki, do_match_pathspec()üzerinde önemli bir advantge vardı match_pathspec()- match_pathspec()iki değer ve bayrakları için başka bir değer geçmek için gerekli olan bu yeni arayanların birine bayrakları hardcode olacaktır.

Ayrıca, do_match_pathspec()doğrudan arama yanlış olsa da, gözlemlenebilir son çıktıda büyük olasılıkla herhangi bir fark yoktu, çünkü hata sadece bunun fill_diretory()gereksiz dizinlerde tekrarlanacağı anlamına geliyordu .

Dizinin altındaki tek tek yollar üzerinde daha sonra yapılan bu-yol-eşleştirme kontrolleri bu ekstra yolların filtrelenmesine neden olacağından, yanlış işlevi kullanmaktan tek fark gereksiz hesaplamadır.

Bu kötü çağrılardan ikincisi do_match_pathspec()- ya doğrudan hareket ya da kopyalama + düzenleme yoluyla - daha sonraki birkaç yeniden yapılandırmaya dahil edildi.

Bkz. 777b420347 (" dir: senkronize et treat_leading_path()ve read_directory_recursive()", 2019-12-19, Git v2.25.0-rc0 - birleştirme ), 8d92fb2927 (" dir: üstel algoritmayı doğrusal olanla değiştir", 2020-04-01, Git v2.27.0 -rc0 - toplu işlemde listelenen birleştirme ) ve 95c11ecc73 ("Hataya eğilimli API'yi düzelt ; yalnızca eşleşmeleri döndürmesini sağla", 2020-04-01, Git v2.27.0-rc0 - toplu iş # 5'te listelenen birleştirme ) .fill_directory()

Bunların sonuncusu, do_match_pathspec()tek bir dosyada kullanımını başlattı ve bu nedenle, olmaması gereken tek tek yolların döndürülmesiyle sonuçlandı.

Çağırma sorunu do_match_pathspec()yerine match_pathspec()! Unwanted_path`` göz ardı edilecektir: Böyle `' gibi herhangi olumsuzlanan desenler olmasıdır .

match_pathspec_with_flags()Negatiflenmiş kalıpları doğru bir şekilde kontrol ederken özel bayrakları belirleme gereksinimlerini karşılamak için yeni bir işlev ekleyin, do_match_pathspec()başkalarının kötüye kullanmasını önlemek için yukarıya büyük bir yorum ekleyin ve do_match_pathspec()bunun yerine ya match_pathspec()da kullanmak yerine mevcut arayanları düzeltin match_pathspec_with_flags().

Son bir not, DO_MATCH_LEADING_PATHSPECbirlikte çalışırken özel dikkat gerektiren DO_MATCH_EXCLUDE.

Buradaki nokta DO_MATCH_LEADING_PATHSPECşudur ki, aşağıdaki gibi bir yol belirtimimiz varsa

*/Makefile

ve gibi bir dizin yolunu kontrol ediyoruz

src/module/component

onu bir eşleşme olarak kabul etmek istiyoruz, böylece dizinde yineleniriz, çünkü aşağıda _mightbir Makefileyerde adlandırılmış bir dosyaya sahiptir .

Bununla birlikte, bir dışlama kalıbı kullandığımızda, yani şöyle bir yol belirtimiz var:

:(exclude)*/Makefile

gibi bir dizin yolu olduğunu söylemek İSTEMİYORUZ

src/module/component

(negatif) bir eşleşmedir.

Oradayken olabilir bu dizinin altındaki 'Makefile' yere adında bir dosya olması, ayrıca diğer dosyaları olabilir ve biz emptively-öncesi Çek şu dizin altındaki tüm dosyaları ardı edemeyiz; yinelememiz ve ardından dosyaları tek tek kontrol etmemiz gerekir.

Ayarlayın DO_MATCH_LEADING_PATHSPECmantığı sadece olumlu pathspecs için devreye girecek şekilde.


7
Birden fazla dosya yapabilir misin?
Justin Thomas

12
@JustinThomas inanıyorum ki (henüz test edilmemiştir) bu yol dışlama modelini birden çok kez tekrarlayabilir ":(exclude)pathPattern1" ":(exclude)pathPattern2", dolayısıyla birden çok klasörü / dosyayı görmezden gelirsiniz .
VonC

7
Git'i bir Bash kabuğunda çalıştırıyorsanız, hataları önlemek için ':!sub'bunun yerine kullanın . çalışmıyor. bash: ... event not found":\!sub"
Kenny Evitt

1
@KennyEvitt Düzenlemeniz ve yorumunuz için teşekkür ederiz. Daha fazla görünürlük için ikincisini cevaba dahil ettim.
VonC

2
Bu işlevle ilgili resmi belgelerin nerede olduğunu merak edenler için, bkz. git help glossary( git help -g[İçinde önerildiğini bulduğum listede buldum git help]).
ravron

4

tl; dr: shopt -s extglob && git log !(unwanted/glob|another/unwanted/glob)

Eğer kullanıyorsanız Bash kullanmak gerekir genişletilmiş globbing ihtiyacınız olan dosyaları almak için özelliği:

$ cd -- "$(mktemp --directory)" 
$ git init
Initialized empty Git repository in /tmp/tmp.cJm8k38G9y/.git/
$ mkdir aye bee
$ echo foo > aye/foo
$ git add aye/foo
$ git commit -m "First commit"
[master (root-commit) 46a028c] First commit
 0 files changed
 create mode 100644 aye/foo
$ echo foo > bee/foo
$ git add bee/foo
$ git commit -m "Second commit"
[master 30b3af2] Second commit
 1 file changed, 1 insertion(+)
 create mode 100644 bee/foo
$ shopt -s extglob
$ git log !(bee)
commit ec660acdb38ee288a9e771a2685fe3389bed01dd
Author: My Name <jdoe@example.org>
Date:   Wed Jun 5 10:58:45 2013 +0200

    First commit

globstarÖzyinelemeli eylem için bunu ile birleştirebilirsiniz .


7
Bu, artık var olmayan dosyaları etkileyen kayıtları göstermez. Aynı şekilde çok yakın ve güzel hack.
Anonymoose

-2

Bir dosyadaki değişiklikleri geçici olarak göz ardı edebilirsiniz :

git update-index --skip-worktree path/to/file

Bu dosyalara tüm değişiklikler tarafından göz ardı edilecektir Bundan sonra git status, git commit -abu dosyaları işlemek için hazır olduğunuzda, sadece ters vb:

git update-index --no-skip-worktree path/to/file

ve normal şekilde taahhüt edin.


9
Bu biraz farklı bir durumu ele alıyor gibi görünüyor. zaten yapılmış olan işlemlerin filtrelenmesine git update-index --skip-worktreeneden olmaz git log.
Anonymoose
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.