Close

git diff


Diffing is een functie die twee gegevenssets als input accepteert en als output de wijzigingen ertussen weergeeft. git diff is een Git-opdracht voor meerdere doeleinden die een diff-functie uitvoert op Git-gegevensbronnen. Deze gegevensbronnen kunnen commits, branches, bestanden en meer zijn. In dit document worden veelvoorkomend gebruik van git diff en verschillende workflowpatronen besproken. De opdracht git diff wordt vaak gebruikt in combinatie met git status en git log om de huidige status van een Git-repo te analyseren.

Diffs lezen: outputs


Indeling van raw-output

De volgende voorbeelden worden uitgevoerd in een eenvoudige repo. De repo is aangemaakt met de onderstaande opdrachten:

$:> 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

Als we op dit punt git diff uitvoeren, is er geen uitvoer. Dit gedrag is verwacht omdat er geen wijzigingen zijn in de repo naar diff. Zodra de repo is aangemaakt en we het bestand diff_test.txt hebben toegevoegd, kunnen we de inhoud van het bestand wijzigen om te beginnen met experimenteren met diff-output.

Git-branch
gerelateerd materiaal

Git-branch

Logo Bitbucket
Oplossing bekijken

Git leren met Bitbucket Cloud

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

Als je deze opdracht uitvoert, wordt de inhoud van het bestand diff_test.txt gewijzigd. Eenmaal gewijzigd, kunnen we een diff bekijken en de output analyseren. Het uitvoeren van git diff levert nu de volgende output op:

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

Laten we nu een meer gedetailleerde uitsplitsing van de diff-output bekijken.

1. Input voor de vergelijking

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

Deze regel geeft de inputbronnen van de diff weer. We zien dat a/diff_test.txt en b/diff_test.txt zijn doorgegeven aan de diff.

2. Metagegevens

index 6b0c6cf..b37e70a 100644

Met deze regel worden enkele interne Git-metagegevens weergegeven. Je hebt deze informatie waarschijnlijk niet nodig. De cijfers in deze uitvoer komen overeen met de hash-ID's van de versie van het Git-object.

3. Markeringen voor wijzigingen

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

Deze regels zijn een legenda die symbolen toewijst aan elke diff-inputbron. In dit geval worden veranderingen ten opzichte van a/diff_test.txt gemarkeerd met --- en de veranderingen ten opzichte van b/diff_test.txt worden gemarkeerd met het symbool +++.

4. Diff-segmenten

De rest van de diff-output is een lijst met diff-'segmenten'. Een diff geeft alleen de gedeelten van het bestand weer die wijzigingen bevatten. In ons huidige voorbeeld hebben we maar één segment omdat we met een eenvoudig scenario werken. Segmenten hebben hun eigen granulaire outputsemantiek.

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

De eerste regel is de segmentheader. Elk segment wordt voorafgegaan door een header tussen de @@-symbolen. De inhoud van de header is een overzicht van de wijzigingen die in het bestand zijn aangebracht. In ons vereenvoudigde voorbeeld staat -1 +1, wat betekent dat er in regel één wijzigingen zitten. In een meer realistische diff zou je een header zien als:

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

In dit headervoorbeeld zijn er 6 regels geëxtraheerd vanaf regel 34. Daarnaast zijn er 8 regels toegevoegd vanaf regel 34.

De resterende inhoud van het diff-segment geeft de recente veranderingen weer. Elke gewijzigde regel wordt voorafgegaan door een +- of --symbool, dat aangeeft van welke versie van de diff-input de veranderingen afkomstig zijn. Zoals we eerder hebben besproken, geeft - veranderingen aan ten opzichte van a/diff_test.txt en + geeft veranderingen aan ten opzichte van b/diff_test.txt.

Veranderingen benadrukken


1. git diff --color-words

git diff heeft ook een speciale modus om veranderingen met veel meer granulariteit te markeren: --color-words. Deze modus tokeniseert toegevoegde en verwijderde regels op basis van witruimte en differentieert die vervolgens.

$:> 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

Nu worden in de output alleen de kleurgecodeerde woorden weergegeven die zijn gewijzigd.

2. git diff-highlight

Als je de Git-bron kloont, vind je een submap met de naam contrib. Deze bevat een heleboel tools die verband houden met Git, naast andere interessante onderdelen die het nog niet hebben gemaakt tot Git core. Eén daarvan is een Perl-script met de naam diff-highlight. Diff-highlight koppelt overeenkomende regels van de diff-output aan elkaar en markeert gewijzigde subwoordfragmenten.

$:> 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

Nu hebben we onze diff teruggebracht tot de kleinst mogelijke wijziging.

Diffing van binaire bestanden


Naast de hulpprogramma's voor tekstbestanden die we tot nu toe hebben gedemonstreerd, kan git diff worden uitgevoerd op binaire bestanden. Helaas is de standaardoutput niet erg nuttig.

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

Git heeft wel een functie waarmee je een shell-opdracht kunt specificeren om de inhoud van je binaire bestanden om te zetten in tekst voordat je de diff uitvoert. Dit vraagt wel enige configuratie. Eerst moet je een textconv-filter specificeren die beschrijft hoe je een bepaald type binair bestand naar tekst converteert. We gebruiken een eenvoudig hulpprogramma genaamd pdftohtml (beschikbaar via homebrew) om mijn pdf's om te zetten in voor mensen leesbare HTML. Je kunt dit configureren voor één repository door je .git/config-bestand te bewerken of dit globaal doen door ~ /.gitconfig te bewerken

[diff "pdfconv"]
textconv=pdftohtml -stdout

Dan hoef je alleen maar een of meer bestandspatronen te koppelen aan onze pdfconv-filter. Je kunt dit doen door een .gitattributes-bestand te maken in de hoofdmap van je repository.

*.pdf diff=pdfconv

Eenmaal geconfigureerd, voert git diff eerst het binaire bestand uit via het geconfigureerde conversiescript en wordt er een diff gemaakt van de conversieoutput. Dezelfde techniek kan worden toegepast om nuttige diffs op te halen uit allerlei soorten binaire bestanden, bijvoorbeeld: zip's, jar's en andere archieven: als je unzip -l (of iets dergelijks) gebruikt in plaats van pdftohtml, krijg je de paden te zien die zijn toegevoegd of verwijderd tussen commitimages. exiv2 kan worden gebruikt om veranderingen in metagegevens weer te geven, zoals documenten met image-afmetingen. Er bestaan conversietools voor het transformeren van .odf, .doc en van andere documentformaten naar platte tekst. In geval van nood werkt strings vaak voor binaire bestanden waarvoor geen formele converter bestaat.

Bestanden vergelijken: git diff file


Aan de opdracht git diff kan een expliciete optie voor het bestandspad worden doorgegeven. Wanneer een bestandspad wordt doorgegeven aan git diff, wordt de diff-bewerking naar het opgegeven bestand geleid. De onderstaande voorbeelden laten zien hoe dit in zijn werk gaat.

git diff HEAD ./path/to/file

Dit voorbeeld is gericht op ./path/to/file. Indien aangeroepen, worden de specifieke veranderingen in de werkmap vergeleken met de index, waarbij de veranderingen worden weergegeven die nog niet zijn gestaged. git diff voert de vergelijking standaard uit ten opzichte van HEAD. Weglaten van HEAD in het voorbeeld hierboven git diff ./pad/to/file heeft hetzelfde effect.

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

Wanneer git diff wordt aangeroepen met de optie --cached, vergelijkt de diff de gestagede wijzigingen met de lokale repository. De optie --cached is een synoniem van --staged.

Alle veranderingen vergelijken


Als je git diff aanroept zonder een bestandspad, worden de wijzigingen in de hele repository vergeleken. De bovenstaande, bestandsspecifieke voorbeelden, kunnen worden aangeroepen zonder het argument ./path/to/file en kunnen dezelfde outputresultaten hebben voor alle bestanden in de lokale repo.

Veranderingen sinds de laatste commit


git diff toont standaard alle niet-gecommitte wijzigingen sinds de laatste commit.

git diff

Bestanden vergelijken tussen twee verschillende commits


git diff kan Git-refs naar commits voor diff doorgestuurd krijgen. Enkele voorbeelden van refs zijn HEAD, tags en branchnamen. Elke commit in Git heeft een commit-ID, die je kunt verkrijgen wanneer je GIT LOG uitvoert. Je kunt deze commit-ID ook doorgeven aan 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

Branches vergelijken


Twee branches vergelijken

Branches worden zoals alle andere ref-inputs vergeleken met git diff

git diff branch1..other-feature-branch

In dit voorbeeld wordt de puntoperator geïntroduceerd. De twee punten in dit voorbeeld geven aan dat de diff-input bestaat uit de uiteinden van beide branches. Hetzelfde effect treedt op als de punten worden weggelaten en er een spatie wordt gebruikt tussen de branches. Daarnaast is er een operator met drie punten:

git diff branch1...other-feature-branch

De operator met drie punten initieert de diff door de eerste invoerparameter branch1 te wijzigen. Dit verandert branch1 in een referentie van de gedeelde gemeenschappelijke bovenliggende commit van de twee diff-inputs, de gedeelde voorouder van branch1 en de andere functiebranch. De inputparameter van de laatste parameter blijft ongewijzigd als het uiteinde van other-feature-branch.

Bestanden uit twee branches vergelijken


Om een specifiek bestand in verschillende branches te vergelijken, moet je het pad naar het bestand als derde argument invoeren voor git diff

git diff main new_branch ./diff_test.txt

Samenvatting


Op deze pagina zijn het diffing-proces van Git en de opdracht git diff besproken. We hebben besproken hoe je de git diff-uitvoer kunt lezen en welke gegevens in de output zijn opgenomen. Er zijn voorbeelden gegeven van hoe je de output van git diff kunt aanpassen met markeringen en kleuren. We hebben verschillende strategieën besproken, zoals de diffing van bestanden in branches en specifieke commits. Naast de opdracht git diff hebben we ook git log en git checkout gebruikt.


Deel dit artikel
Volgend onderwerp

Aanbevolen artikelen

Bookmark deze resources voor meer informatie over soorten DevOps-teams of voor voortdurende updates over DevOps bij Atlassian.

Mensen die samenwerken met een muur vol tools

Bitbucket-blog

Toelichting DevOps

DevOps-leertraject

Demo Den Feature-demo's met Atlassian-experts

Hoe Bitbucket Cloud werkt met Atlassian Open DevOps

Meld je aan voor onze DevOps-nieuwsbrief

Thank you for signing up