-
1. Начало
- 1.1 За Version Control системите
- 1.2 Кратка история на Git
- 1.3 Какво е Git
- 1.4 Конзолата на Git
- 1.5 Инсталиране на Git
- 1.6 Първоначална настройка на Git
- 1.7 Помощна информация в Git
- 1.8 Обобщение
-
2. Основи на Git
-
3. Клонове в Git
-
4. GitHub
-
5. Git инструменти
- 5.1 Избор на къмити
- 5.2 Интерактивно индексиране
- 5.3 Stashing и Cleaning
- 5.4 Подписване на вашата работа
- 5.5 Търсене
- 5.6 Манипулация на историята
- 5.7 Мистерията на командата Reset
- 5.8 Сливане за напреднали
- 5.9 Rerere
- 5.10 Дебъгване с Git
- 5.11 Подмодули
- 5.12 Пакети в Git (Bundling)
- 5.13 Заместване
- 5.14 Credential Storage система
- 5.15 Обобщение
-
6. Настройване на Git
- 6.1 Git конфигурации
- 6.2 Git атрибути
- 6.3 Git Hooks
- 6.4 Примерна Git-Enforced политика
- 6.5 Обобщение
-
7. Git и други системи
- 7.1 Git като клиент
- 7.2 Миграция към Git
- 7.3 Обобщение
-
8. Git на ниско ниво
- 8.1 Plumbing и Porcelain команди
- 8.2 Git обекти
- 8.3 Git референции
- 8.4 Packfiles
- 8.5 Refspec спецификации
- 8.6 Транспортни протоколи
- 8.7 Поддръжка и възстановяване на данни
- 8.8 Environment променливи
- 8.9 Обобщение
-
9. Приложение A: Git в други среди
-
10. Приложение B: Вграждане на Git в приложения
- 10.1 Git от команден ред
- 10.2 Libgit2
- 10.3 JGit
- 10.4 go-git
- 10.5 Dulwich
-
A1. Приложение C: Git команди
- A1.1 Настройки и конфигурация
- A1.2 Издърпване и създаване на проекти
- A1.3 Snapshotting
- A1.4 Клонове и сливане
- A1.5 Споделяне и обновяване на проекти
- A1.6 Инспекция и сравнение
- A1.7 Дебъгване
- A1.8 Patching
- A1.9 Email команди
- A1.10 Външни системи
- A1.11 Административни команди
- A1.12 Plumbing команди
5.10 Git инструменти - Дебъгване с Git
Дебъгване с Git
В допълнение на основната си задача за контрол на версиите, Git също така осигурява някои команди, които могат да ви помогнат при търсене на грешки в сорс кода. Понеже Git е проектиран да обслужва всякакъв вид съдържание, тези инструменти са доста общи, не навлизат в дълбочина, но въпреки това често могат да бъдат полезни.
Анотации на файлове
Ако проследявате дадена грешка в кода си и искате да разберете кога и как е възникнала, файловите анотации често са най-добрия начин да направите това.
Те показват кой е последния къмит модифицирал всеки един ред от произволен файл.
Така че, ако срещнете метод с бъгав код в него, можете да анотирате файла с командата git blame
за да установите кой къмит е въвел в кода специфичния ред или редове от код.
Следващият пример използва git blame
за да установи кои къмити и разработчици са отговорни за редовете код от един Makefile
файл в проекта на Linux ядрото и освен това използва флага L
за да ограничи изхода до редовете между 69 и 82:
$ git blame -L 69,82 Makefile
b8b0618cf6fab (Cheng Renquan 2009-05-26 16:03:07 +0800 69) ifeq ("$(origin V)", "command line")
b8b0618cf6fab (Cheng Renquan 2009-05-26 16:03:07 +0800 70) KBUILD_VERBOSE = $(V)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) ifndef KBUILD_VERBOSE
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) KBUILD_VERBOSE = 0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75)
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 76) ifeq ($(KBUILD_VERBOSE),1)
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 77) quiet =
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 78) Q =
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 79) else
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 80) quiet=quiet_
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 81) Q = @
066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 82) endif
Първото поле в ляво на таблицата е част от SHA-1 хеша на къмита, който последно е модифицирал съответния ред.
Следващите две колони се извличат от самия къмит — името на автора му и датата на къмита.
В следващите колони идват номера и съдържанието на реда от файла.
Отбележете също и редовете започващи с ^1da177e4c3f4
, при тях префикса ^
обозначава, че те са били създадени с първия къмит на хранилището и след това не са променяни нито веднъж.
Този вид обозначение причинява малко смут, защото досега видяхме поне три различни начина, при които Git използва този символ за да модифицира SHA-1 хеш стойностите, но в този конкретен случай това е неговото значение.
Друга хубава черта на Git е, че не проследява изрично преименуванията на файловете.
Git записва snapshot-ите и след това се опитва да установи какво е било безусловно преименувано постфактум.
Една от интересните особености на това е, че можете да правите запитвания и за премествания на код.
С параметър -C
към git blame
Git анализира файла, който анотирате и се опитва да установи откъде са се появили дадени отрязъци от код, ако те са копирани от друго място.
Например, да кажем че преработвате файл с име GITServerHandler.m
в множество файлове, един от които се казва GITPackUpload.m
.
Изследвайки GITPackUpload.m
с параметър -C
, можете да видите къде първоначално са се намирали секции код от него:
$ git blame -C -L 141,153 GITPackUpload.m
f344f58d GITServerHandler.m (Scott 2009-01-04 141)
f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC
f344f58d GITServerHandler.m (Scott 2009-01-04 143) {
70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI
ad11ac80 GITPackUpload.m (Scott 2009-03-24 145)
ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha;
ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g
ad11ac80 GITPackUpload.m (Scott 2009-03-24 148)
ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI
ad11ac80 GITPackUpload.m (Scott 2009-03-24 150)
56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) {
56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb
56ef2caf GITServerHandler.m (Scott 2009-01-05 153)
Това е наистина полезно. Нормално бихте получили като оригинален къмит този, при който сте вмъкнали съдържанието в новия файл, защото това е първия път, когато сте докоснали тези редове в този файл. Git обаче може да ви намери и оригиналния къмит, в който сте написали тези редове, дори те да са били в друг файл.
Бинарно търсене
Анотирането на файлове помага, когато знаете къде започва проблема.
Ако обаче не знаете какво се е счупило и има дузина или стотици къмити от последния път, когато знаете че кодът е работил, вероятно ще прибегнете до помощта на git bisect
.
Командата bisect
се използва за бинарно търсене в историята на къмитите за да ви помогне да идентифицирате даден проблем възможно най-бързо.
Нека кажем, че сте публикували завършена версия на кода си и започвате да получавате новини за грешки, които не се наблюдават в работната версия и нямате идея защо кодът се държи така.
Връщате се обратно в кода и се оказва, че всъщност можете да пресъздадете грешката, но все още не разбирате защо възниква.
В такъв случай можете да bisect-нете (разполовите) кода за да потърсите причината (понятието идва от начина, по който Git третира и разцепва историята в процеса на търсене описан в примерите, които следват).
Първо, изпълнявате git bisect start
за да стартирате процеса и след това git bisect bad
за да кажете на системата, че текущия къмит е проблематичен.
След това, трябва да кажете на bisect кога е бил последния работещ статус на нещата изпълнявайки git bisect good <good_commit>
:
$ git bisect start
$ git bisect bad
$ git bisect good v1.0
Bisecting: 6 revisions left to test after this
[ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] Error handling on repo
Git е установил около 12 къмита, които са се случили между този, който сте маркирали като последно работещ (v1.0) и текущата проблемна версия и е извлякъл за вас средния от тях.
На този етап, можете да си пуснете тестовете, за да видите дали проблемът все още се появява в този извлечен къмит.
Ако е така, то той е възникнал някъде преди средния къмит. Ако не е, значи възниква след него.
Да кажем, че проблемът го няма на текущия къмит — вие уведомявате Git за това с git bisec good
и продължавате да търсите:
$ git bisect good
Bisecting: 3 revisions left to test after this
[b047b02ea83310a70fd603dc8cd7a6cd13d15c04] Secure this thing
Сега сте на друг къмит, който е по средата между този който току що тествахте и проблематичния.
Пускате тестовете отново и този път установявате, че грешката се появява и уведомявате Git с git bisect bad
:
$ git bisect bad
Bisecting: 1 revisions left to test after this
[f71ce38690acf49c1f3c9bea38e09d82a5ce6014] Drop exceptions table
Този къмит е безпроблемен и сега Git има информацията, която му е нужна за да разбере къде се е появил проблема. Вие получавате SHA-1 хеша на първия проблемен къмит, заедно с малко данни за него и списък на модифицираните файлове така че да успеете да установите източника на грешката:
$ git bisect good
b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit
commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04
Author: PJ Hyett <pjhyett@example.com>
Date: Tue Jan 27 14:48:32 2009 -0800
Secure this thing
:040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730
f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config
Когато приключите, трябва да изпълните git bisect reset
за да пренасочите HEAD към мястото, където сте били преди да стартирате процеса:
$ git bisect reset
Това е мощен инструмент, който за минути може да провери стотици къмити в процеса на търсене на грешка.
В допълнение, ако имате скрипт, който завършва със статус exit 0, ако проектът работи коректно или с различен статус, ако това не е така, можете напълно да автоматизирате git bisect
.
Първо, вие отново указвате обхвата на bisect подавайки познатите добър и лош къмит.
Можете да направите това изписвайки ги с bisect start
командата, първо подавате лошия (HEAD) и след това последно познатия добър (v1.0):
$ git bisect start HEAD v1.0
$ git bisect run test-error.sh
Правейки това, Git автоматично ще изпълнява test-error.sh
за всеки извлечен къмит докато намери първия проблематичен.
Можете също да изпълнявате неща като make
или make tests
или каквото и да било друго средство, което използвате за автоматично тестване.