Анализ сделанных изменений — Введение в 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 — команда, которую нужно обязательно запускать перед каждым коммитом. С ее помощью можно проанализировать добавляемые изменения и исправить возможные ошибки, ведь иногда программисты случайно добавляют в коммит то, что туда не должно попасть.
Самостоятельная работа
- Выполните все шаги из урока
- Сделайте коммит с сообщением add new content
- Залейте изменения на GitHub
![]()
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Отмена изменений в рабочей директории — Введение в Git
Одна из ключевых возможностей Git — это откат любых сделанных изменений буквально одной командой. Такое практически невозможно сделать без использования системы контроля версий — только если помнить все изменения наизусть. В этом уроке мы поговорим про откат изменений, которые сделаны в рабочей директории, но еще не попали в коммит.
Отдельно отметим, что откат незакоммиченных изменений безвозвратен. Не существует никакой физической возможности получить эти изменения обратно, поэтому будьте крайне осторожны.
Неотслеживаемые файлы
Это самая простая ситуация. Представьте, что вы добавили новые файлы в репозиторий и поняли, что они вам не нужны.
В этом случае можно выполнить очистку:
mkdir one touch two git status On branch main Your branch is up to date with 'origin/main'. # Пустые директории в Git не добавляются в принципе # Физически директория one находится в рабочей директории, # но при этом ее нет в Git, поэтому Git игнорирует ее Untracked files: (use "git add . " to include in what will be committed) two # Выполняем очистку. Команда удалит все незакоммиченные изменения # -f – force, -d – directory git clean -fd Removing one/ Removing two
Забавный факт: про эту команду знает не так много программистов. Используя ее, вы можете удивить даже опытных коллег.
Измененные файлы в рабочей директории
Для отмены изменений в таких файлах используется команда git restore . Причем Git сам напоминает об этом при проверке статуса:
echo 'new text' > INFO.md git status On branch main Your branch is up to date with 'origin/main'. 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 # Отменяем git restore INFO.md
Изменения, подготовленные к коммиту
С файлами, подготовленными к коммиту, можно поступить по-разному. Первый вариант — отменить изменения совсем, второй — отменить только индексацию, не изменяя файлы в рабочей директории. Второе полезно в том случае, если изменения нужны, но мы не хотим их коммитить сейчас:
echo 'new text' > INFO.md git add INFO.md git status On branch main Your branch is up to date with 'origin/main'. Changes to be committed: (use "git restore --staged . " to unstage) modified: INFO.md
И здесь снова помогает Git. При выводе статуса он показывает нужную команду для перевода изменений в рабочую директорию:
--staged INFO.md git status On branch main Your branch is up to date with 'origin/main'. 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
Теперь, если нужно, можно выполнить git restore и окончательно отменить изменения в выбранных файлах:
Самостоятельная работа
- Выполните все шаги из урока
![]()
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Об обучении на Хекслете
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Урок «Как эффективно учиться на Хекслете»
- Вебинар « Как самостоятельно учиться »
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
git stash
Команда git stash позволяет на время «сдать в архив» (или отложить) изменения, сделанные в рабочей копии, чтобы вы могли применить их позже. Откладывание изменений полезно, если вам необходимо переключить контекст и вы пока не готовы к созданию коммита.
- git stash
- Откладывание кода
- Применение отложенных изменений
- Откладывание неотслеживаемых или игнорируемых файлов
- Управление несколькими наборами отложенных изменений
- Просмотр различий между наборами отложенных изменений
- Частичное откладывание изменений
- Создание ветки из отложенных изменений
- Удаление отложенных изменений
- Принцип работы команды git stash
Откладывание кода
Команда git stash сохраняет неподтвержденные изменения (индексированные и неиндексированные) в отдельном хранилище, чтобы вы могли вернуться к ним позже. Затем происходит откат до исходной рабочей копии. Например:
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
nothing to commit, working tree clean
Связанные материалы
git branch
СМ. РЕШЕНИЕ
Изучите Git с помощью Bitbucket Cloud
Теперь вы можете вносить изменения, создавать новые коммиты, переключаться между ветками и выполнять другие операции Git. По необходимости отложенные изменения можно будет применить позже.
Отложенные изменения сохраняются в локальном репозитории Git и не передаются на сервер при выполнении команды push.
Применение отложенных изменений
Чтобы применить ранее отложенные изменения, воспользуйтесь командой git stash pop :
$ git status
On branch main
nothing to commit, working tree clean
$ git stash pop
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Dropped refs/stash@ (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)При извлечении отложенных изменений они удаляются из набора и применяются к рабочей копии.
Вы также можете применить изменения к рабочей копии, не удаляя их из набора отложенных изменений. Для этого воспользуйтесь командой git stash apply :
$ git stash apply
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.htmlЭто полезно, если вам нужно применить одни и те же отложенные изменения к нескольким веткам.
Теперь вы умеете выполнять основные операции с отложенными изменениями. Однако необходимо помнить о следующей особенности команды git stash : по умолчанию Git не создает отложенные изменения для неотслеживаемых или игнорируемых файлов.
Откладывание неотслеживаемых или игнорируемых файлов
По умолчанию команда git stash создает следующие отложенные изменения:
- изменения, добавленные в раздел проиндексированных файлов (индексированные изменения);
- изменения в файлах, отслеживаемых Git в настоящее время (неиндексированные изменения).
При этом следующие файлы отложены не будут:
- новые файлы в рабочей копии, которые еще не были проиндексированы;
- игнорируемые файлы.
Поэтому если в приведенный выше пример добавить третий файл — неиндексированный (т. е. без выполнения команды git add ), при выполнении команды git stash этот файл не будет отложен.
$ script.js
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Untracked files:
script.js
$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
Untracked files:
script.jsЗапуск git stash с параметром -u (или —include-untracked ) позволяет отложить неотслеживаемые файлы:
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Untracked files:
script.js
$ git stash -u
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
nothing to commit, working tree cleanМожно также отложить изменения, внесенные в игнорируемые файлы. Для этого используйте параметр -a (или —all ) при запуске команды git stash .
Управление несколькими наборами отложенных изменений
Вы можете создать несколько наборов отложенных изменений. Команду git stash можно выполнить несколько раз, после чего можно будет просмотреть список созданных наборов с помощью команды git stash list . По умолчанию отложенные изменения имеют пометку WIP (незавершенная работа) наверху ветки или коммита, в которых они были отложены. Возможно, со временем вам будет трудно вспомнить содержимое каждого набора:
$ git stash list
stash@: WIP on main: 5002d47 our new homepage
stash@: WIP on main: 5002d47 our new homepage
stash@: WIP on main: 5002d47 our new homepageРекомендуем добавлять к отложенным изменениям описание в качестве подсказки. Для этого используется команда git stash save «сообщение» :
$ git stash save "add style to our site"
Saved working directory and index state On main: add style to our site
HEAD is now at 5002d47 our new homepage
$ git stash list
stash@: On main: add style to our site
stash@: WIP on main: 5002d47 our new homepage
stash@: WIP on main: 5002d47 our new homepageПо умолчанию команда git stash pop применяет последний набор отложенных изменений: stash@
Если вам нужно применить определенный набор ранее отложенных изменений, укажите его идентификатор в качестве последнего аргумента. Это можно сделать так:
$ git stash pop stash@
Просмотр различий между наборами отложенных изменений
Выполните команду git stash show , чтобы просмотреть сводные данные по набору отложенных изменений:
$ git stash show
index.html | 1 +
style.css | 3 +++
2 files changed, 4 insertions(+)Или укажите параметр -p (или —patch ), чтобы просмотреть разницу между наборами изменений:
$ git stash show -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* + text-decoration: blink;
+>
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+Частичное откладывание изменений
При желании можно отложить один файл, несколько файлов или отдельные изменения в файлах. Если передать команде git stash параметр -p (или —patch ), она будет выполняться для каждого измененного участка кода в рабочей копии, запрашивая подтверждение на откладывание:
$ git stash -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* + text-decoration: blink;
+>
Stash this hunk [y,n,q,a,d,/,e,?]? y
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+
Stash this hunk [y,n,q,a,d,/,e,?]? nНажмите ?, чтобы увидеть полный список команд для работы с участками кода. Часто используются следующие команды:
Команда
Описание
искать участок кода по регулярному выражению
не откладывать участок кода
выйти (все выбранные участки будут отложены)
разделить участок кода на меньшие части
отложить участок кода
Специальной команды для прерывания не предусмотрено, но прекратить процесс откладывания можно, нажав CTRL-C (сигнал SIGINT).
Создание ветки из отложенных изменений
Если изменения в ветке отличаются от отложенных изменений, операции извлечения или применения последних могут привести к конфликтам. Вместо этого вы можете создать новую ветку с помощью команды git stash branch и применить отложенные изменения к ней. Это можно сделать так:
$ git stash branch add-stylesheet stash@
Switched to a new branch 'add-stylesheet'
On branch add-stylesheet
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Dropped refs/stash@ (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)Новая ветка создается на основе коммита, изменения в котором использовались при создании набора. Затем к этой ветке применяются извлеченные изменения.
Удаление отложенных изменений
Удалить определенный набор отложенных изменений можно с помощью команды git stash drop :
$ git stash drop stash@
Dropped stash@ (17e2697fd8251df6163117cb3d58c1f62a5e7cdb)Следующая команда удаляет все наборы отложенных изменений:
$ git stash clearПринцип работы команды git stash
Если вы просто хотели получить информацию о том, как использовать команду git stash , то дальше читать необязательно. Однако если вам необходимо узнать о принципах работы Git (и git stash ) — продолжайте чтение!
Наборы отложенных изменений шифруются в репозитории в виде коммитов. Специальная ссылка в .git/refs/stash указывает на последний созданный набор отложенных изменений, а для ранее созданных наборов изменений используются ссылки из журнала ссылок stash . Именно поэтому для просмотра наборов отложенных изменений используется ссылка stash@ : при этом вы ссылаетесь на n-ю запись в журнале ссылок stash . Поскольку набор отложенных изменений представляет собой обычный коммит, его можно просмотреть с помощью команды git log :
В зависимости от отложенных элементов выполнение команды git stash создает два или три новых коммита. На приведенной выше схеме создаются следующие коммиты:
- stash@ — новый коммит для хранения отслеживаемых файлов, которые находились в рабочей копии при запуске команды git stash ;
- первый родитель stash@ — существующий коммит, который при запуске команды git stash находился в ветке, на которую указывал HEAD;
- второй родитель stash@ — новый коммит, выступавший в роли индекса при запуске команды git stash ;
- третий родитель stash@ — новый коммит, представляющий неотслеживаемые файлы, которые находились в рабочей копии при запуске команды git stash . Третий родитель создается, только если:
- рабочая копия действительно содержит неотслеживаемые файлы, и
- вы указали параметр —include-untracked или —all при вызове команды git stash .
Ниже показано, как команда git stash шифрует рабочий каталог и раздел проиндексированных файлов в виде коммитов:
- Перед откладыванием изменений в рабочем каталоге могут находиться изменения отслеживаемых, неотслеживаемых и игнорируемых файлов. Часть этих изменений также может быть проиндексирована в разделе проиндексированных файлов.
- При выполнении команды git stash все изменения отслеживаемых файлов шифруются в виде двух новых коммитов в ориентированном ациклическом графе. При этом один коммит используется для неиндексированных изменений, а другой — для индексированных изменений, добавленных в раздел проиндексированных файлов. Для указания на них используется специальная ссылка refs/stash .
- Параметр —include-untracked позволяет также зашифровать все изменения неотслеживаемых файлов в виде дополнительного коммита.
- Параметр —all позволяет включить изменения игнорируемых файлов в один коммит с изменениями неотслеживаемых файлов.
При выполнении команды git stash pop изменения из описанных выше коммитов применяются к рабочей копии и разделу проиндексированных файлов, извлеченный коммит удаляется из журнала ссылок на отложенные изменения, и ссылки в журнале сдвигаются. Извлеченные коммиты не удаляются сразу, но помечаются к удалению в будущем при сборе мусора.
Как в GIT откатить состояние файла до состояния в stage?
Есть проект, в котором я создал файл foo.py . Сделал в нем изменения и применил команду git add foo.py . Запустив команду git status вижу это(пусть будет ситуация 1):
On branch master Initial commit Changes to be committed: (use "git rm --cached . " to unstage) new file: foo.pyЯ не стал делать коммит, т.е. выполнять команду git commit и захотел немного улучшить решение. Другими словами сейчас мой проект находится в таком состоянии(пусть будет ситуация 2):
On branch master Initial commit Changes to be committed: (use "git rm --cached . " to unstage) new file: foo.py Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: foo.pyКак мне сейчас из ситуации 2 прийти к ситуации 1? То есть убрать изменения из файла foo.py , как будто после ситуации 1 я ничего больше не писал.