Close

git diff


Wykaz różnic (diff) to funkcja, która pobiera dwa zestawy danych wejściowych i wyświetla różnice między nimi. Git diff to wielofunkcyjne polecenie systemu Git uruchamiające funkcję diff względem źródeł danych Git. Mogą nimi być commity, gałęzie, pliki itd. W artykule omawiamy typowe zastosowania git diff i tworzenie wykazów różnic między wzorami przepływów pracy. Polecenie git diff często używa się wraz z git status i git log do analizy bieżącego stanu repozytorium Git.

Odczyt wykazów różnic: dane wyjściowe


Nieprzetworzony format wyjściowy

Poniższe przykłady zostaną wykonane na prostym repozytorium. Repozytorium zostaje utworzone za pomocą następujących poleceń:

$:> mkdir diff_test_repo
$:> cd diff_test_repo
$:> touch diff_test.txt
$:> echo "this is a git diff test example" > diff_test.txt
$:> git init .
Initialized empty Git repository in /Users/kev/code/test/.git/
$:> git add diff_test.txt
$:> git commit -am"add diff test file"
[main (root-commit) 6f77fc3] add diff test file
1 file changed, 1 insertion(+)
create mode 100644 diff_test.txt

Jeśli w tym momencie wykonamy polecenie git diff, nie otrzymamy danych wyjściowych. To spodziewane zachowanie, ponieważ zmiany nie zostały jeszcze wprowadzone do repozotyrium. Po utworzeniu repozytorium i dodaniu pliku diff_test.txt możemy zmienić zawartość pliku, aby rozpocząć eksperymenty z wynikami funkcji diff.

Gałąź Git
materiały pokrewne

Gałąź Git

Logo Bitbucket
POZNAJ ROZWIĄZANIE

Poznaj środowisko Git z rozwiązaniem Bitbucket Cloud

$:> echo "this is a diff example" > diff_test.txt

Wykonanie tego polecenia spowoduje zmianę zawartości pliku diff_test.txt. Gdy to nastąpi, możemy wyświetlić wykaz różnic i przeanalizować wynik. Teraz wynikiem wykonania polecenia git diff będą następujące dane wyjściowe:

diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Przyjrzyjmy się dokładniej strukturze danych wykazu różnic.

1. Dane wejściowe porównania

diff --git a/diff_test.txt b/diff_test.txt

Ten wiersz zawiera źródła wejściowe wykazu różnic. Widzimy, że do polecenia zostały przekazane pliki a/diff_test.txt i b/diff_test.txt.

2. Metadane

index 6b0c6cf..b37e70a 100644

Ten wiersz zawiera wewnętrzne metadane Git. Najprawdopodobniej nie będziemy potrzebować tych informacji. Liczby w tym wierszu odpowiadają hashom wersji obiektów Git.

3. Znaczniki zmian

--- a/diff_test.txt
+++ b/diff_test.txt

Te wiersze stanowią legendę symboli przypisanych do każdego źródła wejściowego wykazu. W tym przypadku zmiany z pliku a/diff_test.txt zostały oznaczone symbolem ---, natomiast zmiany z pliku b/diff_test.txt symbolem +++.

4. Elementy wykazu

Pozostałą treść stanowi lista elementów wykazu różnic. Obejmuje on wyłącznie sekcje pliku zawierające zmiany. Widzimy tylko jeden element, ponieważ to dość prosty przykład. Elementy charakteryzują się specyficzną semantyką danych wyjściowych.

@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Pierwszy wiersz to nagłówek fragmentu. Każdy fragment jest poprzedzony nagłówkiem zawartym między symbolami @@. Zawartość nagłówka jest podsumowaniem zmian wprowadzonych w pliku. W naszym uproszczonym przykładzie widzimy „-1 +1”, co oznacza, że zmiany wprowadzono w pierwszym wierszu. W przypadku rzeczywistego wykazu nagłówek będzie wyglądał w ten sposób:

@@ -34,6 +34,8 @@

W powyższym przykładzie zostało wyodrębnionych 6 wierszy, zaczynając od wiersza nr 34. Dodatkowo dodano 8 wierszy, zaczynając od wiersza nr 34.

Pozostałą treść elementu wykazu stanowią ostatnie zmiany. Każdy zmieniony wiersz jest poprzedzony symbolem + lub - wskazującym, z którego pliku źródłowego pochodzą zmiany. Jak wspomnieliśmy wcześniej, - oznacza zmiany z pliku a/diff_test.txt, a + oznacza zmiany z pliku b/diff_test.txt.

Wyróżnianie zmian


1. git diff --color-words

Polecenie git diff obejmuje również specjalny tryb bardziej szczegółowego wyróżniania zmian: ‐‐color-words. Dodane i usunięte wiersze oznaczane są znakami odstępu, a następnie uwzględniane do utworzenia wykazu zmian.

$:> git diff --color-words
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
this is agit difftest example

Teraz wyświetlone zostają wyłącznie oznaczone kolorami zwroty, które uległy zmianie.

2. git diff-highlight

Gdy sklonujemy źródło git, otrzymamy podkatalog o nazwie contrib. Zawiera on kilka narzędzi systemowych oraz inne interesujące elementy jeszcze niewłączone do trzonu systemu Git. Jednym z nich jest skrypt Perl o nazwie diff-highlight. Diff-highlight zestawia pasujące wiersze wykazu różnic i wyróżnia fragmenty zmienionych podsłów.

$:> git diff | /your/local/path/to/git-core/contrib/diff-highlight/diff-highlight
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

W ten sposób ograniczamy wykaz do możliwie najmniejszego zakresu zmian.

Tworzenie wykazu różnic dla plików binarnych


Oprócz przedstawionych dotychczas narzędzi do obsługi plików tekstowych polecenie git diff można również zastosować do plików binarnych. Niestety domyślne dane wyjściowe nie są zbyt pomocne.

$:> git diff
Binary files a/script.pdf and b/script.pdf differ

System Git umożliwia określenie polecenia powłoki, które przekształci zawartość plików binarnych w tekst przed utworzeniem wykazu różnic. Wymaga to jednak wprowadzenia drobnych zmian konfiguracyjnych. Po pierwsze należy określić filtr textconv opisujący sposób konwersji określonego typu plików binarnych na tekst. My używamy prostego narzędzia pdftohtml (dostępnego za pośrednictwem homebrew) do konwersji plików PDF na czytelny dla człowieka kod HTML. Można to ustawić dla pojedynczego repozytorium przez edycję pliku .git/config lub globalnie przez edycję ~ /.gitconfig.

[diff "pdfconv"]
textconv=pdftohtml -stdout

Następnie wystarczy powiązać jeden lub więcej wzorców plików z naszym filtrem pdfconv. Możemy to zrobić przez utworzenie pliku .gitattributes w katalogu głównym repozytorium.

*.pdf diff=pdfconv

Gdy będą wprowadzone odpowiednie zmiany konfiguracji, git diff najpierw uruchomi plik binarny za pośrednictwem skonfigurowanego skryptu konwertera, a następnie wyświetli wykaz zmian w danych wyjściowych konwertera. Tę samą technikę można zastosować do wydobycia użytecznych różnic ze wszelkiego rodzaju plików binarnych, np. plików .zip, .jar i innych archiwów. Użycie polecenia unzip -l (lub podobnego) zamiast pdf2html spowoduje wyświetlenie ścieżek, które zostały dodane lub usunięte między commitami. Exiv2 można użyć do wykazania zmian w metadanych takich jak wymiary obrazów. Istnieją też narzędzia do konwersji plików .odf, .doc i innych formatów dokumentów na zwykły tekst. W przypadku plików binarnych nieobsługiwanych przez formalny konwerter często sprawdzają się ciągi znaków.

Porównywanie plików: git diff file


W ramach git diff można też użyć opcji jawnej ścieżki pliku. W wyniku przekazania ścieżki pliku do git diff działanie polecenia zostaje ograniczone do określonego pliku. Na poniższych przykładach możemy zobaczyć to zastosowanie.

git diff HEAD ./path/to/file

W tym przykładzie zakres działania zostaje ograniczony do ./path/to/file. Po wywołaniu funkcja dokonuje porównania konkretnych zmian w katalogu roboczym względem indeksu, wykazując te jeszcze nieprzeniesione do przechowalni. Domyślnie git diff przeprowadzi porównanie względem HEAD. Pominięcie HEAD w powyższym przykładzie git diff ./path/to/file da ten sam efekt.

git diff --cached ./path/to/file

Jeśli polecenie git diff zostaje wywołane z opcją --cached, wówczas porównuje zmiany w przechowalni z repozytorium lokalnym. Opcja --cached odpowiada opcji --staged.

Porównywanie wszystkich zmian


Wywołanie git diff bez ścieżki pliku spowoduje porównanie zmian w całym repozytorium. Powyższe przykłady dotyczące poszczególnych plików można wykonać bez argumentu ./path/to/file i uzyskać takie same wyniki dla wszystkich plików w lokalnym repozytorium.

Zmiany od ostatniego commitu


Domyślnie git diff wykazuje wszystkie niezatwierdzone zmiany od ostatniego commitu.

git diff

Porównywanie plików między dwoma commitami


Do polecenia git diff można przekazać odniesienia Git do commitów. Przykładowe odniesienia to wskaźnik HEAD, tagi czy nazwy gałęzi. Każdy commit w Git ma identyfikator, który można uzyskać za pomocą GIT LOG. Identyfikator commitu można również przekazać do polecenia git diff.

git log --pretty=oneline
957fbc92b123030c389bf8b4b874522bdf2db72c add feature
ce489262a1ee34340440e55a0b99ea6918e19e7a rename some classes
6b539f280d8b0ec4874671bae9c6bed80b788006 refactor some code for feature
646e7863348a427e1ed9163a9a96fa759112f102 add some copy to body

$:> git diff 957fbc92b123030c389bf8b4b874522bdf2db72c ce489262a1ee34340440e55a0b99ea6918e19e7a

Porównywanie gałęzi


Porównywanie dwóch gałęzi

Porównanie gałęzi wygląda dokładnie tak samo jak w przypadku innych danych wejściowych polecenia git diff.

git diff branch1..other-feature-branch

W tym przykładzie zostaje wprowadzony operator w postaci kropek. Dwie kropki oznaczają, że danymi wejściowymi polecenia diff są końcówki obu gałęzi. Ten sam efekt nastąpi, jeśli pominiemy kropki i zastosujemy spację między gałęziami. Dodatkowo istnieje operator w postaci trzech kropek:

git diff branch1...other-feature-branch

Trzy kropki wywołują wykaz różnic przez zmianę pierwszego parametru wejściowego branch1. Następuje zmiana branch1 w odniesienie do commitu współdzielonego elementu nadrzędnego między dwiema danymi wejściowymi wykazu — wspólnego elementu nadrzędnego branch1 oraz gałęzi other-feature-branch. Ostatni parametr wejściowy pozostaje niezmieniony jako końcówka gałęzi other-feature-branch.

Porównywanie plików z dwóch gałęzi


Aby porównać konkretny plik między gałęziami, należy przekazać ścieżkę pliku jako trzeci argument do git diff.

git diff main new_branch ./diff_test.txt

Podsumowanie


Omówiliśmy proces wykazywania różnic i polecenie git diff. Przedstawiliśmy sposób odczytywania danych wyjściowych polecenia git diff i poszczególne informacje w nich zawarte. Podane przykłady pokazały, jak zmienić dane wyjściowe git diff za pomocą wyróżniania i kolorów. Omówiliśmy różne strategie wykazywania zmian, np. jak wykazać różnice między plikami w gałęziach i poszczególnymi commitami. Oprócz polecenia git diff korzystaliśmy również z git log i git checkout.


Udostępnij ten artykuł
Następny temat

Zalecane lektury

Dodaj te zasoby do zakładek, aby dowiedzieć się więcej na temat rodzajów zespołów DevOps lub otrzymywać aktualności na temat metodyki DevOps w Atlassian.

Ludzie współpracujący przy ścianie pełnej narzędzi

Blog Bitbucket

Ilustracja DevOps

Ścieżka szkoleniowa DevOps

Demonstracje funkcji z ekspertami Atlassian

Zobacz, jak Bitbucket Cloud współpracuje z Atlassian Open DevOps

Zapisz się do newslettera DevOps

Thank you for signing up