Git diff z numerami linii (dziennik Git z numerami linii)

93

Kiedy wykonuję a git difflub a git log -p, w jaki sposób mogę uzyskać numery wierszy pliku źródłowego dołączone do danych wyjściowych?

Próbowałem to sprawdzić man git-diff | grep "line numbers"i spróbowałem googlować, ale szybko nic nie uzyskałem.

Drew LeSueur
źródło

Odpowiedzi:

92

Nie można uzyskać czytelnych dla człowieka numerów wierszy za pomocą git diff

Obecnie nie ma żadnych opcji wyświetlania numerów linii pionowo z boku git diff.

Format Unified-diff

Te informacje są jednak dostępne w (c) nagłówkach porcji dla każdej zmiany w różnicach, ale są one tylko w formacie unified-diff :

@@ -start,count +start,count @@

Oryginalny stan pliku jest reprezentowany za pomocą -, a nowy stan jest reprezentowany przez +(nie oznaczają one dodania i usunięcia w nagłówku porcji. startReprezentuje numer linii początkowej każdej wersji pliku i countreprezentuje liczbę zawartych linii począwszy od punktu początkowego.

Przykład

diff --git a/osx/.gitconfig b/osx/.gitconfig
index 4fd8f04..fcd220c 100644
--- a/osx/.gitconfig
+++ b/osx/.gitconfig
@@ -11,7 +11,7 @@ <== HERE!
 [color "branch"]
        upstream = cyan
 [color "diff"]
-       meta = yellow
+       meta = cyan
        plain = white dim
        old = red bold
        new = green bold

Nagłówek przystojniaka

@@ -11,7 +11,7 @@

mówi, że poprzednia wersja pliku zaczyna się w linii 11 i zawiera 7 linii:

11  [color "branch"]
12         upstream = cyan
13  [color "diff"]
14 -       meta = yellow
14 +       meta = cyan
15         plain = white dim
16         old = red bold
17         new = green bold

podczas gdy następna wersja pliku również zaczyna się w linii 11 i zawiera również 7 linii.

Format Unified-diff nie jest przeznaczony do spożycia przez ludzi

Jak zapewne możesz stwierdzić, format unified-diff nie ułatwia obliczania numerów linii (przynajmniej jeśli nie jesteś maszyną). Jeśli naprawdę chcesz odczytać numery wierszy, musisz użyć narzędzia do porównywania, które wyświetli je za Ciebie.

Dodatkowe czytanie

Khalid
źródło
4
Tutaj jest grep do wyodrębniania tylko numerów linii w zmodyfikowanych plikach, np. Do filtrowania raportu w stylu checkstylegit diff --unified=0 | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
Jakub Bochenski
1
@ Komentarz Jakuba Bocheńskiego całkiem ładnie rozwiązał mój problem.
0xbe5077ed
Jest to naprawdę przydatne tylko wtedy, gdy określisz --unified=0lub -U0.
krakaj
Właśnie skończyłem git diffn, zastępstwo (opakowanie), git diffktóre pokazuje numery linii i ma pełną kompatybilność ze wszystkimi zastosowaniami i opcjami git diff: stackoverflow.com/questions/24455377/ ...
Gabriel Staples
22

Oto dwa kolejne rozwiązania, rozwijające kod Andy'ego Talkowskiego.

Zwykły tekst:

  git diff | gawk 'match($0,"^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@",a){left=a[1];right=a[2];next};\
   /^(---|\+\+\+|[^-+ ])/{print;next};\
   {line=substr($0,2)};\
   /^-/{print "-" left++ ":" line;next};\
   /^[+]/{print "+" right++ ":" line;next};\
   {print "(" left++ "," right++ "):"line}'

Kolorowy tekst przy założeniu \033[66mformatu kodów kolorów:

  git diff --color=always | \
    gawk '{bare=$0;gsub("\033[[][0-9]*m","",bare)};\
      match(bare,"^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@",a){left=a[1];right=a[2];next};\
      bare ~ /^(---|\+\+\+|[^-+ ])/{print;next};\
      {line=gensub("^(\033[[][0-9]*m)?(.)","\\2\\1",1,$0)};\
      bare~/^-/{print "-"left++ ":" line;next};\
      bare~/^[+]/{print "+"right++ ":" line;next};\
      {print "("left++","right++"):"line;next}'

Kod zmienia wiersze zaczynające się odpowiednio od -i +do -1:-i +1:+oraz wiersze zaczynające się niczym do (5,6):. Liczby to numery wierszy z odpowiedniego pliku.

PFudd
źródło
Zauważam, że łamie wyrównanie (wcięcie) kodu, podczas gdy język natywny git diffstarannie zachowuje wyrównanie. W tej chwili mam nad głową ten kod, więc czy zechciałbyś go naprawić? Innymi słowy, gdy w jednej linii jest napisane, +240:+a w następnej (241,257):, musisz dodać dodatkowe spacje do górnej linii, aby kod zachował właściwe wyrównanie i wcięcia z kodem z dolnej linii. Może można to łatwo zrobić za pomocą druku?
Gabriel Staples
... mam na myśli z printf.
Gabriel Staples
Nieważne; Mam to! Właśnie skończyłem git diffn. Zobacz tutaj: stackoverflow.com/a/61997003/4561887 . Dzięki @PFudd za odpowiedź. Przestudiowałem go i użyłem do nauki, a potem zacząłem od zera i pisałem git diffn. Po sformatowaniu, aby móc odczytać Twój kod (dzięki @EdMorton), mogłem nauczyć się z niego wielu wspaniałych rzeczy, które mi pomogły.
Gabriel Staples
6

Oto skrypt, który próbuje to naprawić - nie testowałem go w gniewie, ale wydaje się w porządku. Opiera się na rekordach tworzonych przez git diff i używa awk do utrzymywania liczby linii.

# Massage the @@ counts so they are usable
function prep1() {
   cat | awk -F',' 'BEGIN { convert = 0; }
       /^@@ / { convert=1; }
       /^/  { if ( convert == 1 ) { print $1,$2,$3;
              } else { print $0;
              }
              convert=0;
             }'
}

# Extract all new changes added with the line count
function prep2() {
  cat | awk 'BEGIN { display=0; line=0; left=0; out=1;}
     /^@@ / { out=0; inc=0; line=$4; line--; display=line; left=line;        }
     /^[-]/   { left++; display=left; inc=0; }
     /^[+]/   { line++; display=line; inc=0; }
     /^[-+][-+][-+] / { out=0; inc=0; }
     /^/    { 
               line += inc;
               left += inc;
               display += inc;
               if ( out == 1 ) {
                   print display,$0;
               } else {
                   print $0;
               }
               out = 1;
               inc = 1;
               display = line;
            }'
} 

git diff $1 | prep1 | prep2 
Andy Talkowski
źródło
4

Możesz użyć git difftooldo zrobienia porównania za pomocą zewnętrznego edytora, który wyświetli numery linii. Oto jak to zrobić z vim / vimdiff:

  1. Ustaw vimdiff jako difftool gita:

    git config --global diff.tool vimdiff
    
  2. Skonfiguruj ~/.vimrcautomatyczne wyświetlanie numerów linii podczas korzystania z vimdiff:

    if &diff
        set number
    endif
    
  3. Uruchom git difftool, który użyje vimdiff z numerami linii:

    git difftool
    
wisbucky
źródło
Wykonując tylko git difftool, otworzyło mi się narzędzie tkdiff, które samo w sobie ma funkcję numeru linii. Dzięki wisbucky
Richardd
3

Szybkim sposobem jest użycie git diff -U0. Spowoduje to ustawienie linii kontekstu na 0, co spowoduje, że wartości @@ będą pasować do faktycznie zmienionych linii. Domyślnie wartości @@ obejmują 3 wiersze kontekstu przed / po, co nie jest wygodne dla ludzi.

Przykład:

git diff # default
@@ -10,8 +10,8 @@

Trudno jest obliczyć numery wierszy zmienionych wierszy, ponieważ wiersz 10 odnosi się do pierwszego wiersza poprzedniego kontekstu. Rzeczywisty numer linii pierwszej zmienionej linii to 10 + 3 = 13. Aby obliczyć liczbę zmienionych linii, musisz również odjąć kontekst przed i po: 8-3-3 = 2.

git diff -U0
@@ -13,2 +13,2 @@

Jak widać, ustawienie context = 0 sprawia, że ​​wartości @@ są łatwiejsze do odczytania dla ludzi. Możesz zobaczyć, że zmienione linie zaczynają się w linii 13 i są 2 zmienione linie.

To nie jest idealne, ponieważ pokazuje tylko numer linii dla każdego bloku. Jeśli chcesz zobaczyć numery linii dla każdej linii, użyj difftool dla zewnętrznego edytora. Zobacz https://stackoverflow.com/a/50049752

wisbucky
źródło
3

Lubię używać git difftoolz meldem jako moim difftool. Łatwiej jest na niego spojrzeć git diff, ma ładne porównanie GUI obok siebie i pokazuje numery linii po każdej stronie.

Ustawiać:

  1. Instrukcje, jak skonfigurować meld jako narzędzie difftool dla systemu Windows lub Linux

Przykładowy zrzut ekranu:

wprowadź opis obrazu tutaj

Aktualizacja z 24 maja 2020 r .:

Właśnie napisałem w git diffnciągu ostatnich kilku dni, aby zastąpić git diffgo w wierszu poleceń. Spróbuj. Zobacz moją drugą odpowiedź tutaj .

Gabriel Staples
źródło
3

Od 24 maja 2020 r. Możesz teraz używać w git diffntym celu narzędzia innej firmy (pełne ujawnienie: napisałem). Jest to lekkie opakowanie git diff, napisane w awkjęzyku programowania opartym na wzorcach / akcjach. Oto przykładowe dane wyjściowe z uruchomienia git diffn:

wprowadź opis obrazu tutaj

Oto demo:

1/3: Demo git diffn:

Utwórz ten plik:

hello_world.c:

#include <stdio.h>

int main()
{
    printf("Hello World\n");

    return 0;
}

Zatwierdź to:

git add hello_world.c
git commit -m "add hello_world.c"

Zmień to na to i zapisz plik:

hello_world.c:

// Basic hello world example

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello Gabriel\n");
    
    int i = 700;
    printf("i = %i\n", i);
    return 0;
}

Teraz biegnij:

git diff

Oto wynik działania git diff pierwszego dla celów porównawczych:

$ git diff
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+// Basic hello world example
+
 #include <stdio.h>
 
-int main()
+int main(int argc, char *argv[])
 {
-    printf("Hello World\n");
-
+    printf("Hello Gabriel\n");
+    
+    int i = 700;
+    printf("i = %i\n", i);
     return 0;
-}
\ No newline at end of file
+}

I zrzut ekranu pokazujący kolor. Zwróć uwagę, że sekcja podświetlona na czerwono pokazuje po prostu puste spacje (w tym przypadku spacje), które można usunąć:

wprowadź opis obrazu tutaj

Oto wynik działania git diffn . Zauważ, że pokazuje doskonale wszystkie numery linii!

  • Numery linii dla usuniętych linii znajdują się po lewej stronie i pokazują- znak zarówno po lewej, jak i po prawej stronie, :aby pomóc ci lepiej widzieć - niezależnie od tego, czy twoje oczy lubią skanować w dół na prawo od okrężnicy, czy w dół po drugiej stronie po lewej stronie ekranu.
  • Numery wierszy dla dodanych wierszy są dalej w prawo i pokazują+ znak zarówno po lewej, jak i po prawej stronie :.
  • Numery wierszy dla niezmienionych wierszy pokazanych dla kontekstu są wyświetlane zarówno dla lewego (stary plik), jak i dla prawej (nowy plik), oddzielonych znakiem, .

Wyjście git diffn:

$ git diffn
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+        1:+// Basic hello world example
+        2:+
    1,   3: #include <stdio.h>
    2,   4: 
-   3     :-int main()
+        5:+int main(int argc, char *argv[])
    4,   6: {
-   5     :-    printf("Hello World\n");
-   6     :-
+        7:+    printf("Hello Gabriel\n");
+        8:+    
+        9:+    int i = 700;
+       10:+    printf("i = %i\n", i);
    7,  11:     return 0;
-   8     :-}
\ No newline at end of file
+       12:+}

I zrzut ekranu pokazujący kolor. Zwróć uwagę, że dwukropki NIE są kolorowane ani stylizowane tak, aby pasowały do ​​otaczającego tekstu po lewej i prawej stronie. Jest to celowe i zaprojektowane zachowanie działające jako wizualny separator między numerami linii dodanymi po lewej stronie a oryginalnym git diffwyjściem po prawej stronie.

wprowadź opis obrazu tutaj

2/3: Co to jest?

Od górygit-diffn.sh :

OPIS:

git-diffn.sh

  1. zamiennik typu drop-in, dla git diffktórego jest również wyświetlany numer linii! Używaj go dokładnie tak git diff, jak , z tą różnicą, że zobaczysz również te piękne numery wierszy, które pomogą Ci zrozumieć wprowadzone zmiany.

  2. ponieważ jest to tylko lekkie opakowanie oparte na języku awk git diff, przyjmuje WSZYSTKIE akceptowane opcje i parametry git diff. Przykłady:

  3. git diffn HEAD~

  4. git diffn HEAD~3..HEAD~2

  5. działa z dowolnymi git diffustawieniami kolorów, nawet jeśli używasz kolorów niestandardowych

  6. Zobacz moją odpowiedź tutaj, aby dowiedzieć się, jak ustawić niestandardowe kolory różnic, a także zobaczyć zrzut ekranu wyjściowego koloru niestandardowego z git diffn: Jak dostosować kolor nagłówka diff w git diff?

  7. Oto kilka przykładowych git configpoleceń z mojej odpowiedzi powyżej, aby ustawić niestandardowe git diffkolory i atrybuty (formatowanie tekstu):

       git config --global color.diff.meta "blue"
       git config --global color.diff.old "black red strike"
       git config --global color.diff.new "black green italic"
       git config --global color.diff.context "yellow bold"
    
  8. in git diffn, wyjście kolorowe jest domyślnie WŁĄCZONE; jeśli chcesz wyłączyć kolor wyjściowy, musisz użyć --no-colorlub --color=never. Zobacz man git diffszczegóły. Przykłady:

     git diffn --color=never HEAD~
     git diffn --no-color HEAD~3..HEAD~2
    

3/3: Instalacja

  1. Windows (nieprzetestowane): to może działać wewnątrz terminala bash dostarczanego z Git dla Windows , ale nie zostało przetestowane. Zainstaluj Git dla Windows. Otwórz terminal bash, z którym jest dostarczany, i spróbuj wykonać poniższe instrukcje. Potrzebuję kilku testerów, którzy przetestują to w Git dla Windows. Zobacz i odpowiedz tutaj: https://github.com/git-for-windows/git/issues/2635 .
  2. Mac (nieprzetestowane): użyj terminala i postępuj zgodnie z poniższymi instrukcjami. Może być konieczne zainstalowanie gawk. Jeśli tak, spróbuj tego : brew install gawk.
  3. Linux (testowany na Ubuntu 18.04 i działa idealnie): postępuj zgodnie z instrukcjami terminala poniżej.

Opcja 1 (moja rekomendacja): pobierz całe repozytorium, a następnie utwórz link symboliczny do programu, abyś mógł łatwo otrzymywać aktualizacje, wykonując git pullrepozytorium w dowolnym momencie.

Po pierwsze, cdgdziekolwiek chcesz to zainstalować. Następnie uruchomić:

git clone https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.git
cd eRCaGuy_dotfiles/useful_scripts
mkdir -p ~/bin
ln -si "${PWD}/git-diffn.sh" ~/bin/git-diffn

Gotowe! Teraz wykonaj ostatni krok poniżej!

Opcja 2 (dla tych, którzy chcą tylko jednego pliku): pobierz tylko jeden plik jeden raz.

mkdir -p ~/bin
cd ~/bin
wget https://raw.githubusercontent.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/master/useful_scripts/git-diffn.sh
chmod +x git-diffn.sh
mv git-diffn.sh git-diffn

Gotowe! Teraz wykonaj ostatni krok poniżej!

Ostatni krok:

Teraz zamknij i ponownie otwórz swój terminal lub przeprowadź go ponownie za pomocą . ~/.bashrci gotowe!

git diffnbędzie teraz działać jako dokładny zamiennik git diff!

Gabriel Staples
źródło
1

Możesz spróbować

git blame

w pliku. Pokazuje ci committer, identyfikator zatwierdzenia i numer linii dla każdej linii w pliku.

Juan
źródło
4
Problem polega na tym, że nie pokazuje różnicy , o co prosił oryginalny plakat. git blamepokaże tylko aktualny stan pliku z numerami linii.
5
Wiedziałem o git winy, ale ktoś googlujący mógł tego nie mieć. To mogłoby komuś pomóc. Dzięki za odpowiedź.
Drew LeSueur
git blamew żaden sposób nie odpowiada na pytanie; Jestem dość zdumiony głosami uprzywilejowanymi tutaj
Michael Mrozek
Nie spamuj przepełnienia stosu odpowiedziami, które nie są związane z pytaniami.
Ahmed
0

Najpierw skonfiguruj narzędzie do porównywania git, np. Meld

git config --global diff.tool meld

Następnie wyciągnij difftool na jakiś plik:

git difftool -y config.rb

Zapamiętaj ustawienie numeru linii w preferencjach narzędzia porównywania.

HaxtraZ
źródło