La page de manuel de git-diff
est assez longue et explique de nombreux cas qui ne semblent pas nécessaires pour un débutant. Par exemple:
git diff origin/master
La page de manuel de git-diff
est assez longue et explique de nombreux cas qui ne semblent pas nécessaires pour un débutant. Par exemple:
git diff origin/master
Réponses:
Jetons un coup d'œil à l'exemple de différence avancée de l'historique git (dans commit 1088261f dans le référentiel 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] == '-') {
Permet d'analyser ce patch ligne par ligne.
La première ligne
diff --git a / builtin-http-fetch.cb / http-fetch.cest un en-tête "git diff" dans le formulaire
diff --git a/file1 b/file2
. Les noms de fichiers a/
et b/
sont les mêmes sauf si un changement de nom / copie est impliqué (comme dans notre cas). Le --git
est de dire que diff est dans le format diff « git ».Viennent ensuite une ou plusieurs lignes d'en-tête étendues. Les trois premiers
indice de similitude 95% renommer depuis builtin-http-fetch.c renommer en http-fetch.cnous dire que le fichier a été renommé
builtin-http-fetch.c
en http-fetch.c
et que ces deux fichiers sont identiques à 95% (ce qui a été utilisé pour détecter ce renommage). index f3e63d7..e8f44ba 100644nous parler du mode du fichier donné (
100644
signifie qu'il s'agit d'un fichier ordinaire et non par exemple d'un lien symbolique, et qu'il n'a pas de bit d'autorisation exécutable), et du hachage raccourci de la pré-image (la version du fichier avant le changement donné) et de la post-image (le version du fichier après modification). Cette ligne est utilisée par git am --3way
pour essayer de faire une fusion à 3 voies si le patch ne peut pas être appliqué lui-même.Vient ensuite l'en-tête de diff unifié sur deux lignes
--- un / builtin-http-fetch.c +++ b / http-fetch.cComparé au
diff -U
résultat, il n'a pas de date de modification de fichier ni de date de modification de fichier après les noms de fichier source (préimage) et de destination (postimage). Si le fichier a été créé, la source est /dev/null
; si le fichier a été supprimé, la cible est /dev/null
. diff.mnemonicPrefix
variable de configuration true, à la place a/
et b/
préfixes dans cet en- tête de deux lignes , vous pouvez avoir la place c/
, i/
, w/
et o/
comme préfixes, respectivement à ce que vous comparez; voir git-config (1)Viennent ensuite un ou plusieurs morceaux de différences; chaque morceau montre une zone où les fichiers diffèrent. Les morceaux au format unifié commencent par des lignes comme
@@ -1,8 +1,9 @@ou
@@ -18,6 +19,8 @@ int cmd_http_fetch (int argc, const char ** argv, ...C'est dans le format
@@ from-file-range to-file-range @@ [header]
. La plage de fichiers est sous la forme -<start line>,<number of lines>
et la plage de fichiers est +<start line>,<number of lines>
. La ligne de départ et le nombre de lignes font référence à la position et à la longueur du morceau dans la pré-image et la post-image, respectivement. Si le nombre de lignes n'est pas affiché, cela signifie qu'il est égal à 0.
L'en-tête facultatif montre la fonction C où chaque changement se produit, s'il s'agit d'un fichier C (comme l' -p
option dans diff GNU), ou l'équivalent, le cas échéant, pour d'autres types de fichiers.
Vient ensuite la description des différences entre les fichiers. Les lignes communes aux deux fichiers commencent par un caractère espace. Les lignes qui diffèrent réellement entre les deux fichiers ont l'un des caractères indicateurs suivants dans la colonne d'impression de gauche:
Ainsi, par exemple, le premier morceau
#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;
signifie que cela a cmd_http_fetch
été remplacé par main
, et cette const char *prefix;
ligne a été ajoutée.
En d'autres termes, avant la modification, le fragment approprié du fichier 'builtin-http-fetch.c' ressemblait à ceci:
#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;
Après la modification, ce fragment du fichier maintenant 'http-fetch.c' ressemble à ceci:
#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;
Il pourrait y avoir
\ Pas de nouvelle ligne à la fin du fichierligne présente (ce n'est pas dans l'exemple diff).
Comme Donal Fellows l'a dit, il est préférable de pratiquer la lecture des différences sur des exemples réels, où vous savez ce que vous avez changé.
Références:
git blame -C -C
, c'est comme ça que ça fonctionne; c'est la décision de conception de Git. Le format git diff montre juste l'index de similitude (ou dissimilarité) à l'utilisateur.
[header]
est le précédent le plus proche comme avec le début de la fonction qui précède un morceau. Dans la plupart des cas, cette ligne inclut le nom de la fonction dans laquelle se trouve le morceau de diff. Ceci est configurable avec diff
gitattribute défini sur diff driver, et diff driver incluant la xfuncname
variable de configuration.
@@ -1,2 +3,4 @@
une partie du diff
Cette partie m'a pris du temps à comprendre, j'ai donc créé un exemple minimal.
Le format est fondamentalement le même que le diff -u
diff unifié.
Par exemple:
diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')
Ici, nous avons supprimé les lignes 2, 3, 14 et 15. Sortie:
@@ -1,6 +1,4 @@
1
-2
-3
4
5
6
@@ -11,6 +9,4 @@
11
12
13
-14
-15
16
@@ -1,6 +1,4 @@
veux dire:
-1,6
signifie que cette partie du premier fichier commence à la ligne 1 et affiche un total de 6 lignes. Il montre donc les lignes 1 à 6.
1
2
3
4
5
6
-
signifie "ancien", comme nous l'appelons habituellement comme diff -u old new
.
+1,4
signifie que cette partie du deuxième fichier commence à la ligne 1 et affiche un total de 4 lignes. Il montre donc les lignes 1 à 4.
+
signifie "nouveau".
Nous n'avons que 4 lignes au lieu de 6 car 2 lignes ont été supprimées! Le nouveau morceau est juste:
1
4
5
6
@@ -11,6 +9,4 @@
pour le second morceau est analogue:
sur l'ancien fichier, nous avons 6 lignes, à partir de la ligne 11 de l'ancien fichier:
11
12
13
14
15
16
sur le nouveau fichier, nous avons 4 lignes, à partir de la ligne 9 du nouveau fichier:
11
12
13
16
Notez que la ligne 11
est la 9ème ligne du nouveau fichier car nous avons déjà supprimé 2 lignes sur le morceau précédent: 2 et 3.
En-tête de morceau
Selon votre version et configuration de git, vous pouvez également obtenir une ligne de code à côté de la @@
ligne, par exemple func1() {
dans:
@@ -4,7 +4,6 @@ func1() {
Cela peut également être obtenu avec le -p
drapeau de la plaine diff
.
Exemple: ancien fichier:
func1() {
1;
2;
3;
4;
5;
6;
7;
8;
9;
}
Si nous supprimons la ligne 6
, le diff affiche:
@@ -4,7 +4,6 @@ func1() {
3;
4;
5;
- 6;
7;
8;
9;
Notez que ce n'est pas la bonne ligne pour func1
: elle a sauté les lignes 1
et 2
.
Cette fonctionnalité impressionnante indique souvent exactement à quelle fonction ou classe chaque morceau appartient, ce qui est très utile pour interpréter la différence.
Comment l'algorithme pour choisir l'en-tête fonctionne exactement est discuté à: D'où provient l'extrait de l'en-tête de morceau git diff?
@@ -1,6 +1,4 @@
pls, ne lisez pas en -1
tant que minus one
ou en +1
tant que tel, plus one
lisez-le comme line 1 to 6
dans l'ancien (premier) fichier. Notez ici - implies "old"
pas moins. BTW, merci pour la clarification ... haash.
+1,4
dit que cette pièce correspond aux lignes 1 à 4 du deuxième fichier ". En effet, +1,4
peut faire référence à des lignes de contexte non contingentes. Au contraire, ce que " +1,4
" signifie en réalité, c'est " qu'il y a des 4
lignes (c'est-à-dire des lignes de contexte) dans cette" version "du fichier ". Il est important de comprendre la signification de la +
, -
et <whitespace>
au début de ces lignes, car elle s'applique à l'interprétation des mecs. Un exemple plus visuel: youtube.com/watch?v=1tqMjJeyKpw
Voici l'exemple simple.
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
Voici une explication (voir les détails ici ).
--git
n'est pas une commande, cela signifie que c'est une version git de diff (pas unix)a/ b/
sont des répertoires, ils ne sont pas réels. c'est juste une commodité lorsque nous traitons le même fichier (dans mon cas, a / est dans l'index et b / est dans le répertoire de travail)10ff2df..84d4fa2
sont les ID de blob de ces 2 fichiers100644
est le "mode bits", indiquant qu'il s'agit d'un fichier normal (non exécutable et non pas un lien symbolique)--- a/file +++ b/file
les signes moins montrent des lignes dans la version a / mais manquantes dans la version b /; et le signe plus indique les lignes manquantes dans a / mais présentes dans b / (dans mon cas --- signifie lignes supprimées et +++ signifie lignes ajoutées dans b / et ceci le fichier dans le répertoire de travail)@@ -1,5 +1,5 @@
pour comprendre cela, il vaut mieux travailler avec un gros fichier; si vous avez deux changements dans des endroits différents, vous obtiendrez deux entrées comme @@ -1,5 +1,5 @@
; Supposons que vous ayez le fichier line1 ... line100 et supprimé line10 et ajoutez un nouveau line100 - vous obtiendrez:@@ -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
) doivent être lus en octal (valeurs: 1, 2, 4 respectivement autorisation eXecute, Write et Read) et correspondent dans cet ordre au propriétaire (utilisateur), puis au groupe, puis aux autres autorisations. Donc, en bref, 644
cela signifierait que s'il était écrit de manière symbolique u=rw,og=r
, il est lisible par tout le monde mais accessible en écriture uniquement par le propriétaire. Les autres chiffres sur la gauche codent d'autres informations, comme s'il s'agit d'un lien symbolique, etc. Les valeurs peuvent être vues sur github.com/git/git/blob/… , le premier 1 dans cette position est "fichier normal".
Le format de sortie par défaut (qui provient à l'origine d'un programme connu comme diff
si vous voulez chercher plus d'informations) est connu comme un «diff unifié». Il contient essentiellement 4 types de lignes différents:
+
,-
, etJe vous conseille de vous entraîner à lire les différences entre deux versions d'un fichier où vous savez exactement ce que vous avez changé. Comme ça, vous reconnaîtrez exactement ce qui se passe quand vous le voyez.
Sur mon mac:
info diff
puis sélectionnez: Output formats
-> Context
-> Unified format
-> Detailed Unified
:
Ou diff homme en ligne sur gnu suivant le même chemin vers la même section:
Fichier: diff.info, Noeud: Unified détaillé, Next: Exemple Unified, Up: Format Unified
Description détaillée du format unifié ......................................
Le format de sortie unifié commence par un en-tête de deux lignes, qui ressemble à ceci:
--- FROM-FILE FROM-FILE-MODIFICATION-TIME +++ TO-FILE TO-FILE-MODIFICATION-TIME
L'horodatage ressemble à `2002-02-21 23: 30: 39.942229878 -0800 'pour indiquer la date, l'heure avec des fractions de seconde et le fuseau horaire.
Vous pouvez changer le contenu de l'en-tête avec l'option `--label = LABEL '; voir * Remarque sur les noms alternatifs ::.
Viennent ensuite un ou plusieurs morceaux de différences; chaque morceau montre une zone où les fichiers diffèrent. Les mecs au format unifié ressemblent à ceci:
@@ FROM-FILE-RANGE TO-FILE-RANGE @@ LINE-FROM-EITHER-FILE LINE-FROM-EITHER-FILE...
Les lignes communes aux deux fichiers commencent par un caractère espace. Les lignes qui diffèrent réellement entre les deux fichiers ont l'un des caractères indicateurs suivants dans la colonne d'impression de gauche:
`+ 'Une ligne a été ajoutée ici au premier fichier.
`- 'Une ligne a été supprimée ici du premier fichier.
Votre question ne permet pas de savoir quelle partie des différences vous semble déroutante: la différence réelle ou les informations supplémentaires de l'en-tête que git imprime. Juste au cas où, voici un bref aperçu de l'en-tête.
La première ligne est quelque chose comme diff --git a/path/to/file b/path/to/file
- évidemment, elle vous indique simplement à quel fichier cette section du diff est destinée. Si vous définissez la variable de configuration booléenne diff.mnemonic prefix
, le a
et b
sera remplacé par des lettres plus descriptives comme c
et w
(validation et arborescence de travail).
Ensuite, il y a des "lignes de mode" - des lignes vous donnant une description de tout changement qui n'implique pas de changer le contenu du fichier. Cela inclut les fichiers nouveaux / supprimés, les fichiers renommés / copiés et les modifications des autorisations.
Enfin, il y a une ligne comme index 789bd4..0afb621 100644
. Vous ne vous en soucierez probablement jamais, mais ces nombres hexadécimaux à 6 chiffres sont les hachages SHA1 abrégés des anciens et nouveaux blobs pour ce fichier (un blob est un objet git stockant des données brutes comme le contenu d'un fichier). Et bien sûr, 100644
c'est le mode du fichier - les trois derniers chiffres sont évidemment des permissions; les trois premiers donnent des informations supplémentaires sur les métadonnées des fichiers ( SO post décrivant que ).
Après cela, vous êtes sur la sortie diff unifiée standard (tout comme le classique diff -U
). Il est divisé en morceaux - un morceau est une section du fichier contenant les modifications et leur contexte. Chaque morceau est précédé d'une paire de ---
et +++
lignes indiquant le fichier en question, alors la comparaison est réelle (par défaut) trois lignes de contexte de chaque côté du -
et des +
lignes montrant les lignes supprimées / ajoutées.
index
ligne. Confirmé pargit hash-object ./file