Git diff что делает
Перейти к содержимому

Git diff что делает

  • автор:

Команда Git diff. Как сравнивать изменения в Git

git diff

Для вывода изменений в файлах по сравнению с последним коммитом, используется git diff без параметров:

git diff

Команда выводит изменения в файлах, которые еще не были добавлены в индекс. Сравнение происходит с последним коммитом.

Сравнение с последним коммитом, включая файлы в индексе

Если вы изменили какие-нибудь файлы в вашем рабочем каталоге и добавили один или несколько из них в индекс (с помощью git add ), то команда git diff не покажет изменения в этих файлах. Чтобы показать изменения в файлах, включая файлы, добавленные в индекс, используется ключ —cached :

git diff --cached

Сравнение коммитов

Команда git diff позволяет сравнивать два различных коммита. Сначала нужно определить хеш (ID) коммитов, которые требуется сравнивать. Можно воспользоваться командой git log, чтобы вывести список коммитов и их идентификаторы:

git log --oneline

Теперь сравним два коммита. Для этого в качестве первого аргумента команде git diff указывается хеш первого коммита, а вторым аргументом хеш второго коммита, например:

git diff 4612297 5e356cf

Сравнение двух веток

Для вывода всех изменений между концами двух веток, необходимо для git diff указать имена веток:

git diff branch1 branch2

Сравнение файлов между двумя ветками

Чтобы сравнить конкретные файлы между двумя ветками используется команда:

git diff branch1 branch2 ./myfile.cpp

Вместо branch1, branch2 нужно указать название веток, а вместо myfile.cpp путь до сравниваемого файла. Через пробел можно добавить еще файлы для сравнения.

Исключить некоторые файлы из сравнения

Иногда нужно выполнить git diff , но исключить один или несколько файлов, чтобы команда git diff их проигнорировала. Для этого используется запись вида ’:(exclude)имя_файла’ или короткая запись ’:!имя_файла’

git diff -- . ':(exclude)file1.abc' ':(exclude)file2.abc'

Или более короткая запись:

git diff -- . ':!file1.abc' ':!file2.abc'

Сравнивать только изменения в файлах (игнорировать новые и удаленные файлы)

Чтобы исключить из сравнения новые и удаленные файлы, можно воспользоваться опцией —diff-filter , которая позволяет выбирать какие именно изменения (файлы) нужно сравнивать.

Чтобы выполнить сравнение только изменений внутри файлов (игнорируя новые, удаленные, переименованные файлы) используется ключ Modified (M) — —diff-filter=M :

git diff --diff-filter=M

Смотрите также:

  • Как изменить файлы в старом коммите (не последнем)
  • Как добавить все файлы в коммит, кроме одного
  • Как создать ветку из предыдущего коммита
  • Команда Git stash. Как прятать изменения в Git
  • Как показать файлы, которые будут добавлены в текущий коммит
  • Как изменить дату коммита
  • Как установить Git
  • Как добавить файлы в последний коммит
  • Как создать новый репозиторий
  • Как объединить коммиты

git diff

Сравнение — это функция, анализирующая два входных набора данных и отображающая различия между ними. git diff представляет собой многоцелевую команду Git, которая инициирует функцию сравнения источников данных Git — коммитов, веток, файлов и т. д. В этом документе описываются типичные варианты вызова git diff и схемы рабочего процесса сравнения. Зачастую вместе с командой git diff используются git status и git log для анализа текущего состояния репозитория Git.

Чтение вывода команды diff

Формат вывода необработанных данных

Следующие примеры будут выполнены в простом репозитории. Репозиторий создается с помощью перечисленных ниже команд:

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

Если выполнить git diff на этом этапе, команда ничего не выведет. Это ожидаемая ситуация, поскольку в репозитории отсутствуют изменения для сравнения. После создания репозитория и добавления файла diff_test.txt можно отредактировать его содержимое и поэкспериментировать с выходными данными команды сравнения.

git branch

Связанные материалы
git branch
СМ. РЕШЕНИЕ
Изучите Git с помощью Bitbucket Cloud
$:> echo "this is a diff example" > diff_test.txt

При выполнении этой команды содержимое файла diff_test.txt будет изменено. После этого можно просмотреть изменения и проанализировать выходные данные. Теперь при выполнении git diff мы получим следующие выходные данные:

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

А теперь подробно рассмотрим выходные данные сравнения.

1. Входные данные сравнения

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

В этой строке отображаются входные данные сравнения. Как видите, для сравнения переданы файлы a/diff_test.txt и b/diff_test.txt .

2. Метаданные

index 6b0c6cf..b37e70a 100644

В этой строке отображаются внутренние метаданные Git. Скорее всего, они вам не понадобятся. Номера в этих выходных данных соответствуют хеш-идентификаторам версий объектов Git.

3. Маркеры изменений

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

Эти строки представляют собой легенду обозначений для каждого источника входных данных сравнения. В данном случае изменения из файла a/diff_test.txt помечаются символом — , а из файла b/diff_test.txt — символом +++ .

4. Сравниваемые фрагменты

Остальные выходные данные сравнения — это список сравниваемых фрагментов. При сравнении отображаются только разделы файла, в которых есть изменения. В данном примере имеется только один такой фрагмент, поскольку обрабатывается простой сценарий. Фрагменты имеют собственную ограниченную семантику вывода.

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

Первая строка — это заголовок фрагмента. К началу каждого фрагмента добавляется заголовок, окруженный символами @@ . Заголовок кратко описывает изменения в файле. В нашем простом примере заголовок -1 +1 означает, что имеются изменения в первой строке. В реальных случаях заголовок может выглядеть так:

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

В данном примере заголовка было извлечено 6 строк начиная со строки 34. Кроме того, после строки 34 было добавлено 8 строк.

Остальное содержимое фрагмента сравнения — это недавние изменения. Каждой измененной строке предшествует символ + или — , указывающий на источник входных данных сравнения. Как уже упоминалось, символ — указывает на изменения в файле a/diff_test.txt , а + — на изменения в файле b/diff_test.txt .

Подсветка изменений

1. git diff —color-words

Кроме того, команда git diff имеет специальный режим подсветки изменений с повышенной детализацией: ‐‐color-words . В этом режиме добавленные и удаленные строки отделяются пробелами, а затем выполняется их сравнение.

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

Теперь в выходных данных отображаются только измененные слова с цветовой подсветкой.

2. git diff-highlight

При клонировании источника Git появляется подкаталог с именем contrib. Он содержит набор связанных с Git инструментов и различные данные, которые пока еще не были включены в ядро Git. В их число входит скрипт Perl под названием diff-highlight. Diff-highlight попарно сопоставляет совпадающие строки выходных данных сравнения и подсвечивает измененные фрагменты внутри слов.

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

Теперь сравниваемые строки объединены в пары для определения наименьших возможных изменений.

Сравнение двоичных файлов

Наряду с описанными возможностями обработки текстовых файлов команда git diff может работать с двоичными файлами. К сожалению, в этом случае использовать формат вывода по умолчанию не слишком продуктивно.

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

В Git есть функция, с помощью которой можно указать команду оболочки для преобразования содержимого двоичных файлов в текст до начала сравнения. Для этого потребуется выполнить небольшую настройку. Для начала необходимо указать фильтр textconv, описывающий процесс преобразования определенного типа двоичного файла в текст. В данном случае используется простой инструмент pdftohtml (доступный в Homebrew), который позволяет преобразовывать файлы PDF в удобный для восприятия формат HTML. Его можно назначить отдельному репозиторию в файле .git/config или глобально в файле ~ /.gitconfig

[diff "pdfconv"]
textconv=pdftohtml -stdout

Затем необходимо связать с фильтром pdfconv один или несколько шаблонов файлов. Для этого необходимо создать файл .gitattributes в корневом каталоге репозитория.

*.pdf diff=pdfconv

После настройки команда git diff сначала обрабатывает двоичный файл с помощью настроенного скрипта конвертера, а затем выполняет сравнение выходных данных конвертера. Этот метод можно использовать для эффективного сравнения любых двоичных файлов, например ZIP, JAR и других архивов. Используя инструмент unzip -l (или аналогичный) вместо pdf2html, можно просмотреть, какие пути были добавлены в коммит или удалены из него по сравнению с другим коммитом. Утилиту exiv2 можно использовать для просмотра изменений метаданных, например размеров изображения. Существуют инструменты для преобразования .odf, .doc и других форматов документов в простой текст. В крайнем случае команда может работать с двоичными файлами, для которых формальных конвертеров не существует.

Сравнение файлов: файл git diff

В команде git diff можно указать явный путь к файлу. Если в git diff указан путь к файлу, выполняется сравнение этого файла. Более подробно этот процесс показан на примерах ниже.

git diff HEAD ./path/to/file

В этом примере выполняется сравнение для файла ./path/to/file . Рабочий каталог сравнивается с разделом проиндексированных файлов и выводятся изменения, которые еще не были проиндексированы. По умолчанию git diff выполняет сравнение с HEAD . Если опустить аргумент HEAD в приведенном выше примере и выполнить команду git diff ./path/to/file , это не повлияет на результат.

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

При вызове git diff с использованием параметра —cached сравниваются проиндексированные изменения и локальный репозиторий. Параметр —cached синонимичен параметру —staged .

Сравнение всех изменений

При вызове git diff без указания пути к файлу выполняется сравнение всех изменений в репозитории. Команды из приведенных выше примеров можно вызвать без аргумента ./path/to/file и получить аналогичные результаты для всех файлов в локальном репозитории.

Изменения после последнего коммита

По умолчанию команда git diff выводит все неподтвержденные изменения, внесенные после последнего коммита.

git diff

Сравнение файлов в двух коммитах

Команде git diff можно передать ссылки на коммиты Git для сравнения. Возможные варианты ссылок — HEAD , теги и имена веток. Каждый коммит в Git имеет идентификатор, который можно получить с помощью команды git log . Этот идентификатор коммита тоже можно передать в 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

Сравнение веток

Сравнение двух веток

Ветки сравниваются с помощью команды git diff точно так же, как любые другие входные ссылки.

git diff branch1..other-feature-branch

В этом примере демонстрируется оператор точка. Две точки показывают, что сравниваются последние коммиты двух веток. Тот же результат можно получить, если опустить точки и поставить пробел между именами веток. Кроме того, можно использовать трехточечный оператор:

git diff branch1. other-feature-branch

Оператор «три точки» инициирует сравнение путем изменения первого параметра ввода branch1 . Параметр branch1 преобразуется в ссылку на родительский коммит, общий для двух входных объектов сравнения. Это общий предок ветки branch1 и другой функциональной ветки. Последний параметр ввода остается без изменений — это последний коммит другой функциональной ветки.

Сравнение файлов из двух веток

Чтобы сравнить конкретный файл в разных ветках, передайте команде git diff путь к файлу в качестве третьего аргумента.

git diff main new_branch ./diff_test.txt

Резюме

На этой странице были рассмотрены процесс сравнения в Git и команда git diff . Мы объяснили, как читать вывод команды git diff и различные виды выходных данных. В примерах было показано, как изменить выходные данные git diff с помощью подсвечивания и использования цветов. Кроме того, были рассмотрены различные стратегии сравнения, например сравнение файлов в разных ветках и конкретных коммитах. Наряду с git diff также использовались команды git log и git checkout .

Анализ сделанных изменений — Введение в Git

Во время разработки программистам часто приходится останавливаться и анализировать изменения, которые они сделали с последнего коммита.

Потребность смотреть изменения становится очевидной, если представить себе, что такое работа над реальным проектом. Как правило, это тысячи строк кода, сотни файлов, десятки часов работы над одной задачей.

Потратив даже несколько часов в таком проекте, очень сложно вспомнить, что и где менялось, а что еще осталось поменять. Чтобы было проще, нужно анализировать изменения, о чем мы поговорим в этом уроке.

Как анализировать изменения

Анализировать изменения важно даже в небольших проектах. Прямо сейчас во время разработки этого курса изменилось несколько файлов и git status выглядит так:

(use "git restore --staged . " to unstage) modified: 300-working-directory/README.md Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) modified: 100-intro/README.md modified: 250-github/README.md modified: 300-working-directory/README.md modified: 300-working-directory/spec.yml modified: 350-changes/README.md 

Попробуем воспроизвести подобную ситуацию в нашем проекте. Выполним следующий код в репозитории hexlet-git:

echo 'new line' >> INFO.md echo 'Hello, Hexlet! How are you?' > README.md git status Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) modified: INFO.md modified: README.md no changes added to commit (use "git add" and/or "git commit -a") 

Изменились оба файла. В один файл мы добавили строчку, в другом — заменили. Как теперь посмотреть эти изменения?

Для этого в Git есть команда git diff , которая показывает разницу между тем, что было и что стало:

--git a/INFO.md b/INFO.md index d5225f8..40f51f1 100644 --- a/INFO.md +++ b/INFO.md @@ -1 +1,2 @@ git is awesome! +new line diff --git a/README.md b/README.md index ffe7ece..00fd294 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -Hello, Hexlet! +Hello, Hexlet! How are you? 

Вывод команды поначалу может смутить. Здесь довольно много служебных данных, за которыми уже идут изменения.

Вывод git diff содержит не файлы целиком, а именно те строки, которые изменились — и иногда строки вокруг измененных для удобства анализа.

Слева от строк ставится:

  • Знак — , если строка была удалена
  • Знак + , если строка была добавлена

Сама команда не просто выводит на экран разницу между файлами, но и запускает пейджер — специальную программу, которая позволяет перемещаться по выводу и искать внутри него нужные данные. Для этого используются клавиши:

  • f — перемещение вниз
  • b или u — перемещение вверх
  • q — или выход из режима просмотра

По умолчанию команда git diff показывает изменения только для тех модифицированных файлов, которые еще не были добавлены в индекс. Подразумевается, что добавленные в индекс файлы смотреть не нужно, ведь мы их уже подготовили к коммиту. Но лучше еще раз увидеть эти изменения и все проверить. Для этого нужно запустить команду git diff с флагом —staged :

# Выведет все изменения, сделанные в рабочей директории # которые были добавлены в индекс git diff --staged 

В целом, git diff — команда, которую нужно обязательно запускать перед каждым коммитом. С ее помощью можно проанализировать добавляемые изменения и исправить возможные ошибки, ведь иногда программисты случайно добавляют в коммит то, что туда не должно попасть.

Самостоятельная работа
  1. Выполните все шаги из урока
  2. Сделайте коммит с сообщением add new content
  3. Залейте изменения на GitHub

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Команды, важные в работе с Git

Git – это распределенная система контроля версий — каждый разработчик создает на своем компьютере отдельный, полноценный репозиторий. Git поддерживают несколько крупных репозиториев – GitHub, SourceForge, BitBucket — удобно использовать один из них в качестве основного хранилища для корпоративных проектов.
После создания удалённого репозитория для проекта на одном из вышеперечисленных сервисов (или ином соответствующим образом настроенном сервере), каждый разработчик должен получить свою локальную копию содержимого удалённого репозитория. Для этого:
1. Создаем на локальной машине новую директорию для проекта project_name, переходим в нее.
2. Выполняем следующую команду:

$ git clone [email protected]:devlabuser/sharp.git ./ 

“./” в конце команды означает, что создать репозиторий нужно в текущей директории. Если не указать эти символы, внутри текущей папки будет создана директория c именем репозитория, в которой и будет находиться содержимое склонированного проекта.

Создание коммитов

После того, как внесены нужные изменения в файлы или код, список всех измененных и добавленных файлов можно просмотреть командой:

$ git status 

Чтобы подготовить файлы к фиксации в коммите (говоря на языке Git — проиндексировать изменения), добавляем в него файлы командой:

$ git add -A 

Чтобы проиндексировать изменения одного конкретного файла, нужно указать его имя:

$ git add EDITEDFILE 

Выполняем коммит:

$ git commit -m "Комментарий к коммиту" 

Заливаем изменения, зафиксированные последним коммитом, на сервер:

$ git push 

Если над проектом работает кто-то помимо Вас, и он успел загрузить на сервер свои коммиты до Вас, то перед тем, как использовать команду git push, Вам необходимо использовать команду git pull, чтобы привести состояние вашего локального репозитория в соответствие с удалённым (иначе команда git push при выполнении выдаст ошибку).
В ходе этого процесса слияния Ваших локальных и удалённых данных могут возникнуть противоречия между ними (например, если Вы и Ваш коллега изменили одну и ту же часть одного и того же файла по-разному) — система git сама уведомит Вас, в каких файлах произошли неразрешимые для самой системы конфликты, и Вы сможете их надлежащим образом отредактировать.
Но что если конфликтный файл не подлежит редактированию — например, если он бинарный? Чтобы решить такой конфликт, надо просто выбрать – какая версия файла будет использоваться — ваша или из вливаемых данных. Чтобы использовать свой вариант файла, вводим команды:

$ git checkout --ours binary.dat $ git add binary.dat 

Если мы выбираем версию из вливаемой ветки:

$ git checkout --theirs binary.dat $ git add binary.dat 

“ours” – от английского “наш”, “theirs” – от английского “их”.
Вышесказанное приводит нас к выводу — коммиты следует делать по возможности чаще, регулярно сверяясь с тем, как протекает работа у коллег — если коммиты будут содержать минимум изменений, локализовывать и устранять ошибки и конфликты придётся в меньшем количестве кода и файлов.

Просмотр изменений

git log — просмотр логов. Выводимый результат:

$ git log commit 9a452d9cdbdb57e7e4f2b09f8ce2f776cd56657a Author: DevLab User [email protected] Date: Wed Jul 31 18:35:47 2013 +0400 first commit commit d528335724dfc15461996ed9d44d74f23ce6a075 Author: DevLab User user@mail.ru Date: Wed Jul 31 06:24:57 2013 -0700 Initial commit 

Вывод данных о каждом коммите в одну строку:

$ git log --pretty=oneline 9a452d9cdbdb57e7e4f2b09f8ce2f776cd56657a first commit d528335724dfc15461996ed9d44d74f23ce6a075 Initial commit 

Поиск по ключевому слову в комментариях к коммиту:

$ git log | grep -e "first" first commit 

Вывести сгруппированные по авторам коммиты:

$ git shortlog Desperado (5): aaaaa safddav safdgdf index sas 

Статистика изменения файлов, вроде числа измененных файлов, внесенных в них строк, удаленных файлов вызывается ключом —stat:

$ git log --stat commit b1c953d9e214980a487e4a0fb5389d45fef0d90e Author: Mihail Dzantiev Date: Thu May 5 13:51:00 2016 +0300 keywords app/controllers/ControllerBase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 4a215611a8bb9d4dcb46f4edb0d2c0bbea4c41e3 Author: Mihail Dzantiev Date: Thu May 5 11:28:11 2016 +0300 local changes app/controllers/ControllerBase.php | 2 +- app/views/about/index.volt | 12 +--- app/views/inc/about.volt | 2 +- app/views/inc/about_index.volt | 2 +- app/views/index/index.volt | 2 +- element | 2 +- public/html/css/about.css | 2 +- public/html/css/main-block.css | 2 +- public/html/css/style.css | 2 +- public/html/scss/about.scss | 2 +- public/html/scss/main-block.scss | 2 +- public/sitemap.xml | 252 +++++++++++++++++++++++++++++++++++++++++++---------------------------------- 18 files changed, 154 insertions(+), 130 deletions(-) commit 741cd866d76b081bd43441fd84a7c5209c0bf5e8 Author: root Date: Thu May 5 11:04:12 2016 +0300 server side app/views/blog/post.volt | 2 ++ element | 2 +- 

Команда git show позволяет просмотреть, какие именно изменения произошли в указанном коммите:

$ git show 99452d955bdb57e7e4f2b09f8ce2fbb6cd56377a commit 99452d955bdb57e7e4f2b09f8ce2fbb6cd56377a Author: DevLab User Date: Wed Jul 31 18:35:47 2013 +0400 first commit diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..4add785 --- /dev/null +++ b/readme.txt @@ -0,0 +1 @@ +Text \ No newline at end of file 

Чтобы увидеть, что же вы изменили, но пока не проиндексировали, наберите git diff (эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса):

$ git diff diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ebb991..643e24f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,8 @@ branch directly, things can get messy. Please include a nice description of your changes when you submit your PR; if we have to read the whole diff to figure out why you're contributing in the first place, you're less likely to get feedback and have your change -merged in. +merged in. Also, split your changes into comprehensive chunks if you patch is +longer than a dozen lines. 

Если вы хотите посмотреть, что вы проиндексировали и что войдёт в следующий коммит, вы можете выполнить git diff —staged (эта команда сравнивает ваши индексированные изменения с последним коммитом):

$ git diff --staged diff --git a/README b/README new file mode 100644 index 0000000..03902a1 --- /dev/null +++ b/README @@ -0,0 +1 @@ +My Project 

Также можно просмотреть разницу между любыми двумя коммитами (git diff commit1 commit2):

$ git diff b1c953d 4a21561 diff --git a/app/controllers/ControllerBase.php b/app/controllers/ControllerBase.php index 84eacea..117c1dc 100755 --- a/app/controllers/ControllerBase.php +++ b/app/controllers/ControllerBase.php @@ -54,7 +54,7 @@ class ControllerBase extends Controller // SEO $this->view->setVar('title','Hot Pie – Осетинские пироги'); $this->view->setVar('description', 'Заказ Осетинских пирогов с доставкой по Москве'); - $this->view->setVar('keywords', 'осетинские пироги Москва'); + $this->view->setVar('keywords', 'осетинские пироги доставка'); // Статичные страницы // всегда контент 

Показать, что за файлы менялись в коммите:

$ git diff-tree --no-commit-id --name-only -r commit1 .DS_Store app/views/about/index.volt element public/html/css/about.css public/html/css/style.css 

Ветки

Любой проект предусматривает множество контекстов, в которых ведётся работа; каждый компонент, исправление ошибки, эксперимент или альтернатива вашему продукту — это своего рода контекст сам по себе. Его можно рассматривать как отдельный «тематический раздел», чётко отграниченный от других таких разделов. Если такие тематические разделы не отделять друг от друга с помощью веток, неизбежно повышается риск появления проблем. Перемешивание тематических разделов в одном контексте:
1. Усложняет контроль над ними — а при большом количестве тематических разделов он становится почти невозможным;
2. Усложняет откат какого-либо действия, которое привело к ошибке, так как оно уже смешалось со слишком большим количеством других вещей;
3. Не вдохновляет людей на эксперименты, так как после смешивания экспериментального кода с основным кодом проекта становится очень трудно извлечь его из репозитория.
Чтобы создать новую ветку на основании текущего состояния, нужно выбрать имя и выполнить одну команду в командной строке. Допустим, мы хотим начать работу над новой версией контактной формы, следовательно создадим новую ветку под названием «contact-form»:

$ git branch contact-form 

Если выполнить команду git branch не указывая имя ветки, мы получим список всех веток, которые есть на локальном репозитории (а ключ -v предоставит немного дополнительной информации):

$ git branch -v contact-form b1c953d keywords * master b1c953d [ahead 1, behind 1] keywords 

Маленькая звёздочка напротив ветки под названием «master» обозначает ветку, которая на данный момент является активной. Итак, перед тем, как начать работу над нашей контактной формой, нужно сделать её активным контекстом:

$ git checkout contact-form 

Теперь эта ветка — наш текущий рабочий контекст (на языке Git это называется «HEAD branch»). Все изменения и любой коммит, совершённые с текущего момента, будут влиять только на этот контекст — остальные контексты останутся нетронутыми. Чтобы переключить контекст на другую ветку, мы просто снова используем команду git checkout.
Чтобы добавить изменения из одной ветки в другую, можно выполнить их «слияние» в текущий рабочий контекст. Например, если мы некоторое время работали над нашим компонентом «contact-form», а теперь желаем добавить эти изменения в ветку «master», то нам нужно переключиться на эту ветку и выполнить git merge:

$ git checkout master $ git merge contact-form 

Полезная возможность для выяснения состояния веток состоит в том, чтобы составить список только тех веток, которые Вы слили (или не слили) в текущую ветку. Для этих целей в Git’е есть опции —merged и —no-merged. Чтобы посмотреть те ветки, которые Вы уже слили с текущей, выполните команду git branch —merged:

$ git branch --merged iss53 * master 

Вывод всех локальных и удалённых веток:

$ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/master 

Получить имя текущей ветки:

$ git rev-parse --abbrev-ref HEAD master 

Переименовать текущую ветку:

git branch -m new-branch-name 

Одну конкретную ветку можно склонировать из удалённого репозитория:

git clone -b branch-name --single-branch https://github.com/user/repo.git 

«Черновики» изменений

Часто возникает такая ситуация, что пока Вы работаете над частью своего проекта, всё находится в беспорядочном состоянии, а Вам нужно переключить ветки, чтобы немного поработать над чем-то другим. Проблема в том, что Вы не хотите делать коммит с наполовину доделанной работой только для того, чтобы позже можно было вернуться в это же состояние. Ответ на эту проблему — команда git stash.
Эта команда поглощает грязное состояние рабочего каталога, то есть изменённые отслеживаемые файлы и изменения в индексе, и сохраняет их в стек незавершённых изменений, которые потом в любое время можно снова применить:

$ git stash Saved working directory and index state \ "WIP on master: 049d078 added the index file" HEAD is now at 049d078 added the index file (To restore them type "git stash apply") 

Тепеь Ваш рабочий каталог чист:

$ git status On branch master nothing to commit, working directory clean 

В данный момент Вы легко можете переключить ветки и поработать где-то ещё — ваши изменения сохранены в стеке. Чтобы посмотреть, что у Вас есть припрятанного, выполните git stash list:

$ git stash list stash@: WIP on master: 049d078 added the index file stash@: WIP on master: c264051. Revert "added file_size" stash@: WIP on master: 21d80a5. added number to log 

В нашем случае две «заначки» были сделаны ранее, так что у вас теперь три разных припрятанных работы. Вы можете снова применить ту, которую только что спрятали, с помощью команды, показанной в справке в выводе первоначальной команды stash: git stash apply. Если вы хотите применить одну из старых заначек, можете сделать это, указав её имя так: git stash apply stash@ . Если не указывать конкретный стек, Git будет подразумевать, что вы хотите применить последнюю спрятанную работу:

$ git stash apply On branch master Changes not staged for commit: (use "git add <file>. " to update what will be committed) modified: index.html modified: lib/simplegit.rb 

Как видите, Git восстановил изменения в файлах, которые былиы отменены командой stash. В нашем случае у Вас был чистый рабочий каталог, когда вы восстанавливали спрятанные изменения, и к тому же вы делали это на той же ветке, на которой находились во время прятанья. Но наличие чистого рабочего каталога и применение на той же ветке не обязательны для git stash apply. Вы можете спрятать изменения на одной ветке, переключиться позже на другую ветку и попытаться восстановить изменения. У вас в рабочем каталоге также могут быть изменённые и недокоммиченные файлы во время применения спрятанного — Git выдаст вам конфликты слияния, если что-то уже не может быть применено чисто.
Изменения в файлах были восстановлены, но проиндексированные файлы — нет. Чтобы воостановить и их, выполнить команду git stash apply с опцией —index.
Всё, что делает опция apply — это пытается применить спрятанную работу — то, что вы спрятали, всё ещё будет находиться в стеке. Чтобы удалить спрятанное, выполните git stash drop с именем «заначки», которую нужно удалить:

$ git stash list stash@: WIP on master: 049d078 added the index file stash@: WIP on master: c264051. Revert "added file_size" stash@: WIP on master: 21d80a5. added number to log $ git stash drop stash@ Dropped stash@ (364e91f3f268f0900bc3ee613f9f733e82aaed43) 

Также можно выполнить git stash pop, чтобы применить спрятанные изменения и сразу же удалить их из стека, а просто для удаления всех «черновиков» — git stash clear.
При некоторых сценариях использования, может понадобиться применить спрятанные изменения, поработать, а потом отменить изменения, внесённые командой stash apply — это делается так:

$ git stash show -p stash@ | git apply -R 

Опять же, если не указывать параметр для stash, Git подразумевает то, что было спрятано последним:

$ git stash show -p | git apply -R 

Исправление изменений

Очень легко забыть указать какое-либо изменение или допустить опечатку в комментарии к коммиту. С помощью ключа —amend к команде git commit Git даёт вам возможность изменить самый последний коммит — например, если вы забыли добавить какое-либо изменение и допустили опечатку в названии коммита, это можно легко исправить:

$ git add some-changed-files $ git commit --amend -m "Комментарий, в этот раз без опечаток" 

Помните: коммит, который уже был отослан в удалённый репозиторий, изменять нельзя!
Изменения, для которых не был совершён коммит, называются «локальными». Сброс этих изменений может потребоваться, когда текущий результат вашей работы оказался… скажем, хуже чем то, что было раньше. В Git можно отменить локальные изменения и начать сначала с последней версии вашего проекта, для которой был совершён коммит.
Если вы хотите восстановить один файл, можете использовать команду git checkout (команда нам уже знакома, но в текущем случае она выполняет иные функции):

$ git checkout -- restore-file 

Если день совсем не задался, и требуется сбросить все локальные изменения и восстановить весь проект целиком, то делаем так (это заменит все файлы в вашей рабочей директории на последнюю редакцию, для которой был совершён коммит):

$ git reset --hard HEAD 

Будьте осторожны с этими операциями: поскольку локальные изменения не были зарегистрированы в репозитории, после сброса восстановить их будет невозможно!
Отменить можно не только локальные изменения, но и некоторые коммиты, когда это необходимо — например, если они привели к ошибке в коде.
Команда git reset позволяет буквально вернуться в прошлое — Вы сообщаете к какой версии вы хотите вернуться, и она восстанавливает именно это состояние — отменяя все изменения, которые были осуществлены после этой временной точки. Нужно указать ей коммит, к которому вы хотите вернуться:

$ git reset --hard 2be18d9 

Чтобы восстановить просто самый свежий коммит:

$ git reset --hard HEAD 

Опция -—hard — это наиболее простой и чистый способ, однако она также удаляет все локальные изменения в вашей рабочей директории. Так что перед её применением, убедитесь, что у Вас нет локальных изменений, которые лучше было бы сохранить.
Команда git revert используется в другой ситуации. Представьте, что у Вас есть коммит, от которого Вы бы хотели избавиться, однако коммиты, совершённые после него, все ещё актуальны. В таком случае нельзя использовать команду git reset, потому что она отменит и эти, более поздние коммиты.
Команда revert позволяет откатить последствия от одного конкретного коммита. Она не удаляет какие-либо коммиты, в отличие от git reset — вместо этого она вносит изменения, противоположные изменениям в коммите, который подлежит откату. Например, если вы удалили строку кода, revert добавит точно такую же строку.
Чтобы откатить коммит 2be18d9:

$ git revert 2be18d9 

Чтобы откатить самый свежий коммит:

$ git revert HEAD 

Поиск ошибок

Часто возникает ситуация вида — Вы уверены, что два дня назад всё работало, а теперь — не работает — например, мы знаем, что текущая версия (с меткой «2.0») приведена в негодность, также мы знаем, что несколько коммитов назад (в версии «1.9»), всё было нормально.
Этой информации уже достаточно, чтобы начать охоту на ошибки с помощью git bisect:

$ git bisect start $ git bisect bad $ git bisect good v1.9 

После начала процесса мы сообщили Git, что наш текущий коммит содержит ошибку и обозначили его как «плохой» («bad»). Затем мы сообщили Git какой из предыдущих коммитов точно был рабочим (в качестве параметра для команды git bisect good).
Git после этого восстанавливает проект посередине между заведомо хорошим и плохим состоянием:

Теперь мы проводим тестирование этой версии, чтобы определить является ли это состояние рабочим или же уже содержит ошибку. Когда мы это выясним, снова сообщаем Git о результате с помощью git bisect bad или git bisect good.
Предположим, что мы определили этот коммит тоже как «плохой» — значит, ошибка была допущена раньше — и Git опять сократит количество коммитов под вопросом:

Таким образом Вы очень быстро определите, где именно была допущена ошибка. Когда это произойдёт, выполните git bisect reset, чтобы закончить охоту за ошибкой и восстановить исходное состояние проекта.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *