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.

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


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.


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 

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
    

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


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 .


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!


1

Możesz spróbować

git blame

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


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.