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.
materiały pokrewne
Gałąź Git
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.