Git farkından çıktı nasıl okunur?


271

Man sayfası git-diffoldukça uzun ve yeni başlayanlar için gerekli görünmeyen birçok durumu açıklıyor. Örneğin:

git diff origin/master

1
farklı bir metin editörü kullanarak satır numaraları için @ ... @ aralık gösterimleri belli oldu.
poseid

Hangi metin editörü?
Jus12

Yanıtlar:


489

Git geçmişinden ileri fark örneğine bakalım (git.git deposundaki 1088261f işleminde ):

diff --git a/builtin-http-fetch.c b/http-fetch.c
similarity index 95%
rename from builtin-http-fetch.c
rename to http-fetch.c
index f3e63d7..e8f44ba 100644
--- a/builtin-http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,9 @@
 #include "cache.h"
 #include "walker.h"

-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
 {
+       const char *prefix;
        struct walker *walker;
        int commits_on_stdin = 0;
        int commits;
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
        int get_verbosely = 0;
        int get_recover = 0;

+       prefix = setup_git_directory();
+
        git_config(git_default_config, NULL);

        while (arg < argc && argv[arg][0] == '-') {

Bu yamayı satır satır analiz edelim.

  • İlk satır

    diff --git a / builtin-http-fetch.cb / http-fetch.c
    formdaki bir "git diff" başlığıdır diff --git a/file1 b/file2. Yeniden adlandırma / kopyalama söz konusu olmadıkça (bizim durumumuzda olduğu gibi) a/ve b/dosya adları aynıdır. Bu --git, diff'in "git" diff formatında olduğu anlamına gelir.

  • Sonraki, bir veya daha fazla genişletilmiş başlık satırıdır. İlk üç

    benzerlik endeksi% 95
    builtin-http-fetch.c dosyasından yeniden adlandır
    http-fetch.c olarak yeniden adlandır
    dosyasından yeniden adlandırıldı ki bize builtin-http-fetch.ckarşı http-fetch.cve bu iki dosya (bu yeniden adlandırma algılamak için kullanılan)% 95 aynı olduğunu.

    Genişletilmiş fark başlığındaki son satır,
    dizin f3e63d7..e8f44ba 100644
    bize verilen dosyanın modu ( 100644örneğin, symlink değil sıradan bir dosya olduğu ve yürütülebilir izin bitine sahip olmadığı anlamına gelir) ve kısaltılmış preimage karması (verilen değişiklikten önceki dosya sürümü) ve postimage ( değişiklik sonrası dosyanın sürümü). Bu satır, git am --3waydüzeltme eki uygulanamazsa 3 yönlü birleştirme yapmaya çalışmak için kullanılır .

  • Sıradaki iki satırlı birleşik fark başlığı

    --- a / builtin-http-fetch.c
    +++ b / http-fetch.c
    Sonuçla karşılaştırıldığında, diff -Ukaynak (preimage) ve hedef (postimage) dosya adlarından sonra dosyadan dosya değiştirme zamanına veya dosyadan dosyaya değişiklik zamanına sahip değildir. Dosya oluşturulduysa kaynak /dev/null; dosya silinmişse hedeftir /dev/null.
    Eğer ayarlarsanız diff.mnemonicPrefixyerine true yapılandırma değişkeni a/ve b/bu iki satırlı başlığında önekleri yerine olabilir c/, i/, w/ve o/sırasıyla karşılaştırmak ne önekleri olarak; bkz. git-config (1)

  • Sonra bir ya da daha fazla farklılık yığını gelir; her parça, dosyaların farklı olduğu bir alanı gösterir. Birleştirilmiş biçim parçaları, aşağıdaki gibi başlar

    @@ -1,8 +1,9 @@
    veya
    @@ -18,6 +19,8 @@ int cmd_http_fetch (int argc, const char ** argv, ...
    Biçimdedir @@ from-file-range to-file-range @@ [header]. Dosyadan dosya aralığı biçimindedir -<start line>,<number of lines>ve dosyaya dosya aralığıdır +<start line>,<number of lines>. Hem başlangıç ​​çizgisi hem de satır sayısı, sırasıyla preimage ve postimage'deki iri parçanın konumunu ve uzunluğunu ifade eder. Satır sayısı gösterilmiyorsa 0 olduğu anlamına gelir.

    İsteğe bağlı üstbilgi, bir C dosyası ( -pGNU diff'deki seçenek gibi ) veya diğer dosya türleri için eşdeğerse, her değişikliğin gerçekleştiği C işlevini gösterir .

  • Ardından, dosyaların nerede farklılık gösterdiğinin açıklaması gelir. Her iki dosya için ortak olan satırlar boşluk karakteriyle başlar. İki dosya arasında gerçekten farklı olan çizgiler, sol yazdırma sütununda aşağıdaki gösterge karakterlerinden birine sahiptir:

    • '+' - Buraya ilk dosyaya bir satır eklendi.
    • '-' - İlk dosyadan burada bir satır kaldırıldı.


    Yani, örneğin, ilk yığın

     #include "cache.h"
     #include "walker.h"
    
    -int cmd_http_fetch(int argc, const char **argv, const char *prefix)
    +int main(int argc, const char **argv)
     {
    +       const char *prefix;
            struct walker *walker;
            int commits_on_stdin = 0;
            int commits;
    

    aracı cmd_http_fetchile değiştirildi main, ve bu const char *prefix;hat ilave edildi.

    Başka bir deyişle, değişiklikten önce, 'builtin-http-fetch.c' dosyasının uygun parçası şöyle görünüyordu:

    #include "cache.h"
    #include "walker.h"
    
    int cmd_http_fetch(int argc, const char **argv, const char *prefix)
    {
           struct walker *walker;
           int commits_on_stdin = 0;
           int commits;
    

    Değişiklikten sonra şimdi 'http-fetch.c' dosyasının bu parçası bunun yerine şöyle görünür:

    #include "cache.h"
    #include "walker.h"
    
    int main(int argc, const char **argv)
    {
           const char *prefix;
           struct walker *walker;
           int commits_on_stdin = 0;
           int commits;
    
  • Olabilir

    \ Dosyanın sonunda yeni satır yok
    mevcut (örnekte farklı değildir).

As Donal Fellows söyledi bunu değiştin biliyor gerçek hayattan örneklerle, okuma diffs uygulamaya en iyisidir.

Referanslar:


1
@Geremia: Git, yeniden adlandırma algılaması için benzerlik tabanlı buluşsal yöntemler kullanır ... ve ayrıca kod taşıma ve kopyalama algılaması için de git blame -C -Cböyle çalışır; Git tasarım kararıdır. Git diff formatı kullanıcıya benzerlik (veya farklılık) indeksini gösterir.
Jakub Narębski

1
@Geremi: Daha kesin olmak gerekirse, [header]bir iri parçadan önce gelen fonksiyonun başlangıcı gibi en yakın olanıdır. Çoğu durumda, bu satır diff parçasının bulunduğu işlevin adını içerir. Bu, diffdiff sürücüsüne ayarlı gitattribute ve xfuncnameyapılandırma değişkenini içeren diff sürücüsü ile yapılandırılabilir.
Jakub Narębski

1
@ AnthonyGeoghegan: satırlar silinebilir (daha sonra postimage'deki satır sayısı 0'dır) veya eklenebilir (sonra preimage'deki satır sayısı 0'dır).
Jakub Narębski

1
@KasunSiyambalapitiya: Git'in kullandığı birleşik fark biçimi (bağlam farkı formatı ^ [1] yerine), değiştirilen satır ile kaldırılan ve eklenen satır arasında ayrım yapmaz. [1]: gnu.org/software/diffutils/manual/html_node/Context-Format.html
Jakub Narębski

1
@ JakubNarębski: Satır sayısı varsayılan olarak 1 değil, 0'dır. Bu kadar basit. Uygulamada, görüntülenecek bağlam olmadığı için tek satırlı dosyalar için yalnızca "-1" ve / veya "+1" olarak görünür.
Guido Flohr

68

@@ -1,2 +3,4 @@ farkın bir parçası

Bu kısım anlaması biraz zaman aldı, bu yüzden minimal bir örnek oluşturdum.

Biçim temelde diff -ubirleştirilmiş fark ile aynıdır .

Örneğin:

diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')

Burada 2, 3, 14 ve 15. satırları kaldırdık. Çıktı:

@@ -1,6 +1,4 @@
 1
-2
-3
 4
 5
 6
@@ -11,6 +9,4 @@
 11
 12
 13
-14
-15
 16

@@ -1,6 +1,4 @@ anlamına geliyor:

  • -1,6Bu, ilk dosyanın bu parçasının 1. satırdan başladığını ve toplam 6 satırı gösterdiğini gösterir. Bu nedenle 1'den 6'ya kadar olan satırları gösterir.

    1
    2
    3
    4
    5
    6
    

    -"eski" anlamına gelir diff -u old new.

  • +1,4ikinci dosyanın bu parçasının 1. satırdan başladığı ve toplam 4 satır gösterdiği anlamına gelir. Bu nedenle 1'den 4'e kadar olan satırları gösterir.

    + "yeni" anlamına gelir.

    Biz 2 yerine 6 yerine 4 satır var! Yeni iri parça sadece:

    1
    4
    5
    6
    

@@ -11,6 +9,4 @@ ikinci iri parça benzer:

  • eski dosyada, eski dosyanın 11. satırından başlayarak 6 satırımız var:

    11
    12
    13
    14
    15
    16
    
  • yeni dosyada, yeni dosyanın 9. satırından başlayarak 4 satırımız var:

    11
    12
    13
    16
    

    Bir 11önceki parçadaki 2 satırı zaten kaldırdığımız için satırın yeni dosyanın 9. satırı olduğuna dikkat edin: 2 ve 3.

Yığın başlık

Git sürümünüze ve yapılandırmanıza bağlı olarak, satırın yanında bir kod satırı da alabilirsiniz @@, örneğin func1() {:

@@ -4,7 +4,6 @@ func1() {

Bu aynı zamanda -pova bayrağı ile de elde edilebilir diff.

Örnek: eski dosya:

func1() {
    1;
    2;
    3;
    4;
    5;
    6;
    7;
    8;
    9;
}

Çizgiyi kaldırırsak 6, fark şunu gösterir:

@@ -4,7 +4,6 @@ func1() {
     3;
     4;
     5;
-    6;
     7;
     8;
     9;

Bunun doğru satır olmadığını unutmayın func1: satırları atladı 1ve 2.

Bu harika özellik genellikle her bir iri parçanın hangi fonksiyona veya sınıfa ait olduğunu söyler, bu da farkın yorumlanması için çok yararlıdır.

Üstbilgi seçme algoritması tam olarak şu şekilde tartışılır: git diff iri başlığındaki alıntı nereden geliyor?


11
Bu hala tam olarak anlamayan herkes içindir. Gelen @@ -1,6 +1,4 @@pls okumaz -1olarak minus oneya +1kadar plus oneyerine bu okuma line 1 to 6eski (ilk) dosyasında. Burada - implies "old"eksi değil not edin. BTW, açıklama için teşekkürler ... haash.
dkjain

Bundan @@ -1,8 +1,9 @@ gerçekte ne olduğunu yorumlamak mümkün. örneğin 1) bir satır eklenmiştir 2) bir satır değiştirilmekte ve bir satır eklenmektedir vb. Ya da git diff correclty kodda hangi satırların değiştirildiğini tanımladığı için onları almanın bir yolu olması gerektiği için başka bir yoldan mı. Lütfen bunu
halletmem

Lütfen yukarıdaki cevabın yanlış ve çok yanıltıcı olduğunu unutmayın: "+1,4 bu parçanın ikinci dosyanın 1-4 satırına karşılık geldiğini söylüyor ". Bunun nedeni +1,4, koşullu olmayan bağlam satırlarına atıfta bulunabilmesidir. Aksine söylenen " +1,4" aslında demektir ki " vardır 4dosyanın işte sürüm 'olarak hatlar (yani bağlam hat) ". Anlamını anlamak önemlidir +, -ve <whitespace>bu hunks yorumlanması için geçerli olan bu çizgilerin başında. Daha görsel bir örnek: youtube.com/watch?v=1tqMjJeyKpw
Damilola Olowookere

23

İşte basit örnek.

diff --git a/file b/file 
index 10ff2df..84d4fa2 100644
--- a/file
+++ b/file
@@ -1,5 +1,5 @@
 line1
 line2
-this line will be deleted
 line4
 line5
+this line is added

İşte bir açıklama bu (detaylarını görmek burada ).

  • --git bir komut değildir, bunun anlamı diff'in git sürümüdür (unix değil)
  • a/ b/dizinler, gerçek değiller. aynı dosyayla uğraştığımızda sadece bir kolaylık (benim durumumda a / dizinde ve b / çalışma dizininde)
  • 10ff2df..84d4fa2 bu 2 dosyanın blob kimlikleri
  • 100644 "mod bitleri" dir, bunun normal bir dosya olduğunu gösterir (yürütülebilir değil ve sembolik bir bağlantı değildir)
  • --- a/file +++ b/fileeksi işaretleri a / versiyonundaki satırları gösterir ancak b / versiyonunda eksiktir; ve artı işaretleri, b'de eksik olan / ancak mevcut satırları gösterir (benim durumumda --- silinen satırlar anlamına gelir ve +++, b / 'de eklenen satırlar anlamına gelir ve bu, çalışma dizinindeki dosyadır)
  • @@ -1,5 +1,5 @@bunu anlamak için büyük bir dosya ile çalışmak daha iyidir; farklı yerlerde iki değişikliğiniz varsa iki giriş alırsınız @@ -1,5 +1,5 @@; Diyelim ki line1 ... line100 dosyanız var ve line10'u sildiniz ve yeni line100 ekleyiniz:
@@ -7,7 +7,6 @@ line6
 line7
 line8
 line9
-this line10 to be deleted
 line11
 line12
 line13
@@ -98,3 +97,4 @@ line97
 line98
 line99
 line100
+this is new line100

Teşekkürler. Msgstr "100644, bunun normal bir dosya olduğunu belirten mod bitleridir (yürütülebilir değil ve sembolik bir bağlantı değildir)". "Mod bitleri" Linux'ta mı yoksa sadece Git'te mi?
Tim

@Tim Git'e özgü değil. Sağ 3 basamak ( 644) sekizlik olarak okunmalıdır (değerler: sırasıyla 1, 2, 4 eXecute, Yazma ve Okuma izni) ve bu sırayla Sahip (Kullanıcı), sonra Grup, ardından Diğer izinlere karşılık gelir. Kısacası 644, eğer sembolik olarak yazılmışsa u=rw,og=r, bu herkes tarafından okunabilir ancak sadece sahibi tarafından yazılabilir anlamına gelir . Soldaki diğer rakamlar, bir sembolik bağlantı gibi diğer bilgileri kodlar, vb. Değerler github.com/git/git/blob/… olarak görülebilir , bu konumdaki ilk 1 "normal dosya" dır.
Patrick Mevzek

15

Varsayılan çıktı biçimi (başlangıçta diffdaha fazla bilgi aramak gibi bilinen bir programdan gelir ) “birleşik fark” olarak bilinir. Temel olarak 4 farklı tipte çizgi içerir:

  • tek bir boşlukla başlayan bağlam çizgileri,
  • eklenmiş bir satırı gösteren ve + ,
  • ile başlayan silme satırları - , ve
  • bunun hangi dosyadan bahsettiği gibi üst düzey şeyleri, fark oluşturmak için hangi seçeneklerin kullanıldığını, dosyanın izinlerini değiştirip değiştirmediğini vb.

Tam olarak neyi değiştirdiğinizi bildiğiniz bir dosyanın iki sürümü arasındaki farkları okumayı öneririm. Böylece gördüğünüzde neler olduğunu anlayacaksınız.


5
+1: Uygulama hakkındaki öneri çok iyi - muhtemelen saplantılı olarak okumaya çalışmaktan çok daha hızlı.
Cascabel

6

Mac bilgisayarımda:

info diffsonra seçin: Output formats-> Context-> Unified format-> Detailed Unified:

Ya da çevrimiçi insan aynı bölüme giden aynı yolu izleyerek gnu'ya bağlı kalır:

Dosya: diff.info, Düğüm: Ayrıntılı Birleştirilmiş, Sonraki: Birleştirilmiş Örnek, Yukarı: Birleştirilmiş Biçim

Birleşik Biçimin Ayrıntılı Açıklaması ......................................

Birleştirilmiş çıktı biçimi, aşağıdaki gibi görünen iki satırlı bir başlık ile başlar:

 --- FROM-FILE FROM-FILE-MODIFICATION-TIME
 +++ TO-FILE TO-FILE-MODIFICATION-TIME

Zaman damgası, tarihi, kesirli saniye içeren saati ve saat dilimini belirtmek için `` 2002-02-21 23: 30: 39.942229878 -0800 '' biçimine benzer.

Üstbilginin içeriğini `--label = LABEL 'seçeneğiyle değiştirebilirsiniz; bkz. * Not Alternatif İsimler ::.

Sonra bir ya da daha fazla farklılık yığını gelir; her parça, dosyaların farklı olduğu bir alanı gösterir. Birleştirilmiş biçim parçaları şu şekilde görünür:

 @@ FROM-FILE-RANGE TO-FILE-RANGE @@
  LINE-FROM-EITHER-FILE
  LINE-FROM-EITHER-FILE...

Her iki dosya için ortak olan satırlar boşluk karakteriyle başlar. İki dosya arasında gerçekten farklı olan çizgiler, sol yazdırma sütununda aşağıdaki gösterge karakterlerinden birine sahiptir:

`+ 'Buraya ilk dosyaya bir satır eklendi.

`` - İlk dosyadan burada bir satır kaldırıldı.


1
Git, 'XXX-FILE-MODIFICATION-TIME' parçasını yazdırmaz, çünkü sürüm kontrol sistemi için anlamlı değildir. Dosya sistemi zaman damgalarındaki dosyaları karşılaştırmak için "kötü adam" sürüm kontrolü olarak işlev görebilir.
Jakub Narębski

3

Sorununuzun hangi kısmının kafa karıştırıcı olduğunu düşündüğünüz açık değil: aslında fark veya ekstra başlık bilgisi git yazdırıyor. Her ihtimale karşı, başlığa hızlı bir genel bakış.

İlk satır şöyle bir şeydir diff --git a/path/to/file b/path/to/file- açıkçası sadece farkın bu bölümünün hangi dosya için olduğunu söylüyor. Eğer boolean yapılandırma değişkeni ayarlarsanız diff.mnemonic prefix, ave bbenzeri daha açıklayıcı mektuplar değiştirilecektir cve w(işlemek ve çalışma ağacı).

Sonra, "mod satırları" vardır - satırlar dosyanın içeriğini değiştirmeyi gerektirmeyen değişikliklerin açıklamasını verir. Buna yeni / silinmiş dosyalar, yeniden adlandırılan / kopyalanan dosyalar ve izin değişiklikleri dahildir.

Sonunda böyle bir çizgi var index 789bd4..0afb621 100644. Muhtemelen hiç umursamazsınız, ancak bu 6 haneli onaltılık sayılar, bu dosya için eski ve yeni lekelerin kısaltılmış SHA1 karmalarıdır (bir damla, bir dosyanın içeriği gibi ham verileri depolayan bir git nesnesidir). Ve elbette, 100644dosyanın modu - son üç basamak açıkça izinlerdir; ilk üçü fazladan dosya meta veri bilgisi verir ( bunu açıklayan SO yazısı ).

Bundan sonra, standart birleşik fark çıktısına (klasik gibi diff -U) devam edersiniz . İri parçalara ayrılır - iri parça, dosyanın değişiklikleri ve bağlamlarını içeren bir bölümüdür. Her iri parça bir çift öncesinde ---ve +++söz konusu dosyayı gösteren çizgiler, daha sonra gerçek fark üç her iki tarafında bağlam hatları (varsayılan) -ve +/ kaldırıldı ilave çizgileri gösteren çizgiler.


indexÇizgi için ++ . İle onaylandıgit hash-object ./file
İle
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.