Bir dosyadaki belirli bir satır için kayıt günlüğü alınsın mı?


503

Git'in bir dosyadaki belirli bir satıra dokunan taahhütler için bir kayıt günlüğü vermesinin bir yolu var mı ?

Gibi git blame, ama git blamesize belirli bir çizgiye dokunan SON taahhüt gösterecektir.

Gerçekten benzer bir günlük almak istiyorum, dosyanın herhangi bir yerine taahhüt listesi değil, sadece belirli bir satıra dokunan taahhüt listesi.


Yanıtlar:


631

Ayrıca bakınız Git: hangi işlemlerin bir dizi satıra dokunduğunu keşfedin .


Git 1.8.4 beri , git logsahip -Lçizgilerin bir dizi evrimini görmek için.

Örneğin, git blameçıktısına baktığınızı varsayalım . İşte -L 150,+11"Sadece çizgiler bakmak 150 + 11 150" anlamı:

$ git blame -L 150,+11 -- git-web--browse.sh
a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 150)            die "The browser $browser is not
a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 151)    fi
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 152) fi
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 153) 
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 154) case "$browser" in
81f42f11 git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:38 +0100 155) firefox|iceweasel|seamonkey|iceape)
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 156)    # Check version because firefox < 2.0 do
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 157)    vers=$(expr "$($browser_path -version)" 
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 158)    NEWTAB='-new-tab'
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 159)    test "$vers" -lt 2 && NEWTAB=''
a0685a4f git-web--browse.sh (Dmitry Potapov   2008-02-09 23:22:22 -0800 160)    "$browser_path" $NEWTAB "$@" &

Ve şimdi sıra 155'in ne olduğunu bilmek istiyorsunuz.

Sonra kullanın git log. Burada -L 155,155:git-web--browse.sh"adlı dosyada 155 ila 155 satırlarının evrimini izleyin" anlamına gelir git-web--browse.sh.

$ git log --pretty=short -u -L 155,155:git-web--browse.sh
commit 81f42f11496b9117273939c98d270af273c8a463
Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>

    web--browse: support opera, seamonkey and elinks

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- a/git-web--browse.sh
+++ b/git-web--browse.sh
@@ -143,1 +143,1 @@
-firefox|iceweasel)
+firefox|iceweasel|seamonkey|iceape)

commit a180055a47c6793eaaba6289f623cff32644215b
Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>

    web--browse: coding style

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- a/git-web--browse.sh
+++ b/git-web--browse.sh
@@ -142,1 +142,1 @@
-    firefox|iceweasel)
+firefox|iceweasel)

commit 5884f1fe96b33d9666a78e660042b1e3e5f9f4d9
Author: Christian Couder <chriscool@tuxfamily.org>

    Rename 'git-help--browse.sh' to 'git-web--browse.sh'.

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- /dev/null
+++ b/git-web--browse.sh
@@ -0,0 +127,1 @@
+    firefox|iceweasel)

2
'git log --toplama sırası --graph -u -L 155,155: git-web--browse.sh' - bu önemli bir hata verdi: 'geçersiz nesne adı 155,155'. Git sürümü: 1.8.3.2. Herhangi bir öneri?
BairDev

12
Git 1.8.4 veya üst sürümüne geçin.
Matt McClure

4
"COMA'daki 155. satırın tarihini" bilmek istiyorsam (HEAD'deki 155. satır yerine). Sadece kullanabilir miyim git log commitA-hash -L 155,155:file-name?
Ida

@Flimm, güçlü bir tercihim yok.
Matt McClure

dosya taşınmış / yeniden adlandırılmış olması dışında bu iyi çalışır ... Görünüşe göre --follow satır aralığı argümanlarıyla birleştirilmekten hoşlanmaz.
Mike Ellery

66

Pick-ax kullanarak bir dizi taahhüt alabilirsiniz.

git log -S'the line from your file' -- path/to/your/file.txt

Bu, söz konusu dosyadaki metni etkileyen tüm taahhütleri size verecektir. Dosya bir noktada yeniden adlandırıldıysa --follow-parent ekleyebilirsiniz.

Bu düzenlemelerin her birindeki taahhütleri incelemek isterseniz, sonucu şuna git şovuna yönlendirebilirsiniz:

git log ... | xargs -n 1 git show

5
Bunun nasıl yardımcı olduğunu gördüğümden emin değilim. Metin etkilenmişse, satır artık aynı değildir, bu nedenle kazma size yalnızca en son değişikliği gösterecektir. O zaman git log -S'the previous version of the line', aynen böyle yapmak zorunda kalırsınız , tıpkı bunu yapacağınız gibi git blame -L. Ve git blamesadece verilen yerde değil, her yerde metni aramak zorunda olduğu için, bundan çok daha yavaş olacaktır .
Cascabel

Daha kabul edilebilir hale getirmek için orada bir normal ifade kullanabilirsiniz. Şu anda, ayrıntılı bir komut dosyası oluşturmadan "yamalarda gezinmek" için bir yol yoktur. Gitk'in bu işlevi gelecekte yama görünümünde alacağını umuyorum.
Adam Dymitruk

3
buna neden balta denir ? :)
Ocak'ta Ciprian Tomoiagă


14

Bunu yapmanın son derece kolay bir yolu vim-kaçak kullanmaktır . Dosyayı vim'de açın, kullanmak istediğiniz satırları seçin V, ardından girin

:Glog

Artık bu satırın değiştirildiği dosyanın tüm düzeltmelerini görmek için :cnextve öğelerini kullanabilirsiniz :cprev. Herhangi bir noktada, :Gblamesha, yazar ve tarih bilgilerini görmek için girin .


13

Matt'in cevabını basitleştirmek -

git blame -L14,15 -- <file_path>

Burada bir hat için bir suçlanacaksınız 14 to 15.

Yana -Lseçenek beklediği Rangebir param olarak biz alamayan Blamekullanarak tek hat için -Loption` .

Referans


10

Bunun için yerleşik bir şey olduğuna inanmıyorum. Tek bir satırın, dosyanın geri kalanı da önemli ölçüde değişmeden birkaç kez değişmesinin nadir olması, bu nedenle satır numaralarının çok değişmesine neden olacaksınız.

Çizgi her zaman sahip olduğu konum şanslı yeterince Eğer bazı Adını hiç değişmedi bir değişkene örneğin bir ödev tanımlayan karakteristik, sizin için düzenli ifade seçim kullanabilirsiniz git blame -L. Örneğin:

git blame -L '/variable_name *= */',+1

Ancak bu sadece bu normal ifade için ilk eşleşmeyi bulur , bu nedenle çizgiyi eşleştirmek için iyi bir yolunuz yoksa, çok yararlı değildir.

Sanırım bir şeyi hackleyebilirsin. Şu anda kod yazmak için zamanım yok, ama ... bu satırlar boyunca bir şey. Koş git blame -n -L $n,$n $file. İlk alan dokundu tamamlama önceki ve ikinci alan satır numarasıdır olduğunu değiştirilemez olabilirdi beri taahhüt. Bunları alın ve çalıştırın git blame -n $n,$n $commit^ $file, yani dosya son değiştirilmeden önce taahhütten başlayarak aynı şey.

(Satırı değiştiren son işlem bir birleştirme taahhüdü ise bunun başarısız olacağını unutmayın. Birincil yol, birleştirme çakışması çözümünün parçası olarak değiştirilirse bunun gerçekleşebileceğini unutmayın.)

Düzenleme: arasında oldu bu posta listesi gönderim Mart'tan itibaren bahseder 2011 bugün tigve git guibunu yardımcı olacak bir özelliği vardır. Bu özellik git'in kendisi için dikkate alınmış, ancak bitmemiş gibi görünüyor.


6

Bu , dosya satırını göstermek git blameiçin her anlamlı revizyonu gerektirir :$LINE$FILE

git log --format=format:%H $FILE | xargs -L 1 git blame $FILE -L $LINE,$LINE

Her zamanki gibi, suçlama her satırın başında revizyon numarasını gösterir. Ekleyebilirsiniz

| sort | uniq -c

toplu sonuçlar elde etmek için, bu satırı değiştiren taahhütlerin bir listesi gibi bir şey. (Tam olarak değil, kod yalnızca hareket ettirildiyse, bu satırın farklı içerikleri için aynı işlem kimliğini iki kez gösterebilir. Daha ayrıntılı bir analiz git blameiçin bitişik işlemlerin sonuçlarıyla ilgili gecikmeli bir karşılaştırma yapmanız gerekir . )


Yine, bunun işe yaramadığını düşünüyorum, çünkü o hattın önceki konumunu izlemiyor. 2 satır önce bir satır eklenmiş olsaydı, başka bir satıra
bakarsınız

6

İşte bir git takma adını tanımlayan bir çözüm, bu yüzden bunu şu şekilde kullanabilirsiniz:

git rblame -M -n -L '/REGEX/,+1' FILE

Çıktı örneği:

00000000 18 (Not Committed Yet 2013-08-19 13:04:52 +0000 728) fooREGEXbar
15227b97 18 (User1 2013-07-11 18:51:26 +0000 728) fooREGEX
1748695d 23 (User2 2013-03-19 21:09:09 +0000 741) REGEXbar

Diğer adı .gitconfig dosyanızda tanımlayabilir veya aşağıdaki komutu çalıştırabilirsiniz.

git config alias.rblame !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); echo $line; done' dumb_param

Bu çirkin bir astardır, bu yüzden burada gizlenmiş bir eşdeğer bash işlevi:

git-rblame () {
    local commit line
    while line=$(git blame "$@" $commit 2>/dev/null); do
        commit="${line:0:8}^"
        if [ "00000000^" == "$commit" ]; then
            commit=$(git rev-parse HEAD)
        fi
        echo $line
    done
}

Kazma çözümü ( git log --pickaxe-regex -S'REGEX ' ) normal ifadeyi içeren satırın diğer değişikliklerini değil, yalnızca satır eklemelerini / silmelerini verecektir.

Bu çözümün bir sınırlaması git suçlama sadece 1. REGEX eşleşmesini döndürür, bu nedenle birden çok eşleşme varsa özyineleme başka bir satırı takip etmek için "atlayabilir". Bu "sıçramaları" tespit etmek için tam geçmiş çıktısını kontrol ettiğinizden emin olun ve ardından REGEX'inizi parazit çizgilerini yok saymak için sabitleyin.

Son olarak, tam fark elde etmek için her taahhütte git show'u çalıştıran alternatif bir sürüm :

git config alias.rblameshow !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); git show $commit; done' dumb_param

2

Git suçlama komutundaki her bir komutun özetini almak git blameve bunları birleştirmek için karıştırabilir ve git logkomutlar ekleyebilirsiniz. Aşağıdaki bash + awk betiği gibi bir şey. Taahhüt özetini kod yorumu satır içi olarak ekler.

git blame FILE_NAME | awk -F" " \
'{
   commit = substr($0, 0, 8);
   if (!a[commit]) {
     query = "git log --oneline -n 1 " commit " --";
     (query | getline a[commit]);
   }
   print $0 "  // " substr(a[commit], 9);
 }'

Bir satırda:

git blame FILE_NAME | awk -F" " '{ commit = substr($0, 0, 8); if (!a[commit]) { query = "git log --oneline -n 1 " commit " --"; (query | getline a[commit]); } print $0 "  // " substr(a[commit], 9); }'

2

Benim durumumda satır numarası zaman içinde çok değişmişti. Ayrıca "git blame -L" içinde normal ifadeyi desteklemeyen git 1.8.3'teydim. (RHEL7 hala 1.8.3'e sahiptir)

myfile=haproxy.cfg
git rev-list HEAD -- $myfile | while read i
do
    git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"
done | grep "<sometext>"

Oneliner:

myfile=<myfile> ; git rev-list HEAD -- $myfile | while read i; do     git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"; done | grep "<sometext>"

Bu elbette bir komut dosyasına veya bir işleve yapılabilir.

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.