Сторінка чоловіка git-diff
досить довга, і пояснюється багато випадків, які не здаються необхідним початківцю. Наприклад:
git diff origin/master
Сторінка чоловіка git-diff
досить довга, і пояснюється багато випадків, які не здаються необхідним початківцю. Наприклад:
git diff origin/master
Відповіді:
Розглянемо приклад розширеного відмінності від історії git (у фільмі 1088261f у сховищі 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] == '-') {
Дозволяє аналізувати цей патч за рядком.
Перший рядок
razl - git a / buildin-http-fetch.cb / http-fetch.cє заголовком "git diff" у формі
diff --git a/file1 b/file2
. Файли a/
та b/
назви файлів однакові, якщо не йдеться про перейменування / копію (як у нашому випадку). Це --git
означає, що diff є у форматі "git".Далі - один або кілька розширених рядків заголовка. Перші три
індекс подібності 95% перейменувати з вбудованого http-fetch.c перейменуйте на http-fetch.cскажіть нам, що файл був перейменований з
builtin-http-fetch.c
на http-fetch.c
і що ці два файли на 95% однакові (що було використано для виявлення цього перейменування). індекс f3e63d7..e8f44ba 100644розкажіть нам про режим заданого файлу (
100644
означає, що це звичайний файл, а не, наприклад, посилання, а також що він не має виконавчого біта дозволу), а також про скорочений хеш-преймідж (версія файлу перед заданою зміною) та пост-зображення ( версія файлу після зміни). Цей рядок використовується для того, git am --3way
щоб спробувати здійснити тристороннє злиття, якщо виправлення неможливо застосувати самостійно.Далі - дворядковий уніфікований заголовок diff
--- a / buildin-http-fetch.c +++ b / http-fetch.cУ порівнянні з
diff -U
результатом, він не має файлів-файлів-модифікацій-часу, ані часу-модифікацій-файлів після джерела (попереднього зображення) та пункту призначення (пост-зображення). Якщо файл створено, джерелом є /dev/null
; якщо файл було видалено, ціль є /dev/null
. diff.mnemonicPrefix
змінну конфігурації в TRUE, замість a/
і b/
префіксів в цьому заголовку два рядки ви можете мати замість c/
, i/
, w/
і o/
як префікси, відповідно до того , що ви порівняйте; див. git-config (1)Далі йдуть один або декілька луків різниць; кожна команда показує одну область, де файли відрізняються. Уніфікований формат опису починається на зразок рядка
@@ -1,8 +1,9 @@або
@@ -18,6 +19,8 @@ int cmd_http_fetch (int argc, const char ** argv, ...Це у форматі
@@ from-file-range to-file-range @@ [header]
. Діапазон від-файлу знаходиться у формі -<start line>,<number of lines>
, а діапазон до-файлу - +<start line>,<number of lines>
. І початковий, і рядковий рядки відносяться до положення та довжини перегину відповідно до зображення та після зображення. Якщо кількість рядків не відображається, це означає, що це 0.
Необов'язковий заголовок показує функцію C, де відбувається кожна зміна, якщо це файл C (наприклад, -p
опція в GNU diff) або еквівалент, якщо такий є, для інших типів файлів.
Далі йде опис того, де файли відрізняються. Рядки, спільні для обох файлів, починаються з пробілу. Рядки, які насправді відрізняються між двома файлами, містять один із наступних символьних символів у лівій колонці друку:
Так, наприклад, перший шматок
#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;
означає, що cmd_http_fetch
його замінили main
, і цей const char *prefix;
рядок було додано.
Іншими словами, перед зміною відповідний фрагмент файлу 'izgrain-http-fetch.c' виглядав так:
#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;
Після зміни цей фрагмент файлу "http-fetch.c" виглядає замість цього:
#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;
Може бути
\ Немає нового рядка в кінці файлурядок присутній (він не є в прикладі розл.).
Як сказали стипендіати Доналу , найкраще практикувати читання відрізняється на прикладах із реального життя, де ви знаєте, що змінилося.
Список літератури:
git blame -C -C
, ось так це працює; це рішення дизайну Git. Формат git diff просто показує індекс подібності (або несхожості) на користувача.
[header]
це найближчий передує, як і з початком функції, що передує лупі. У більшості випадків цей рядок містить назву функції, в якій знаходиться відрізок. Це може бути налаштовано за допомогою diff
gitattribute, встановленої для diff драйвера, і diff драйвера, включаючи xfuncname
змінну конфігурації.
@@ -1,2 +3,4 @@
частина розл
Ця частина знадобила мені час, щоб зрозуміти, тому я створив мінімальний приклад.
Формат в основному такий же, як diff -u
уніфікований розл.
Наприклад:
diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')
Тут ми видалили рядки 2, 3, 14 та 15. Вихід:
@@ -1,6 +1,4 @@
1
-2
-3
4
5
6
@@ -11,6 +9,4 @@
11
12
13
-14
-15
16
@@ -1,6 +1,4 @@
засоби:
-1,6
означає, що цей фрагмент першого файлу починається з рядка 1 і показує загалом 6 рядків. Тому він показує рядки 1 - 6.
1
2
3
4
5
6
-
означає "старий", як ми його зазвичай називаємо diff -u old new
.
+1,4
означає, що цей фрагмент другого файлу починається з рядка 1 і показує загалом 4 рядки. Тому він показує рядки 1 - 4.
+
означає "новий".
У нас є лише 4 рядки замість 6, оскільки 2 рядки видалено! Новий фрагмент:
1
4
5
6
@@ -11,6 +9,4 @@
для другої частини аналог:
у старому файлі маємо 6 рядків, починаючи з рядка 11 старого файлу:
11
12
13
14
15
16
у новому файлі у нас 4 рядки, починаючи з рядка 9 нового файлу:
11
12
13
16
Зауважте, що рядок 11
- це 9-й рядок нового файлу, тому що ми вже видалили 2 рядки з попереднього елемента: 2 і 3.
Заголовок Ханка
Залежно від версії та конфігурації git, ви також можете отримати рядок коду поруч із @@
рядком, наприклад, func1() {
у:
@@ -4,7 +4,6 @@ func1() {
Це також можна отримати із -p
прапором рівнини diff
.
Приклад: старий файл:
func1() {
1;
2;
3;
4;
5;
6;
7;
8;
9;
}
Якщо ми видалимо рядок 6
, різниця показує:
@@ -4,7 +4,6 @@ func1() {
3;
4;
5;
- 6;
7;
8;
9;
Зауважте, що це не правильний рядок для func1
: він пропускав лінії 1
та 2
.
Ця дивовижна функція часто точно вказує, до якої функції чи класу належить кожен елемент, що дуже корисно для інтерпретації різниці.
Як саме алгоритм вибору заголовка працює, обговорюється на: Звідки береться уривок у заголовку git diff hunk?
@@ -1,6 +1,4 @@
pls не читайте -1
як minus one
або +1
як plus one
натомість читайте це як line 1 to 6
у старому (першому) файлі. Зверніть увагу тут - implies "old"
не на мінус. До речі, дякую за роз’яснення… хааш.
+1,4
сказано, що цей фрагмент відповідає рядкам 1 - 4 другого файлу ". Це тому, що +1,4
може посилатися на непередбачувані рядки контексту. Швидше, що +1,4
насправді означає, що "" є 4
рядки (тобто рядки контексту) у цій "версії" файлу ". Важливо , щоб зрозуміти сенс +
, -
і <whitespace>
на початку цих рядків, як це відноситься до інтерпретації скнари. Більш наочний приклад: youtube.com/watch?v=1tqMjJeyKpw
Ось простий приклад.
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
Ось пояснення (деталі див. Тут ).
--git
не команда, це означає, що це git версія diff (не unix)a/ b/
- це каталоги, вони не реальні. це просто зручність, коли ми маємо справу з тим самим файлом (у моєму випадку a / знаходиться в індексі, а b / знаходиться у робочому каталозі)10ff2df..84d4fa2
- це ідентифікатори blob цих 2-х файлів100644
є "бітами режиму", що вказує, що це звичайний файл (не виконуваний і не символічне посилання)--- a/file +++ b/file
знаки мінус показує рядки у версії a /, але відсутні у b / версії; та знаки плюс показує рядки, відсутні у /, але присутні в b / (у моєму випадку --- означає видалені рядки, а +++ означає додані рядки в b /, і це файл у робочій директорії)@@ -1,5 +1,5 @@
щоб зрозуміти це, краще працювати з великим файлом; якщо у вас є дві зміни в різних місцях, ви отримаєте два записи, як-от @@ -1,5 +1,5 @@
; припустимо, у вас є файл line1 ... line100 та видалений line10 та доданий новий рядок100 - ви отримаєте:@@ -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
) повинні читатись у вісімці (значення: 1, 2, 4 відповідно eXecute, Write та Read дозвіл) і відповідає в цьому порядку власнику (користувачеві), потім групуванню, а потім іншим дозволам. Отже, коротше, 644
це означає, що якщо написано символічно u=rw,og=r
, це читається для всіх, але може бути написано лише власником. Інші цифри, що знаходяться зліва, кодують іншу інформацію, наприклад, якщо це символьне посилання тощо. Значення можна побачити github.com/git/git/blob/… , перший 1 у цій позиції - "звичайний файл".
Формат виводу за замовчуванням (який спочатку походить від програми, відомої так, diff
ніби ви хочете шукати більше інформації) відомий як "уніфікований розл." Він містить по суті 4 різних типів рядків:
+
,-
таЯ раджу, що ви на практиці читання відрізняються між двома версіями файлу, де ви точно знаєте, що ви змінили. Так, ви зрозумієте, що відбувається, коли побачите це.
На моєму комп'ютері:
info diff
потім виберіть: Output formats
-> Context
-> Unified format
-> Detailed Unified
:
Або людина в Інтернеті відрізняється від gnu по тому ж шляху до того ж розділу:
Файл: diff.info, Вузол: Детальний Уніфікований, Далі: Приклад Уніфікований, Вгору: Уніфікований формат
Детальний опис уніфікованого формату ......................................
Уніфікований вихідний формат починається з дворядкового заголовка, який виглядає приблизно так:
--- FROM-FILE FROM-FILE-MODIFICATION-TIME +++ TO-FILE TO-FILE-MODIFICATION-TIME
Марка часу виглядає як "2002-02-21 23: 30: 39.942229878 -0800", щоб вказати дату, час з дробовими секундами та часовий пояс.
Ви можете змінити вміст заголовка за допомогою параметра `--label = LABEL '; див. * Примітка альтернативних імен ::.
Далі йдуть один або декілька луків різниць; кожна команда показує одну область, де файли відрізняються. Уніфіковані формати виглядають так:
@@ FROM-FILE-RANGE TO-FILE-RANGE @@ LINE-FROM-EITHER-FILE LINE-FROM-EITHER-FILE...
Рядки, спільні для обох файлів, починаються з пробілу. Рядки, які насправді відрізняються між двома файлами, містять один із наступних символьних символів у лівій колонці друку:
`+ 'Тут було додано рядок до першого файлу.
`- 'З першого файлу тут видалено рядок.
З вашого запитання незрозуміло, яку частину дифузів ви вважаєте заплутаною: власне diff чи надруковані додаткові відомості заголовка. На всякий випадок, ось короткий огляд заголовка.
Перший рядок є чимось на кшталт diff --git a/path/to/file b/path/to/file
- очевидно, він просто розповідає, для якого файлу призначений цей розділ diff. Якщо ви встановите булеву змінну конфігурації diff.mnemonic prefix
, то a
і b
буде змінено на більш описові літери, такі як c
і w
(виконувати та працювати дерево).
Далі, є "рядки режиму" - рядки, що дають опис будь-яких змін, які не передбачають зміни вмісту файлу. Сюди входять нові / видалені файли, перейменовані / скопійовані файли та зміни дозволів.
Нарешті, є така лінія, як index 789bd4..0afb621 100644
. Вам, мабуть, ніколи не буде про це байдуже, але ці 6-значні шістнадцяткові цифри - це скорочені хеші SHA1 старого та нового крапок цього файлу (blob - це git-об’єкт, який зберігає необроблені дані, як вміст файлу). І звичайно, 100644
це режим файлу - три останні цифри, очевидно, є дозволами; перші три дають додаткову інформацію про метадані файлів ( повідомлення, що описує це ).
Після цього ви переходите до стандартного уніфікованого різного виходу (як і класичний diff -U
). Він розділений на файли - це фрагмент файлу, що містить зміни та їх контекст. Кожному елементу передує пара ---
та +++
рядки, що позначають відповідний файл, тоді фактичним розбігом є (за замовчуванням) три рядки контексту з обох боків -
та +
рядки, що показують видалені / додані рядки.
index
рядка. Підтвердженоgit hash-object ./file