Перейти к основному содержимому
06ФУНДАМЕНТ · ГЛАВА 06Git: первый коммит#1

Git: первый коммит

Прочитано 0%Квизы 0/6Тренажёры 0/6Уровень 1 · Новичок

Зачем это нужно

Представь: ты три часа доводил проект до рабочего состояния, потом «немного улучшил» — и всё сломалось. Как вернуть версию, которая работала? Копии project_final_2_НОВЫЙ в соседней папке — путь к хаосу: рано или поздно забудешь, какая из пяти копий рабочая. Для этого придумали систему контроля версий (version control system) — программу, которая запоминает состояния проекта в виде цепочки снимков, а не просто хранит файлы как есть. Самая распространённая такая система — Git. Каждый снимок называется коммитом (commit): что изменилось, когда и зачем. Можно листать историю, сравнивать версии и откатываться к любой точке — как чекпоинты в игре, только сохраняешь их сам и когда захочешь.

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

Как это было
Git написал Линус Торвальдс в апреле 2005 года, когда у разработчиков ядра Linux внезапно отобрали бесплатную лицензию на систему контроля версий BitKeeper. Линус сел за замену 3 апреля, уже 7 апреля git хранил историю самого себя, а через две недели, 16 апреля, Линус перевёл на него разработку всего ядра Linux. Слово «git» на британском сленге значит «мерзавец» — Линус шутил, что называет проекты в честь себя.

Сквозной пример: репозиторий шаг за шагом

Дальше — один сквозной проект my-app, который мы проведём через весь цикл: от пустой папки до нескольких коммитов в истории. Все команды и вывод терминала ниже — не выдумка и не сокращение: это дословный вывод настоящего Git (версия 2.43, та, что ставится по умолчанию из apt на свежей Ubuntu 24.04 — ровно такая машина ждёт тебя на чемпионате), полученный в чистом окружении именно для этой главы. Открой свой терминал и повторяй команды по ходу чтения — тренажёр в браузере команды Git не выполняет, поэтому весь текст ниже спроектирован так, чтобы можно было разобрать вывод не запуская его: с интерактивными разборами, самопроверками и печатью вручную.

git init: из папки в репозиторий

Создадим папку проекта и превратим её в репозиторий:

mkdir my-app
cd my-app
git init

Вот дословный ответ терминала:

hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/student/my-app/.git/

Это не ошибка — все строки hint: (подсказка) Git печатает при первом init на свежей машине, и дальше в этой сессии их уже не будет. Смысл подсказки: у первой ветки (про ветки — подробно в следующей главе) нужно какое-то имя, версии Git до недавнего времени называли её master, сейчас многие сервисы (например GitHub) по умолчанию заводят main — и Git честно предупреждает, что имя зависит от настройки init.defaultBranch, а не зашито намертво. На чемпионатской машине или на своём компьютере название может оказаться любым из этих — дальше в главе используется master, ровно то имя, которое дал этот git init без дополнительных настроек.

Разберём финальную строку — ту, что реально сообщает результат:

Нажми на часть выражения

Внешне в проекте как будто ничего не изменилось — но появилась скрытая папка .git (имя, начинающееся с точки, ls без флагов не показывает). Проверим:

ls -la
total 12
drwxr-xr-x 3 student student 4096 Aug 31 19:22 .
drwxr-xr-x 3 student student 4096 Aug 31 19:22 ..
drwxr-xr-x 7 student student 4096 Aug 31 19:22 .git

Заглянем внутрь — это и есть весь механизм Git, который отныне будет следить за проектом:

ls .git
HEAD
branches
config
description
hooks
info
objects
refs

Пока не нужно запоминать назначение каждого файла — со временем это станет привычным, а пока держи короткую расшифровку главного:

  • HEAD — указатель на текущую ветку: файл cat .git/HEAD содержит одну строку ref: refs/heads/master — «сейчас мы смотрим на ветку master».
  • objects — сюда Git реально складывает содержимое коммитов, файлов и снимков в сжатом виде; это и есть история.
  • refs — папка с указателями на ветки и метки: куда именно в objects смотрит имя master.
  • config — настройки конкретно этого репозитория (не путать с глобальными настройками пользователя, о них — в разделе про коммит).
  • hooks, info, description, branches — служебные вещи для продвинутых сценариев, в этой главе не понадобятся.
GIT · КУДА СМОТРИТ HEADHEADrefs/heads/masterфайл с одним hash внутриref: refs/heads/master — HEAD указывает на ветку, ветка указывает на коммитновый коммит — сдвигается ветка, а вместе с ней и HEAD
HEAD не хранит коммит напрямую: он смотрит на имя текущей ветки, а уже она указывает на конкретный коммит.
Важно

Трогать .git руками не нужно никогда — вся работа с ним идёт только через команды git .... Если эту папку удалить, репозиторий исчезнет насовсем, а сами файлы проекта (main.py и другие) останутся на месте, просто без истории.

Отвечено вопросов: 0 из 4
Что делает команда git init?
Где физически хранится история коммитов после git init?
git init выводит подсказку про имя ветки master/main с текстом hint:. О чём она?
Что покажет ls -la в только что созданной папке my-app сразу после git init, если до этого папка была пустой?
Отвечено верно: 0 из 4

git status: читаем построчно

git status — самая частая команда цикла: она отвечает на вопрос «что вообще сейчас происходит с проектом». Спросим у пустого репозитория:

git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Три смысловых блока: на какой ветке мы находимся, сколько коммитов уже есть (пока ни одного), и что делать дальше. Теперь создадим файл и спросим снова:

printf 'print("Привет, чемпионат!")\n' > main.py
git status
On branch master

No commits yet

Untracked files:
(use "git add <file>..." to include in what will be committed)
main.py

nothing added to commit but untracked files present (use "git add" to track)

Разберём блок про сам файл — почему он выглядит именно так:

Нажми на часть выражения

И последняя строка блока — короткое резюме всего вывода:

Нажми на часть выражения
Отвечено вопросов: 0 из 4
Что означает untracked в выводе git status?
В самом низу вывода git status стоит строка вида (use "git add <file>..." to include in what will be committed). Зачем Git её печатает?
Табуляция перед именем файла в выводе git status (\tmain.py) — что это?
Пустой репозиторий сразу после git init — что покажет git status в разделе про коммиты?
Отвечено верно: 0 из 4

git add: коробка для посылки

Git не коммитит всё подряд автоматически — и это осознанное решение, а не недоработка. Представь, что отправляешь посылку: на столе перед тобой десять разных вещей, но в коробку идут не все сразу, а только те, что ты сам туда положил. Коробка — это индекс (index), его ещё называют staging area («зона подготовки», «корзина для коммита»): промежуточное место между рабочей папкой (working directory — где ты правишь файлы как обычно) и историей коммитов. Команда git add кладёт конкретный файл в эту коробку; ничего в историю при этом ещё не попадает — снимок делает только следующая команда, git commit.

GIT · ТРИ ЗОНЫgit addcommitрабочая папкаиндекс (staging)история коммитов
Три зоны Git: git add переносит файл из рабочей папки в индекс (staging), git commit делает снимок и добавляет его в историю.

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

Нажми на часть выражения
git add main.py
git status
On branch master

No commits yet

Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: main.py
Нажми на часть выражения

Обрати внимание: main.py переехал из раздела Untracked files в раздел Changes to be committed — сам файл на диске никак не изменился, поменялось только то, что о нём знает Git.

Цель: скорость ≥ 100 зн/мин, точность ≥ 90%

git add main.py
Отвечено вопросов: 0 из 4
В метафоре с посылкой — чему соответствует «коробка» (staging area, индекс)?
Что реально меняется на диске в момент git add main.py?
Как git rm --cached main.py отличается от обычного удаления файла?
После git add main.py файл появился в разделе Changes to be committed со статусом new file. Что означает new file именно здесь?
Отвечено верно: 0 из 4

git commit: что внутри коммита

Прежде чем делать первый снимок, Git попросит представиться — один раз на весь компьютер, а не на каждый коммит. Имя и почта станут подписью под твоими коммитами, и без них коммит просто не получится создать:

git config --global user.name "Ivan Petrov"
git config --global user.email "ivan@example.com"

--global значит «на этом компьютере для всех репозиториев», а не только для my-app; без флага настройка подействовала бы только на текущий проект. Теперь можно сделать сам коммит:

Нажми на часть выражения
git commit -m "add main screen"
[master (root-commit) 5ecfe79] add main screen
1 file changed, 1 insertion(+)
create mode 100644 main.py
Нажми на часть выражения

Коммит готов — но что внутри него на самом деле, кроме файла? Спросим Git напрямую:

git log -1
commit 5ecfe795b9c92b2285b6869710e7e54f0b7f52a8
Author: Ivan Petrov <ivan@example.com>
Date: Mon Aug 31 19:22:49 2026 +0000

add main screen

Вот и ответ на вопрос «что внутри коммита» — ровно четыре вещи, и три из них программист не пишет руками:

Нажми на часть выражения
Интересный факт

Так что из «hash, author, date, message» руками пишется только последнее — сообщение. Остальное Git берёт из настроек и системных часов и вычисляет сам.

GIT · ЧТО ВНУТРИ КОММИТАhash5ecfe79…Git вычисляет самauthorIvan Petrovиз git configdate31 Aug 19:22системные часыmessage"add main screen"пишешь ты самиз четырёх полей коммита руками задаётся только одно
Четыре поля коммита: hash, author и date вычисляет и подставляет сам Git, message — единственное, что пишешь ты.
Отвечено вопросов: 0 из 4
Что делает флаг -m у git commit?
В выводе git log -1 есть строка commit 5ecfe795b9c92b2285b6869710e7e54f0b7f52a8. Что это?
Коммит содержит hash, author, date и message. Что из этого программист задаёт руками при самом коммите?
Зачем git config --global user.name/user.email настраивают один раз, а не при каждом коммите?
Отвечено верно: 0 из 4

git log --oneline: история одной строкой

Изменим main.py и повторим цикл — теперь уже быстрее, раз шаги знакомы:

printf 'print("Привет, чемпионат!")\nprint("Удачи!")\n' > main.py
git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: main.py

no changes added to commit (use "git add" and/or "git commit -a")

Статус файла теперь modified — «изменён»: main.py уже был закоммичен раньше, поэтому Git сравнивает текущее содержимое с тем, что лежит в последнем коммите, а не считает файл незнакомым, как в самый первый раз. Посмотреть, что именно изменилось, можно командой git diff:

git diff
diff --git a/main.py b/main.py
index af6a7c4..6eb4577 100644
--- a/main.py
+++ b/main.py
@@ -1 +1,2 @@
print("Привет, чемпионат!")
+print("Удачи!")

Строка со знаком + в начале — то, что добавилось; строка без знака — то, что осталось как было. Добавим и закоммитим:

git add main.py
git commit -m "add welcome message"
[master 58da937] add welcome message
1 file changed, 1 insertion(+)

Обрати внимание — у этого коммита в квадратных скобках уже нет пометки (root-commit): она бывает только у самого первого коммита в истории. Теперь посмотрим на всю цепочку сразу:

Нажми на часть выражения
git log --oneline
58da937 add welcome message
5ecfe79 add main screen

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

поменял файлы → git status (что изменилось) → git add (что закоммитить) → git commit -m "..." (зафиксировать снимок) → снова поменял файлы.

А git log --oneline — команда, к которой возвращаются в любой момент, чтобы охватить взглядом весь пройденный путь.

Отвечено вопросов: 0 из 4
Чем git log --oneline отличается от обычного git log?
git log --oneline печатает коммиты сверху вниз. В каком порядке?
В каком порядке идёт базовый цикл работы с Git?
Нужно ли запускать git init перед каждым новым коммитом?
Отвечено верно: 0 из 4

Теперь в обратную сторону: перед тобой три знакомых вывода git status — по каждому определи, что именно попадёт в снимок, если набрать git commit прямо сейчас.

Вывод 1 из 3
В свежем репозитории только что создали main.py:
Кликни строки, которые попадут в коммит при git commit прямо сейчас, и нажми «Проверить». Если не попадёт ничего — жми «Проверить» сразу.

Хорошие сообщения коммитов

Сообщение — это письмо себе и команде: через неделю по git log нужно понять, что происходило, не открывая сами файлы. Мировая привычка — писать по-английски, по формуле глагол в начальной форме + что сделано, как будто отдаёшь команду: add main screen, fix score reset, remove unused file, update readme.

Совет

Плохие сообщения — fix, asdf, изменения 2, последняя версия точно — через неделю не скажут вообще ничего ни тебе, ни эксперту на чемпионате. Хватает трёх-шести слов, зато честных и по делу.

Проверь формулу на живых ситуациях: набирай сообщение — чек-лист правил загорается прямо по мере набора.

Задание 1 из 3
Ты дописал в main.py строку, которая спрашивает имя пользователя.
Опиши этот коммит одним сообщением — так, чтобы загорелись все четыре правила:
git commit -m ""0/50
  • · начинается с глагола-действия по-английски: add, fix, remove, update…
  • · после глагола сказано, что именно сделано (не просто «fix» или «123»)
  • · не длиннее 50 символов
  • · без точки в конце

.gitignore: что в историю не берём

Не всё в папке проекта заслуживает места в истории: черновики, временные файлы, кэш вроде __pycache__ — мусор, который создаётся сам и никому не нужен в репозитории. Заведём черновик и посмотрим, как он засоряет вывод:

echo "черновик" > draft.txt
git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
draft.txt

nothing added to commit but untracked files present (use "git add" to track)

Чтобы git status не показывал такие файлы снова и снова, в корне проекта заводят файл с особым именем .gitignore и перечисляют в нём шаблоны того, что нужно игнорировать — по одному на строку:

echo "draft.txt" > .gitignore
git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore

nothing added to commit but untracked files present (use "git add" to track)

draft.txt пропал из списка — Git теперь его полностью игнорирует, зато появился сам .gitignore: он-то как раз обычный файл, и его нужно закоммитить, чтобы правило подействовало не только у тебя, но и у всей команды:

.GITIGNORE · ЧТО ОТСЕИВАЕТСЯв папке на дискеmain.pydraft.txt.gitignoreфильтр по шаблонамgit statusвидит main.pydraft.txtотфильтрован — Git молчитсам файл никуда не делся с диска — просто Git перестал его показывать
Файлы из .gitignore не удаляются с диска — просто git status перестаёт их показывать, как будто их для Git не существует.
git add .gitignore
git commit -m "add gitignore for drafts"
git status
[master 920228d] add gitignore for drafts
1 file changed, 1 insertion(+)
create mode 100644 .gitignore
On branch master
nothing to commit, working tree clean

nothing to commit, working tree clean — «нечего коммитить, рабочая папка чистая» — это финальный, самый спокойный ответ git status: все файлы либо закоммичены, либо явно игнорируются, ничего не потеряно и ничего не забыто. При этом draft.txt никуда не делся — он спокойно лежит рядом на диске, просто Git про него больше не напоминает.

Шаблоны в .gitignore можно расширять: звёздочка означает «любое имя», поэтому *.log закрывает сразу все файлы логов, а __pycache__/ — целую папку:

__pycache__/
*.log
draft.txt

Типичные ошибки

Четыре сообщения, с которыми рано или поздно сталкивается каждый. Тексты ниже — дословный вывод настоящего Git, проверенный вживую специально для этой главы, а не пересказ по памяти.

1. Забыл git add

Изменил файл, но не добавил его в индекс, — и пробуешь коммитить сразу:

git commit -m "add welcome message"
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: main.py

no changes added to commit (use "git add" and/or "git commit -a")

Перевод: «изменения не подготовлены к коммиту... ничего не добавлено к коммиту». Причина: git commit фиксирует только то, что уже лежит в индексе (коробке из раздела про git add); индекс пуст — коммитить нечего, и вместо создания коммита Git просто ещё раз показывает status. Как починить: git add main.py, затем повторить git commit -m "...".

2. Пустой -m

git commit -m ""
Aborting commit due to empty commit message.

Перевод: «прерываю коммит из-за пустого сообщения». Причина: Git намеренно запрещает коммит без единого слова о том, что изменилось, — такое сообщение бесполезно для истории. Как починить: повторить команду с непустым текстом после -m, например git commit -m "add welcome message".

3. not a git repository

Команда Git запущена вне репозитория — например, в /tmp, где нет ни своей папки .git, ни родительской с ней:

git status
fatal: not a git repository (or any of the parent directories): .git

Перевод: «фатальная ошибка: это не git-репозиторий (и ни одна из родительских папок тоже)». Причина: Git ищет папку .git в текущем каталоге и поднимается вверх по родительским, пока не найдёт хоть одну, — и нигде её не находит. Как починить: перейти в папку своего проекта (cd my-app) командой cd, либо, если репозитория ещё не существует вовсе, создать его через git init.

4. Author unknown (identity не настроена)

На свежей машине, где git config --global user.name/user.email ещё ни разу не выполнялись, первый же git commit останавливается:

git commit -m "add main screen"
Author identity unknown

*** Please tell me who you are.

Run

git config --global user.email "you@example.com"
git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'root@d5508f32bf9c.(none)')

Перевод: «личность автора неизвестна... расскажи мне, кто ты... не удалось автоматически определить почтовый адрес». Часть после got — то, что Git попытался подобрать сам по имени пользователя и имени компьютера (здесь это техническое имя контейнера, где проверялась эта глава; на реальной машине там будет твой логин и hostname) — и не смог. Причина: Git подписывает каждый коммит автором, а без user.name/user.email подписывать попросту нечем. Как починить: ровно то, что уже делали в разделе про git commit, — git config --global user.name "Имя Фамилия" и git config --global user.email "почта@пример.ру", один раз на весь компьютер.

Отвечено вопросов: 0 из 4
git commit -m "..." ничего не закоммитил и снова показал вывод, похожий на git status. В чём частая причина?
Команда git commit -m "" отвечает Aborting commit due to empty commit message. Что произошло с коммитом?
git status отвечает fatal: not a git repository (or any of the parent directories): .git. Что произошло?
При первом коммите на новой машине Git отвечает Author identity unknown ... fatal: unable to auto-detect email address. Как починить?
Отвечено верно: 0 из 4

Символы и команды главы

Шпаргалка по всему, что встретилось в этой главе. Вернись сюда, если забудешь, что делает та или иная команда или флаг.

Команда / символЧто делаетПример
git initсоздаёт репозиторий: пустую папку .git внутри текущего каталогаgit init
.gitскрытая служебная папка — само хранилище истории проектаls -la
git statusпоказывает состояние файлов: untracked / modified / уже в индексеgit status
git add <file>кладёт файл в индекс (staging area) — готовит к коммитуgit add main.py
git commit -m "..."создаёт коммит — снимок из того, что лежит в индексеgit commit -m "add main screen"
-mфлаг message: сообщение коммита прямо в команде, без редактораgit commit -m "fix bug"
git config --globalзадаёт имя и почту автора для всех репозиториев на компьютереgit config --global user.name "..."
git logпоказывает историю коммитов от нового к старомуgit log -1
--onelineфлаг: каждый коммит — одна строка (сокращённый hash + сообщение)git log --oneline
hashуникальный SHA-1-отпечаток коммита; для чтения сокращают до 7 символов5ecfe79
(root-commit)пометка первого коммита в истории — у него нет родителя[master (root-commit) 5ecfe79]
.gitignoreфайл со списком шаблонов, которые Git должен игнорировать*.log

Слова главы

repository
1 / 8

Потренируйся печатать

Команды Git ты будешь набирать десятки раз в день — пусть пальцы запомнят их раньше головы.

Цель: скорость ≥ 110 зн/мин, точность ≥ 90%

git status
клавиша ``клавиша 11клавиша 22клавиша 33клавиша 44клавиша 55клавиша 66клавиша 77клавиша 88клавиша 99клавиша 00клавиша --клавиша ==клавиша ⌫клавиша TabTabклавиша QQклавиша WWклавиша EEклавиша RRклавиша TTклавиша YYклавиша UUклавиша IIклавиша OOклавиша PPклавиша [[клавиша ]]клавиша \\клавиша Caps LockCaps Lockклавиша AAклавиша SSклавиша DDклавиша FFклавиша GGклавиша HHклавиша JJклавиша KKклавиша LLклавиша ;;клавиша ''клавиша EnterEnterклавиша ShiftShiftклавиша ZZклавиша XXклавиша CCклавиша VVклавиша BBклавиша NNклавиша MMклавиша ,,клавиша ..клавиша //клавиша ShiftShiftклавиша CtrlCtrlклавиша WinWinклавиша AltAltклавиша ПробелПробелклавиша AltAltклавиша WinWinклавиша MenuMenuклавиша CtrlCtrl
следующая: G — указательный левой руки

Теперь связка подлиннее — ровно то, что происходит после каждого маленького изменения в файле:

Цель: скорость ≥ 130 зн/мин, точность ≥ 90%

git add main.py && git commit -m "add welcome message"
Углубиться

Три состояния файла. Git различает рабочую папку (working directory — где ты правишь файлы как обычно), индекс (staging area — что отобрано в следующий снимок) и саму историю коммитов. git add двигает изменения из первой во вторую, git commit — из второй в третью. Когда вывод git status перестанет удивлять, значит, эта тройка уложилась в голове окончательно.

Коммит — не «сохранение файла». Git хранит не отдельные файлы построчно, а снимки всего проекта целиком на момент коммита, и каждый коммит знает своего родителя — предыдущий коммит в цепочке (кроме самого первого, root-commit, у него родителя нет). Так и получается история, по которой можно ходить назад. Hash из git log — это не случайный номер, а результат хеш-функции SHA-1 от содержимого коммита: файлов, автора, даты, сообщения и hash родителя. Поэтому подделать или незаметно изменить старый коммит невозможно — изменится hash, и это будет видно.

git add . — точка означает «всё из текущей папки». Быстро, но коварно: в коммит залетает всё подряд, включая случайный мусор вроде черновиков или временных файлов. Пока учишься, добавляй файлы по именам — заодно будешь глазами видеть, что именно кладёшь в снимок.

Дальше по теме:

Куда дальше: проверенные ресурсы

  • git-init — man-страница команды init: все флаги и режимы из первых рук.
  • git-commit — man-страница команды commit: -m, -a, --amend и остальные флаги.
  • github/gitignore — готовые шаблоны .gitignore под любой язык и инструмент: скопируй нужный вместо того, чтобы выдумывать свой с нуля.

  • Видео и материалы сообщества — ниже — ролики по теме и ссылки от студентов и преподавателей смотри в самом низу страницы.

Прежде чем браться за челлендж, прогони весь цикл в симуляторе: перед тобой виртуальный репозиторий с уже лежащим в папке README.md — доведи его от git init до цепочки минимум из трёх коммитов и посмотри на графе, как растёт история.

Квест «Прогони цикл init → add → commit и собери минимум три коммита»: сделай минимум три коммита
В папке уже лежит README.md. Доведи его до первого коммита: git init → git add → git commit. Чтобы сделать следующий коммит, файл надо сначала изменить — здесь это команда edit: например edit README.md Мой проект на Kotlin. Полный список команд — help.
project $
Команды: git config · init · status · add · commit -m · diff · log · branch · switch · merge · restore · edit <файл> <текст> — изменить файл · help · clear
Файлы проекта
README.mdне добавлен
Мой первый проект
История коммитов
история пуста — сделай первый коммит
Как это устроено под капотом
Внутри — не настоящий git, а его модель в памяти: коммит — объект с хешем, сообщением, списком родителей и полным снимком файлов, а ветка — просто указатель на хеш коммита. Команды меняют этот граф объектов, при этом формулировки вывода сняты с настоящего git 2.x, чтобы глаз привыкал к реальному терминалу. Граф справа рисуется по тем же объектам: SVG-кружки — коммиты, линии — связи «родитель — потомок», а merge с расхождением создаёт коммит с двумя родителями, ровно как в настоящем git. Push и pull в режиме с origin — упрощённая пересылка недостающих коммитов между двумя такими репозиториями.

Челлендж ⭐

Продолжи проект my-app из главы серией из трёх коммитов — каждый решает одну задачу и подписан по-английски по формуле «глагол + что»:

  1. Допиши в main.py строку, которая спрашивает имя пользователя. Закоммить.
  2. Создай в папке ещё один черновик, например notes.txt, и добейся, чтобы git status перестал его показывать — так, как делали с draft.txt в разделе про .gitignore. То, что для этого понадобилось изменить, — закоммить.
  3. Исправь текст приветствия в первой строке main.py. Закоммить.

⭐ Ступень со звёздочкой. После трёх коммитов запусти git log --oneline и убедись, что видишь ровно шесть строк (три коммита из главы — add main screen, add welcome message, add gitignore for drafts — плюс три новых). Затем ответь себе вслух, не подглядывая в терминал: у какого из шести коммитов в полном git log (без --oneline) была бы пометка (root-commit) — и почему именно у него, а не у остальных пяти.

Проверка: git log --oneline показывает минимум шесть коммитов, git status отвечает nothing to commit, working tree clean — при этом notes.txt спокойно лежит в папке, просто не в истории.

Решение (сначала попробуй сам)
# 1. дописали в main.py строку input("Как тебя зовут? ")
git add main.py
git commit -m "add name question"

# 2. создали notes.txt, затем дописали его в .gitignore
git status # notes.txt виден как untracked
echo "notes.txt" >> .gitignore
git status # notes.txt исчез из списка, изменился .gitignore
git add .gitignore
git commit -m "ignore notes file"

# 3. поправили текст в print(...)
git add main.py
git commit -m "fix greeting text"

git log --oneline # шесть строк

Ответ на ⭐: пометка (root-commit) была бы у самого первого коммита add main screen — единственного во всей цепочке, у которого нет родителя, потому что это вообще первый снимок, сделанный в этом репозитории. У всех остальных пяти коммитов родитель есть — предыдущий коммит по цепочке, поэтому пометка появляется у него ровно один раз за всю историю репозитория.

Обрати внимание на второй шаг: коммитим именно .gitignore, а не сам черновик — notes.txt в историю не попадает никогда, как и draft.txt раньше.

Сводная проверка по всей главе: 8 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.

Что должен уметь

  • Объяснять своими словами, что такое репозиторий (repository), коммит (commit) и зачем проекту вообще нужна история изменений.
  • Прогонять полный цикл git initgit statusgit addgit commit -m "..."git log --oneline без подсказок, вслепую понимая, что делает каждый шаг.
  • Читать вывод git status построчно: отличать untracked-файл от modified, понимать, что уже лежит в индексе, и что означает nothing to commit, working tree clean.
  • Объяснять метафору staging area как коробки для посылки — и почему git add не коммитит файл сразу.
  • Перечислить, из чего состоит коммит (hash, author, date, message) и назвать, что из этого задаёт человек, а что — сам Git.
  • Писать сообщение коммита по-английски по формуле «глагол + что сделано» — коротким и честным.
  • Прятать мусорные файлы от Git через .gitignore и объяснять, почему сам .gitignore при этом коммитят.
  • Узнавать по точному тексту четыре типичные ошибки — забытый git add, пустой -m, not a git repository, неизвестного автора (git config) — и знать, как чинить каждую.

Комментарии

Комментарии появятся после настройки. Нужен аккаунт GitHub — вход прямо в виджете выше.