Strona podręcznika dla użytkownika git-diff
jest dość długa i wyjaśnia wiele przypadków, które nie wydają się konieczne dla początkującego. Na przykład:
git diff origin/master
Strona podręcznika dla użytkownika git-diff
jest dość długa i wyjaśnia wiele przypadków, które nie wydają się konieczne dla początkującego. Na przykład:
git diff origin/master
Odpowiedzi:
Spójrzmy na przykład zaawansowanego porównania z historią git (w zatwierdzeniu 1088261f w repozytorium git.git ):
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] == '-') {
Przeanalizujmy tę łatkę linia po linii.
Pierwsza linia
diff --git a / builtin-http-fetch.cb / http-fetch.cjest nagłówkiem „git diff” w formularzu
diff --git a/file1 b/file2
. Nazwy plików a/
i b/
są takie same, chyba że w grę wchodzi zmiana nazwy / kopii (jak w naszym przypadku). --git
To oznaczać, że edycja jest w „git” formacie diff.Dalej jest jedna lub więcej rozszerzonych linii nagłówka. Pierwsze trzy
wskaźnik podobieństwa 95% zmień nazwę z wbudowanego-http-fetch.c zmień nazwę na http-fetch.cpowiedz nam, że nazwa pliku została zmieniona z
builtin-http-fetch.c
na http-fetch.c
i że te dwa pliki są w 95% identyczne (co zostało użyte do wykrycia tej zmiany). indeks f3e63d7..e8f44ba 100644powiedz nam o trybie danego pliku (
100644
oznacza, że jest to zwykły plik, a nie np. dowiązanie symboliczne i że nie ma wykonywalnego bitu uprawnień), a także o skróconym skrócie preimage (wersja pliku przed daną zmianą) i postimage ( wersja pliku po zmianie). Ten wiersz jest używany przez git am --3way
próbę wykonania 3-kierunkowego scalenia, jeśli łata nie może być zastosowana sama.Dalej jest dwuwierszowy zunifikowany nagłówek diff
--- a / builtin-http-fetch.c +++ b / http-fetch.cW porównaniu do
diff -U
wyniku nie ma on nazw plików od modyfikacji pliku ani czasu modyfikacji pliku po źródłowym (wstępnym obrazie) i docelowym (postimage) nazwach plików. Jeśli plik został utworzony, źródłem jest /dev/null
; jeśli plik został usunięty, celem jest /dev/null
. diff.mnemonicPrefix
konfiguracji zmiennej true, w miejscu a/
i b/
przedrostków w tym dwulinijkowego nagłówka można mieć zamiast c/
, i/
, w/
i o/
jako przedrostków, odpowiednio do czego porównać; patrz git-config (1)Następnie przychodzi jeden lub więcej kawałków różnic; każdy przystojniak pokazuje jeden obszar, w którym różnią się pliki. Kawałki ujednoliconego formatu zaczynają się od linii
@@ -1,8 +1,9 @@lub
@@ -18,6 +19,8 @@ int cmd_http_fetch (int argc, const char ** argv, ...Jest w formacie
@@ from-file-range to-file-range @@ [header]
. Zakres od pliku ma postać -<start line>,<number of lines>
, a zakres od pliku jest +<start line>,<number of lines>
. Zarówno linia początkowa, jak i liczba linii odnoszą się odpowiednio do pozycji i długości przystawki w przedobrazie i po obrazie. Jeśli liczba linii nie jest pokazana, oznacza to, że jest to 0.
Opcjonalny nagłówek pokazuje funkcję C, w której występuje każda zmiana, jeśli jest to plik C (jak -p
opcja w GNU diff) lub równoważny, jeśli taki istnieje, dla innych typów plików.
Następnie znajduje się opis różnic między plikami. Linie wspólne dla obu plików rozpoczynają się znakiem spacji. Linie, które faktycznie różnią się między dwoma plikami, mają jeden z następujących znaków wskaźnikowych w lewej kolumnie wydruku:
Na przykład pierwsza porcja
#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;
oznacza, że cmd_http_fetch
został zastąpiony przez main
i ta const char *prefix;
linia została dodana.
Innymi słowy, przed zmianą odpowiedni fragment pliku „builtin-http-fetch.c” wyglądał następująco:
#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;
Po zmianie ten fragment pliku „http-fetch.c” wygląda następująco:
#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;
Może tam być
\ Brak nowego wiersza na końcu plikulinia obecna (nie ma w tym przykładzie różnicy).
Jak powiedział Donal Fellows , najlepiej ćwiczyć czytanie różnic na prawdziwych przykładach, gdzie wiesz, co zmieniłeś.
Bibliografia:
git blame -C -C
, tak to działa; to decyzja projektowa Git. Format git diff pokazuje tylko indeks podobieństwa (lub podobieństwa) do użytkownika.
[header]
jest najbliższym poprzedzeniem, takim jak początek funkcji, która poprzedza przystojniak. W większości przypadków ten wiersz zawiera nazwę funkcji, w której znajduje się fragment różnicy. Jest to konfigurowalne z diff
gitattribute ustawionym na sterownik diff i sterownik diff zawierający xfuncname
zmienną konfiguracyjną.
@@ -1,2 +3,4 @@
część różnicy
Ta część zajęła mi trochę czasu, aby zrozumieć, więc stworzyłem minimalny przykład.
Format jest w zasadzie taki sam jak diff -u
zunifikowany plik różnic.
Na przykład:
diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')
Tutaj usunęliśmy wiersze 2, 3, 14 i 15. Dane wyjściowe:
@@ -1,6 +1,4 @@
1
-2
-3
4
5
6
@@ -11,6 +9,4 @@
11
12
13
-14
-15
16
@@ -1,6 +1,4 @@
znaczy:
-1,6
oznacza, że ten fragment pierwszego pliku zaczyna się od linii 1 i pokazuje w sumie 6 linii. Dlatego pokazuje linie od 1 do 6.
1
2
3
4
5
6
-
oznacza „stary”, jak zwykle przywołujemy go jako diff -u old new
.
+1,4
oznacza, że ten fragment drugiego pliku zaczyna się od linii 1 i pokazuje w sumie 4 linie. Dlatego pokazuje linie od 1 do 4.
+
oznacza „nowy”.
Mamy tylko 4 linie zamiast 6, ponieważ 2 linie zostały usunięte! Nowy przystojniak to po prostu:
1
4
5
6
@@ -11,6 +9,4 @@
dla drugiego przystojniaka jest analogiczne:
na starym pliku mamy 6 linii, zaczynając od linii 11 starego pliku:
11
12
13
14
15
16
w nowym pliku mamy 4 linie, zaczynając od linii 9 nowego pliku:
11
12
13
16
Zauważ, że linia 11
jest 9 linią nowego pliku, ponieważ już usunęliśmy 2 linie z poprzedniego przystanku: 2 i 3.
Hunk nagłówek
W zależności od wersji git i konfiguracji możesz także uzyskać wiersz kodu obok @@
wiersza, np. func1() {
W:
@@ -4,7 +4,6 @@ func1() {
Można to również uzyskać -p
flagą równiny diff
.
Przykład: stary plik:
func1() {
1;
2;
3;
4;
5;
6;
7;
8;
9;
}
Jeśli usuniemy linię 6
, diff pokaże:
@@ -4,7 +4,6 @@ func1() {
3;
4;
5;
- 6;
7;
8;
9;
Zauważ, że nie jest to poprawna linia dla func1
: pominęła linie 1
i 2
.
Ta niesamowita funkcja często mówi dokładnie, do której funkcji lub klasy należy każdy przystojniak, co jest bardzo przydatne do interpretacji różnic.
Jak dokładnie działa algorytm wyboru nagłówka, omówiono na stronie: Skąd pochodzi fragment nagłówka przystawki git diff?
@@ -1,6 +1,4 @@
PLS nie czytaj -1
jako minus one
lub +1
jako plus one
zamiast tego czytaj tak jak line 1 to 6
w starym (pierwszym) pliku. Uwaga tutaj - implies "old"
nie minus. BTW, dzięki za wyjaśnienie ... haash.
+1,4
mówi, że ten fragment odpowiada wierszom od 1 do 4 drugiego pliku ”. Wynika to z faktu, że +1,4
mogą odnosić się do niepowiązanych linii kontekstowych. Raczej to, co w +1,4
rzeczywistości oznacza „ ”, to że „ w tej„ wersji ”pliku są 4
wiersze (tj. Linie kontekstu) . Ważne jest, aby zrozumieć sens +
, -
i <whitespace>
na początku tych linii, ponieważ odnosi się do interpretacji porcji. Bardziej wizualny przykład: youtube.com/watch?v=1tqMjJeyKpw
Oto prosty przykład.
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
Oto wyjaśnienie (zobacz szczegóły tutaj ).
--git
nie jest poleceniem, oznacza to, że jest to wersja git diff (nie unix)a/ b/
są katalogami, nie są prawdziwe. to tylko wygoda, gdy mamy do czynienia z tym samym plikiem (w moim przypadku a / jest w indeksie, a b / jest w katalogu roboczym)10ff2df..84d4fa2
są identyfikatorami obiektów blob tych 2 plików100644
to „bity trybu”, wskazujące, że jest to zwykły plik (niewykonywalny i nie dowiązanie symboliczne)--- a/file +++ b/file
znaki minus pokazują linie w wersji a /, ale brakuje ich w wersji b /; a znaki plus pokazują brakujące linie w /, ale obecne w b / (w moim przypadku --- oznacza usunięte linie, a +++ oznacza dodane linie wb / i ten plik w katalogu roboczym)@@ -1,5 +1,5 @@
aby to zrozumieć, lepiej pracować z dużym plikiem; jeśli masz dwie zmiany w różnych miejscach, otrzymasz dwa wpisy, takie jak @@ -1,5 +1,5 @@
; załóżmy, że masz plik linia 1 ... linia 100 i usunięty wiersz 10 i dodajesz nową linię 100 - otrzymasz:@@ -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
644
) należy odczytywać ósemkowo (wartości: odpowiednio 1, 2, 4 eXecute, uprawnienie Write i Read) i odpowiada w tej kolejności właścicielowi (użytkownikowi), następnie grupie, a następnie innym uprawnieniom. Krótko mówiąc, 644
oznaczałoby to, jeśli napisane symbolicznie u=rw,og=r
, jest czytelne dla wszystkich, ale zapisywane tylko przez właściciela. Pozostałe cyfry po lewej kodują inne informacje, np. Jeśli jest to dowiązanie symboliczne itp. Wartości można zobaczyć github.com/git/git/blob/... , pierwsza 1 w tej pozycji to „zwykły plik”.
Domyślny format wyjściowy (który pierwotnie pochodzi z programu znanego tak diff
, jakbyś chciał poszukać więcej informacji) jest znany jako „zunifikowany plik różnicowy”. Zawiera zasadniczo 4 różne rodzaje linii:
+
,-
, iRadzę ćwiczyć czytanie różnic między dwiema wersjami pliku, w których dokładnie wiesz, co zmieniłeś. W ten sposób rozpoznasz, co się dzieje, kiedy to zobaczysz.
Na moim komputerze Mac:
info diff
następnie wybierz: Output formats
-> Context
-> Unified format
-> Detailed Unified
:
Lub online man diff na GNU, podążając tą samą ścieżką do tej samej sekcji:
Plik: diff.info, węzeł: szczegółowy ujednolicony, następny: przykład ujednolicony, w górę: ujednolicony format
Szczegółowy opis ujednoliconego formatu ......................................
Ujednolicony format wyjściowy zaczyna się od dwuwierszowego nagłówka, który wygląda następująco:
--- FROM-FILE FROM-FILE-MODIFICATION-TIME +++ TO-FILE TO-FILE-MODIFICATION-TIME
Znacznik czasu wygląda jak „2002-02-21 23: 30: 39.942229878 -0800”, aby wskazać datę, godzinę z ułamkami sekund i strefę czasową.
Możesz zmienić treść nagłówka za pomocą opcji `--label = LABEL '; patrz * Uwaga Alternatywne nazwy ::.
Następnie przychodzi jeden lub więcej kawałków różnic; każdy przystojniak pokazuje jeden obszar, w którym różnią się pliki. Kawałki ujednoliconego formatu wyglądają tak:
@@ FROM-FILE-RANGE TO-FILE-RANGE @@ LINE-FROM-EITHER-FILE LINE-FROM-EITHER-FILE...
Linie wspólne dla obu plików rozpoczynają się znakiem spacji. Linie, które faktycznie różnią się między dwoma plikami, mają jeden z następujących znaków wskaźnikowych w lewej kolumnie wydruku:
`+ 'Tutaj dodano linię do pierwszego pliku.
`- 'Linia została tutaj usunięta z pierwszego pliku.
Z twojego pytania nie jest jasne, która część różnic jest dla Ciebie myląca: tak naprawdę różnica lub dodatkowe informacje nagłówka drukowane przez git. Na wszelki wypadek oto krótki przegląd nagłówka.
Pierwszy wiersz jest coś w stylu diff --git a/path/to/file b/path/to/file
- oczywiście mówi tylko, dla którego pliku przeznaczona jest ta sekcja diff. Jeśli ustawisz zmienną logiczną config diff.mnemonic prefix
The a
a b
zostanie zmieniony na bardziej opisowych liter jak c
i w
(commit i drzewa pracy).
Następnie są „wiersze trybu” - wiersze opisujące wszelkie zmiany, które nie wymagają zmiany zawartości pliku. Dotyczy to nowych / usuniętych plików, plików o zmienionych nazwach / skopiowanych oraz zmian uprawnień.
Wreszcie jest taka linia index 789bd4..0afb621 100644
. Prawdopodobnie nigdy nie będziesz się tym przejmować, ale te 6-cyfrowe liczby szesnastkowe to skróty skrótów SHA1 starych i nowych obiektów blob dla tego pliku (obiekt blob to obiekt git przechowujący surowe dane, takie jak zawartość pliku). I oczywiście 100644
jest to tryb pliku - ostatnie trzy cyfry to oczywiście uprawnienia; pierwsze trzy zawierają dodatkowe informacje o metadanych pliku ( opis SO opisujący to ).
Następnie przejdziesz do standardowego zunifikowanego wyjścia różnicowego (podobnie jak klasyczny diff -U
). Podzielony jest na porcje - porcja to sekcja pliku zawierająca zmiany i ich kontekst. Każdy przystojniak jest poprzedzony parą linii ---
i +++
oznaczających dany plik, a następnie rzeczywistą różnicą są (domyślnie) trzy linie kontekstu po obu stronach linii -
i +
linie pokazujące usunięte / dodane linie.
index
linii. Potwierdzonygit hash-object ./file