ÖNEMLİ : Kendim için aldığım notlar. Umarım size de bir faydası olur. Kullanılan her bir makale referans olarak eklenmiştir.

Git-blame Nedir??

Git-blame komutu, belirli bir dosyanın her bir satırını en son kim tarafından ve hangi commit ile değiştirildiğini göstermek için kullanılır. Git version kontrol sisteminde belirli bir dosyanın belirli bir zaman noktasındaki değişikliklerini, özetle o dosyanın geçmişini araştırırken yararlı bir komuttur.

GIT-BLAME(1)                                          Git Manual                                          GIT-BLAME(1)

NAME
       git-blame - Show what revision and author last modified each line of a file

SYNOPSIS
       git blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
                   [-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
                   [--ignore-rev <rev>] [--ignore-revs-file <file>]
                   [--color-lines] [--color-by-age] [--progress] [--abbrev=<n>]
                   [<rev> | --contents <file> | --reverse <rev>..<rev>] [--] <file>

Git blame Örnek

% git blame sample.txt           
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 4) Sample text 4

Görüleceği üzere sample.txt dosyasındaki bütün değişiklikler, değişiklikleri yapan kullanıcılar, değişikliklerin commit id’leri ve satır numaraları çıktı olarak ekrana yazdırılmıştır.

Git blame -L Option

Burada dikkat edilmesi gereken ana seçenek(option) “-L“‘dir. Bu seçenek, istenirse tüm dosya yerine, bir satır aralığı belirterek ilgili dosyayı görüntülemenizi sağlar. Örneğin;

% git blame -L1,2 sample.txt
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
% git blame -L1,3 sample.txt
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3

-L” seçeneğinden yoksun örnekte bütün dosyadaki satırlar, sıra numarası, commit id’si ve yazar ismi ile basılırken, “-L” seçeneği kullandığımız git blame komutu ilk örnekte sadece 1. ve 2. satırları, ikinci örnekte ise 1. ve 3. satırlar arasındaki satırları çıktı olarak verecektir.

% git blame -L1,+2 sample.txt
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2

Bu arada aynı çıktıyı bu şekilde de alabiliriz. “-L1,+2”, buradaki +2 ifadesinde, 1. satır başlangıç noktası kabul ederek, sonrasındaki 2 satırı çıktı olarak almamızı söylüyor.

Git-blame -L /regex/

Satır aralıklarının başlangıcı ve bitişi için normal ifadeler (regular expression) de kullanabilirsiniz. Bunu yapmak için eğik çizgiler (/ /) içinde aramak istediğiniz ifadeyi belirtirsiniz.

sample.txt

1
2
3
4
Sample text 1
Sample text 2
Sample text 3
Sample text 4

Örneğin, “text 2” normal ifadesinin ilk göründüğü satırdan başlayarak iki satır sonrasına bakmak için aşağıdaki komutu kullanabilirsiniz;

% git blame -L"/text 2/",+2 sample.txt
ef1eddc1 (cortix 2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix 2023-01-05 19:37:50 +0300 3) Sample text 3

Normal ifadeleri ararken kullanılan başka bir yöntemi göstermek istiyorum. Diyelim ki spesifik bir fonksiyonu aratmak istiyorum. Aşağıdakine benzer bir koda sahip olduğumuzu varsayalım ve printList fonsiyonunu git-blame -L komutu ile aratmak istiyorum.

SelectionSortAlgorithm.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class InsertionSort {

    public static void main(String[] args) {
        int[] list = {9,4,3,1,5,8,2};
        for (int j = 1; j < list.length; j++) {
            int key = list[j];
            int i = j - 1;
            while (i >= 0 && list[i] > key) {
                list[i + 1] = list[i];
                i = i - 1;
            }
            list[i+1] = key;
        }
        printList(list);
    }

    public static void printList(int [] list) {
        Arrays.stream(list)
              .forEach(value -> System.out.print(value + " - "));
    }

    public static void printList1(int [] list) {
        Arrays.stream(list)
              .forEach(value -> System.out.print(value + " - "));
    }
}

İlk arama sonucumuz aşağıdaki gibidir. Arama alanını sınırlamak için başlangıç ​​değeri olarak “/printList(/” normal ifadesinin ve bitiş değeri olarak ise “/}/” normal ifadesinin kullanıldığına dikkat edin. Yalnız bu arama bize 14 ve 15. satırları işgal eden, ilgili metodunun çağrıldığı çıktıyı verir.

% git blame -L"/printList(/","/}/" SelectionSortAlgorithm.java
4952f4dd (rosenxyz 2023-01-07 14:49:55 +0300 14)         printList(list);
4952f4dd (rosenxyz 2023-01-07 14:49:55 +0300 15)     }

Aramayı aşağıdaki gibi günceller isek doğrudan metodun kendisini, aralık olarak sadece normal ifadeler kullanarak elde edebiliriz. Komutu rakam aralığı vererek oluşturmadığımıza dikkat edin!

% git blame -L"/printList(int/","/}/" SelectionSortAlgorithm.java
4952f4dd (rosenxyz 2023-01-07 14:49:55 +0300 17)     public static void printList(int [] list) {
4952f4dd (rosenxyz 2023-01-07 14:49:55 +0300 18)         Arrays.stream(list)
4952f4dd (rosenxyz 2023-01-07 14:49:55 +0300 19)               .forEach(value -> System.out.print(value + " - "));
4952f4dd (rosenxyz 2023-01-07 14:49:55 +0300 20)     }

-L” diğer seçeneklere kıyasla daha çok kullanılan bir option olduğu için, bu seçeneğin kullanım formülasyonunu gösteren çıktıyı sayfa sonuna ekledim.

Git blame -e option

-e seçeneği, kullanıcı adı yerine yazarın e-posta adresini gösterir.

Örneğin yukarıdaki sample.txt dosyasını incelediğimiz örneği “-e” seçeneği kullanarak tekrar çalıştıralım istiyorum.

% git blame -e sample.txt                 
b74c86b8 (<[email protected]> 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (<[email protected]>   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (<[email protected]>   2023-01-05 19:37:50 +0300 3) Sample text 3
c62535da (<[email protected]> 2023-01-07 15:35:15 +0300 4) Sample text 5

Git blame -w option

Farklı bir branch’te Sample text 4 commit’inde bıraktığım sample.txt dosyası üzerinde bir değişiklik yapmak istiyorum.

% git blame sample.txt   
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 4) Sample text 4

Örneğin son satırın bitti “Sample text 4” ifadesi peşi sıra boşluk bırakıp, bu boşluğu commit’leyelim istiyorum.

% git blame sample.txt
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3
d4f3b5fc (rosenxyz 2023-01-13 20:11:24 +0300 4) Sample text 4  

görüleceği üzere son satırdaki commit değişti. Şimdi bu commit’e bir bakalım.

git blame w option


Şekilden de görüleceği üzere son commit son satırda yapmış olduğumuz değişiklik olan boşlukları temsil etmektedir. Yalnız -w seçeneğini kullanırsak bu boşluklu commit’ler big blame tarafından görmezden gelinir. Örneğin;

% git blame -w sample.txt
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 4) Sample text 4   

Görüleceği üzere son satır eski commit’i gösteriyor.

Git blame aralık belirleme(specifying range)

Örneğin belli bir commit’den öncesini görmek istemiyoruz. Yani bahsettiğim bu commit’i başlangıç noktası kabul edip, sonrasında olan değişiklikleri göstermek istiyoruz.

% git blame sample.txt
b74c86b8 (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3
d4f3b5fc (rosenxyz 2023-01-13 20:11:24 +0300 4) Sample text 4  

başlangıç noktamız b74c86b8 bu commit olsun.

% git blame b74c86b8.. sample.txt
^b74c86b (rosenxyz 2023-01-05 19:36:32 +0300 1) Sample text 1
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
ef1eddc1 (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3
d4f3b5fc (rosenxyz 2023-01-13 20:11:24 +0300 4) Sample text 4    

görüleceği üzere başlangıç kabul ettiğimiz commit’in id’sinin başında ^ sembolü yer alıyor. Şimdi bu id’yi ef1eddc1 olarak değiştirelim.

% git blame ef1eddc1.. sample.txt
^ef1eddc (cortix   2023-01-05 19:37:50 +0300 1) Sample text 1
^ef1eddc (cortix   2023-01-05 19:37:50 +0300 2) Sample text 2
^ef1eddc (cortix   2023-01-05 19:37:50 +0300 3) Sample text 3
d4f3b5fc (rosenxyz 2023-01-13 20:11:24 +0300 4) Sample text 4  

benzer aralığı tarih ve sürüm bazında da yapabiliriz. Örneğin, Sürüm v1.0.01’den eski veya 3 haftadan eski değişikliklerle ilgilenmiyorsanız, git rev-list’e benzer revizyon aralığı belirticileri kullanabilirsiniz:

git blame v1.0.01.. -- sample.txt
git blame --since=3.weeks -- sample.txt

Sözlük

“-L” Option:

-L <start>,<end>, -L :<funcname>
    Annotate only the line range given by <start>,<end>, or by the function name regex <funcname>. May be
    specified multiple times. Overlapping ranges are allowed.

    <start> and <end> are optional.  -L <start> or -L <start>, spans from <start> to end of file.  -L ,<end>
    spans from start of file to <end>.

    <start> and <end> can take one of these forms:

    •   number

        If <start> or <end> is a number, it specifies an absolute line number (lines count from 1).

    •   /regex/

        This form will use the first line matching the given POSIX regex. If <start> is a regex, it will search
        from the end of the previous -L range, if any, otherwise from the start of file. If <start> is
        ^/regex/, it will search from the start of file. If <end> is a regex, it will search starting at the
        line given by <start>.

    •   +offset or -offset

        This is only valid for <end> and will specify a number of lines before or after the line given by
        <start>.

    If :<funcname> is given in place of <start> and <end>, it is a regular expression that denotes the range
    from the first funcname line that matches <funcname>, up to the next funcname line.  :<funcname> searches
    from the end of the previous -L range, if any, otherwise from the start of file.  ^:<funcname> searches
    from the start of file. The function names are determined in the same way as git diff works out patch hunk
    headers (see Defining a custom hunk-header in gitattributes(5)).

Referanslar