Командная строка и Git: как разработчики работают с кодом
До сих пор мы говорили о самом коде: переменные, циклы, функции, классы. Но у профессии есть вторая половина, о которой в учебниках пишут меньше, — быт разработчика. Как он запускает программу, как хранит её версии, как отдаёт код коллегам и как возвращает вчерашний рабочий вариант, если сегодня всё сломал.
Этим бытом заведуют два инструмента: терминал и Git. Оба выглядят пугающе — чёрное окно и непонятные слова. Оба на самом деле проще, чем кажутся, потому что делают вещи, которые вы и так делаете мышкой, просто другим способом.
Спокойно: сегодня мы не будем ничего ломать. Все команды, которые могут удалить что-то важное, я отмечу отдельно.
Часть первая: терминал
Что это вообще такое
Терминал (он же командная строка, консоль, shell) — это программа, в которой вы управляете компьютером не мышкой, а текстом. Вы печатаете название действия, жмёте Enter, компьютер выполняет и печатает ответ.
Всё, что вы делаете мышкой, можно сделать в терминале: открыть папку, создать файл, скопировать, переименовать, удалить, запустить программу.
Аналогия. Проводник (Explorer, Finder) — это витрина супермаркета: вы ходите между полками и берёте что видите. Терминал — это разговор с продавцом за прилавком: вы говорите словами, что вам нужно, и получаете это, не обходя зал.
Где аналогия ломается. Продавец переспросит, если вы сказали непонятное. Терминал — нет: он либо выполнит команду буквально, либо ответит короткой ошибкой. Он не догадывается о ваших намерениях. Это его главное свойство: буквальность.
Зачем он нужен, если есть мышка
Честный ответ: для простых вещей мышка удобнее, и никто не создаёт папки в терминале из принципа. Терминал выигрывает в четырёх ситуациях:
- Повторяемость. Команду можно записать, отправить коллеге, вставить в инструкцию. Скриншот с движениями мышки так не перешлёшь.
- Массовость. Переименовать 500 файлов мышкой — вечер. Одной командой — секунда.
- Удалённые машины. Сервер в дата-центре не имеет экрана и мышки. Единственный способ им управлять — текст.
- Инструменты разработчика. Git, установщики библиотек, сборщики проектов, запуск тестов — почти все они управляются командами. Мышка к ним просто не прилагается.
Как его открыть
- Windows. Нажмите Пуск и наберите
PowerShell— откройте «Windows PowerShell». Это современный вариант; старыйcmdтоже существует, но команды в нём другие. - macOS. Cmd + пробел, наберите
ТерминалилиTerminal. - Linux. Ctrl + Alt + T в большинстве систем.
- Внутри VS Code (мы ставили его в статье Первая программа): меню Terminal → New Terminal. Удобнее всего: терминал открывается сразу в папке проекта.
Откроется окно с чем-то вроде C:\Users\Anna> или anna@laptop:~$. Это приглашение (prompt) — знак, что компьютер готов слушать. Печатать его не нужно, он появляется сам.
Из чего состоит команда
Разберём по частям:
- Команда — что сделать. Обычно короткое английское слово или сокращение:
ls— от list,cd— от change directory,mkdir— от make directory. - Ключи (или флаги, опции) — как именно сделать. Начинаются с дефиса:
-l,-a. Порядок не важен, несколько ключей можно слить:-laто же самое, что-l -a. - Аргумент — над чем сделать: имя файла или папки. Если не указан, команда обычно работает с текущей папкой.
Части разделяются пробелами. Поэтому имя файла с пробелом внутри нужно брать в кавычки: "мои заметки.txt". Это ошибка номер один у новичков — команда получает два аргумента вместо одного и жалуется на несуществующий файл.
Где я нахожусь: путь
Терминал всегда находится внутри какой-то папки. Это называется текущий каталог (current directory), и все команды по умолчанию действуют именно в нём.
Файлы и папки на компьютере устроены как дерево: папки внутри папок. Путь — это маршрут по этому дереву.
(домашняя папка)"] --> P["projects"] ROOT --> D["Документы"] P --> C["calc"] P --> S["shop"] C --> F1["main.py"] C --> F2["README.md"] S --> F3["app.py"] style C fill:#3d5a80,color:#fff style ROOT fill:#5c6b73,color:#fff
Если мы сейчас находимся в папке calc (она подсвечена), то:
- абсолютный путь к
main.py—/home/anna/projects/calc/main.py. Он начинается от корня и работает откуда угодно; - относительный путь — просто
main.py. Он отсчитывается от текущей папки; ..означает «папка на уровень выше». Путь../shop/app.py— подняться вprojectsи спуститься вshop;.означает «текущая папка».
На Windows пути пишутся через обратный слэш и с буквой диска: C:\Users\Anna\projects\calc. На macOS и Linux — через прямой слэш: /home/anna/projects/calc. Символ ~ (тильда) на macOS и Linux — сокращение для вашей домашней папки.
Первые команды: навигация
Откройте терминал и попробуйте по очереди. Ничего не сломается — все эти команды только смотрят.
pwd
pwd (print working directory) печатает, где вы находитесь. Ожидаемый вывод:
/home/anna
В PowerShell на Windows pwd тоже работает и напечатает что-то вроде C:\Users\Anna.
ls
ls (list) показывает содержимое текущей папки:
Документы Загрузки Изображения projects
Добавим ключи:
ls -la
-l — подробный вид (размер, дата, права доступа), -a — показать в том числе скрытые файлы, имена которых начинаются с точки. В PowerShell тот же смысл у команды ls -Force или dir.
cd projects
cd (change directory) — перейти в папку. Проверьте pwd — путь изменился.
cd ..
Вернулись на уровень выше. Просто cd без аргументов (или cd ~) вернёт вас в домашнюю папку из любого места.
Два приёма, которые экономят часы:
- Tab — автодополнение. Наберите
cd projи нажмите Tab: терминал допишетprojectsсам. Это не только быстрее — это ещё и защита от опечаток. - Стрелка вверх — предыдущая команда. Нажмите несколько раз, чтобы пролистать историю. Повторять длинную команду руками не нужно никогда.
Создание, копирование, удаление
mkdir myproject # создать папку myproject
cd myproject # зайти в неё
Создать пустой файл:
touch notes.txt # macOS / Linux
В PowerShell на Windows:
New-Item notes.txt
Дальше — команды, одинаковые на всех системах (в PowerShell они работают как псевдонимы):
cp notes.txt notes-copy.txt # копировать (copy)
mv notes.txt zametki.txt # переименовать или переместить (move)
rm zametki.txt # удалить (remove)
Внимание.
rmудаляет мимо корзины и без вопросов. Восстановить нельзя. Особенно опасна связкаrm -rf— она удаляет папку со всем содержимым молча. Никогда не вставляйте команду сrm -rfиз интернета, не прочитав её целиком. Пока вы учитесь, удаляйте файлы мышкой — это совершенно нормально.
Запуск программы из терминала
Ради этого всё и затевалось. Создайте в папке myproject файл hello.py (можно в VS Code) с таким содержимым:
# Простая программа, которую мы запустим из терминала
name = input("Как вас зовут? ") # ждём ввод пользователя
print(f"Привет, {name}!") # f-строка подставляет значение переменной
Теперь в терминале, находясь в папке с файлом:
python hello.py
Вывод:
Как вас зовут? Анна
Привет, Анна!
Что здесь произошло: python — это команда (программа-интерпретатор), hello.py — аргумент, то есть файл, который ей скормили. Интерпретатор прочитал файл сверху вниз и выполнил.
Если вместо этого вы увидели:
python: command not found
или
'python' is not recognized as an internal or external command
— значит, терминал не знает, где лежит Python. Попробуйте python3 вместо python (частая ситуация на macOS и Linux). Если не помогло — Python установлен без галочки «Add to PATH», и его нужно переустановить с этой галочкой; мы разбирали это в статье Первая программа.
А если увидели:
python: can't open file 'hello.py': [Errno 2] No such file or directory
— Python запустился, но файла в текущей папке нет. Дословно: «не могу открыть файл hello.py: нет такого файла или каталога». Проверьте pwd и ls: скорее всего, вы находитесь не в той папке. Это не поломка, это просто «вы не там».
Программа, которая принимает аргументы
Раз мы уже в терминале, покажу приятный трюк: программа может получать аргументы из команды — ровно так же, как их получают ls или cp.
import sys # модуль sys даёт доступ к тому, как программу запустили
# sys.argv — список: [имя_файла, первый аргумент, второй аргумент, ...]
if len(sys.argv) < 2: # len — длина списка
print("Использование: python greet.py ИМЯ")
else:
name = sys.argv[1] # [0] — это сам greet.py, [1] — первый аргумент
print(f"Привет, {name}!")
Сохраните как greet.py и запустите двумя способами:
python greet.py Анна
Привет, Анна!
python greet.py
Использование: python greet.py ИМЯ
Вот и вся магия «настоящих» консольных программ: они читают sys.argv и ведут себя по-разному. Списки мы разбирали в статье Списки, словари и множества — sys.argv самый обычный список строк.
Ещё три вещи, которые надо знать
- Ctrl + C — прервать выполнение. Если программа зависла в бесконечном цикле или ждёт чего-то вечно, это ваша кнопка спасения.
- Ctrl + L или команда
clear(clsв PowerShell) — очистить экран. Ничего не удаляет, просто убирает визуальный шум. exit— закрыть терминал.
Часть вторая: Git
Проблема, которую он решает
Знакомая картина:
курсовая.docx
курсовая_финал.docx
курсовая_финал2.docx
курсовая_финал_ИСПРАВЛЕННЫЙ.docx
курсовая_финал_ИСПРАВЛЕННЫЙ_вот_этот.docx
С кодом то же самое, только хуже: вы правите работающую программу, ломаете её, и не помните, что именно поменяли двадцать минут назад. Отменить (Ctrl + Z) уже нельзя — редактор закрывали. Вчерашней рабочей версии нет.
Git — это программа, которая ведёт историю изменений вашего проекта. Она умеет:
- сохранять снимки состояния проекта в любой момент (снимок называется коммит);
- показывать, что именно изменилось между снимками, вплоть до строки;
- возвращать проект к любому прошлому снимку;
- вести несколько параллельных версий проекта (ветки) и потом сливать их;
- объединять работу нескольких человек над одними и теми же файлами.
Аналогия. Git — как режим «История версий» в Google Документах, только вы сами решаете, когда сделать точку сохранения, и подписываете каждую своими словами.
Где аналогия ломается. Google сохраняет автоматически и хранит линейную ленту. Git сохраняет только по вашей команде и хранит дерево: от одной точки может идти несколько параллельных линий развития, которые потом снова сходятся. Эта возможность и делает Git инструментом командной работы, а не просто резервным копированием.
Git — это не GitHub
Путаница, на которой спотыкаются все. Запомните разницу сразу:
- Git — программа на вашем компьютере. Работает без интернета. Хранит историю в скрытой папке
.gitвнутри проекта. - GitHub (а также GitLab, Bitbucket) — сайт, куда можно выложить копию этой истории: чтобы был бэкап, чтобы показать код другим, чтобы работать вместе.
Git можно использовать вообще без GitHub. GitHub без Git — нельзя.
Четыре места, где живёт ваш код
Это центральная идея Git. Пока она не уложится, команды будут казаться случайным набором слов.
Разберём словами:
- Рабочая папка — обычные файлы, которые вы видите и правите в редакторе. Здесь всё как всегда.
- Индекс (staging area, «сцена») — черновик следующего снимка. Вы кладёте сюда те изменения, которые хотите сохранить вместе.
- История (локальный репозиторий) — цепочка сделанных коммитов в папке
.git. Отсюда уже ничего не пропадает. - Сервер (GitHub) — копия истории в интернете.
Зачем нужен индекс? Самый частый вопрос новичка. Представьте: вы за час поправили опечатку в README и заодно переписали функцию расчёта. Это два разных дела, и хочется два разных коммита с разными описаниями. Индекс позволяет сказать: «сейчас сохрани только README, функцию сохраним отдельно».
Аналогия. Индекс — это коробка, в которую вы складываете вещи перед тем, как заклеить её скотчем и подписать. git add — положить вещь в коробку. git commit — заклеить и подписать. Вещи из комнаты (рабочей папки) при этом никуда не деваются.
Установка и первая настройка
Проверьте, установлен ли Git:
git --version
git version 2.43.0
Если команда не найдена — скачайте с git-scm.com/downloads и установите со всеми настройками по умолчанию.
Дальше — единственная настройка, которую делают один раз в жизни. Git подписывает каждый коммит вашим именем, поэтому он должен его знать:
git config --global user.name "Anna Ivanova"
git config --global user.email "anna@example.com"
--global значит «для всех проектов на этом компьютере». Почта попадёт в историю проекта и будет видна всем, кто её откроет, — если это вас смущает, GitHub позволяет использовать специальный служебный адрес вида имя@users.noreply.github.com.
Первый репозиторий
Репозиторий — это папка проекта, за которой Git следит. Создадим её:
mkdir calc
cd calc
git init
Initialized empty Git repository in /home/anna/calc/.git/
Внутри появилась скрытая папка .git — вся история будет храниться там. Удалите её — и проект превратится в обычную папку без истории. Больше туда заглядывать не нужно.
Создайте в папке файл calc.py:
def add(a, b):
"""Складывает два числа и возвращает результат."""
return a + b
print(add(2, 3)) # ожидаемый вывод: 5
Теперь главная команда, которую вы будете набирать чаще всех остальных:
git status
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
calc.py
nothing added to commit but untracked files present (use "git add" to track)
Переведём дословно, потому что Git всегда подсказывает следующий шаг:
On branch main— вы на веткеmain(о ветках чуть ниже);No commits yet— снимков ещё нет;Untracked files— «неотслеживаемые файлы»: Git видитcalc.py, но пока не следит за ним;- в скобках — прямая подсказка, что делать дальше:
use "git add".
Git — редкая программа, которая почти всегда пишет в ответе, какую команду набрать следующей. Читайте эти скобки, там ответ.
Первый коммит
git add calc.py
Изменение положено в индекс. Проверьте git status — файл теперь в разделе Changes to be committed.
git commit -m "Добавил функцию сложения"
[main (root-commit) 8f3a1c2] Добавил функцию сложения
1 file changed, 5 insertions(+)
create mode 100644 calc.py
Ключ -m (message) задаёт сообщение коммита — описание того, что вы сделали. Без -m Git откроет текстовый редактор и будет ждать, что вы напишете сообщение там (и новички часто застревают в редакторе vim; если это случилось, нажмите Esc, наберите :q! и Enter, чтобы выйти).
8f3a1c2 — начало хеша коммита, его уникального идентификатора. По нему коммит можно найти в истории.
Посмотрим историю:
git log --oneline
8f3a1c2 Добавил функцию сложения
Сделайте ещё одно изменение — добавьте в calc.py функцию вычитания — и повторите цикл:
git add calc.py
git commit -m "Добавил функцию вычитания"
git log --oneline
b1d4e77 Добавил функцию вычитания
8f3a1c2 Добавил функцию сложения
Вот и всё. Этот цикл изменил → add → commit вы будете повторять всю жизнь.
Жизненный цикл файла
Каждый файл в репозитории находится в одном из состояний, и команды переводят его между ними:
Понимая эту схему, вы понимаете 90% повседневного Git.
Что писать в сообщении коммита
Сообщение читают люди — включая вас через полгода. Правила простые:
- Плохо:
фикс,изменения,asdf,работа. Через месяц это ничего не скажет. - Хорошо:
Исправил деление на ноль в calc.py,Добавил чтение настроек из config.json. - Пишите, что сделано, а не что вы при этом чувствовали.
- Один коммит — одно законченное изменение. Не сваливайте день работы в один снимок «сделал всё».
Чего не должно быть в репозитории: .gitignore
В проекте всегда заводится мусор: временные файлы Python в папке __pycache__, настройки редактора, служебные файлы системы. Хранить их в истории бессмысленно.
Создайте в корне проекта файл с именем .gitignore (да, начинается с точки):
__pycache__/
*.pyc
.venv/
.DS_Store
.vscode/
Звёздочка * означает «любой набор символов», поэтому *.pyc — все файлы с расширением .pyc. Слэш в конце означает папку.
Отдельно и очень важно: в репозиторий нельзя класть пароли, ключи доступа и токены. Если вы закоммитили пароль и выложили на GitHub, считайте его скомпрометированным — удалить его из истории сложно, а роботы сканируют публичные репозитории круглосуточно. Секреты хранят в отдельном файле, который перечислен в .gitignore.
Как отменить и вернуться
Здесь Git окупается.
Посмотреть, что я наменял с последнего коммита:
git diff
Вывод показывает изменения построчно: строки со знаком - удалены, со знаком + добавлены.
Отменить правки в файле и вернуть его как в последнем коммите:
git restore calc.py
Осторожно: несохранённые правки в этом файле пропадут — но именно этого вы и просили.
Вынуть файл из индекса (передумали включать в коммит):
git restore --staged calc.py
Посмотреть проект таким, каким он был в старом коммите:
git checkout 8f3a1c2
Git скажет что-то про detached HEAD — это не поломка, а предупреждение «вы гуляете по прошлому, а не работаете». Вернуться в настоящее:
git switch main
Главное, что стоит запомнить: всё, что попало в коммит, вернуть можно. Всё, что не попало, — нет. Поэтому коммитьте часто.
Ветки
Ветка — это параллельная линия развития проекта. Вы отходите в сторону, спокойно делаете новую функцию, и основная версия всё это время остаётся рабочей.
Аналогия. Вы пишете книгу и хотите попробовать другую концовку. Делаете копию рукописи, экспериментируете в ней, а оригинал не трогаете. Понравилось — переносите изменения в оригинал; не понравилось — выбрасываете копию.
Где аналогия ломается. Копия рукописи — это отдельные листы бумаги, которые надо потом сверять вручную. Git хранит не копии файлов, а связи между коммитами, и сливает ветки автоматически — вручную придётся вмешаться только там, где обе стороны правили одни и те же строки.
На схеме: основная линия main продолжала жить (в неё внесли правку README), пока в ветке feature-divide делали деление. Потом ветки слили, и обе работы оказались в main.
Команды:
git switch -c feature-divide # создать ветку и перейти в неё
# ... правим файлы, делаем коммиты ...
git switch main # вернуться в основную ветку
git merge feature-divide # влить изменения из ветки в main
git branch -d feature-divide # удалить ветку, она больше не нужна
Если Git сообщит CONFLICT (content): Merge conflict in calc.py — это конфликт слияния: обе ветки поменяли одни и те же строки, и Git не знает, чью версию оставить. Он вставит в файл разметку:
<<<<<<< HEAD
return a / b
=======
return round(a / b, 2)
>>>>>>> feature-divide
Ваша работа — открыть файл, оставить правильный вариант, удалить строки со стрелками и знаками равенства, затем git add и git commit. Звучит страшно, делается за минуту.
GitHub: код в интернете
Пока вся история жила только на вашем диске. Чтобы сделать копию в интернете:
- Зарегистрируйтесь на github.com.
- Нажмите New repository, задайте имя (например,
calc), не ставьте галочки на README и .gitignore — они у нас уже есть. - GitHub покажет готовые команды. Они будут примерно такие:
git remote add origin https://github.com/anna/calc.git
git push -u origin main
git remote add origin ... — запомнить адрес сервера под коротким именем origin (это просто традиция, никакого волшебства в слове нет). git push — отправить коммиты на сервер. Ключ -u связывает вашу ветку с серверной, чтобы дальше хватало просто git push.
Обмен с сервером устроен так:
GitHub — общая точка обмена
Четыре команды на все случаи жизни:
git push— отправить свои коммиты на сервер;git pull— забрать оттуда чужие;git clone https://github.com/кто-то/проект.git— скачать чужой проект целиком вместе со всей историей;git fetch— посмотреть, что появилось на сервере, ничего не меняя у себя.
Начинайте день с git pull, заканчивайте git push. Этой привычки хватит надолго.
Типичные ошибки и что говорят сообщения
fatal: not a git repository (or any of the parent directories): .git
Дословно: «это не git-репозиторий». Вы запускаете команду не в той папке — там нет .git. Проверьте pwd, зайдите в папку проекта или сделайте git init.
nothing to commit, working tree clean
«Нечего коммитить, рабочее дерево чистое». Не ошибка. Значит, вы либо ничего не меняли, либо забыли git add.
error: pathspec 'main' did not match any file(s) known to git
Ветки с таким именем нет. В старых проектах основная ветка называется master, а не main. Посмотрите список: git branch.
Updates were rejected because the remote contains work that you do not have locally
«Отправка отклонена: на сервере есть работа, которой у вас нет». Кто-то (или вы с другого компьютера) уже отправил коммиты. Сделайте git pull, разберитесь с возможным конфликтом, потом git push.
Please tell me who you are
Вы не сделали git config user.name и user.email. Git прямо в сообщении пишет нужные команды.
Коммит с одним огромным изменением. Технически не ошибка, но история становится бесполезной. Лучше пять маленьких понятных коммитов, чем один под названием «всё».
Забытый .gitignore. Через неделю в репозитории 900 файлов __pycache__. Заводите .gitignore первым делом в новом проекте.
Практика
Задания идут от простого к сложному. Всё делается в терминале — так и задумано.
1. Освоиться в терминале. Откройте терминал и не трогая мышку: узнайте текущую папку, посмотрите её содержимое, создайте папку praktika, зайдите в неё, создайте внутри пустой файл readme.txt, убедитесь, что он там есть, вернитесь на уровень выше.
Подсказка: pwd, ls, mkdir, cd, touch (или New-Item в PowerShell), снова ls, cd ... Пользуйтесь Tab — он допишет имена за вас.
2. Первый репозиторий. Внутри praktika сделайте git init, создайте файл hello.py с одной строкой print("Привет!"), запустите его через python hello.py, затем сделайте коммит с внятным сообщением. Проверьте результат через git log --oneline.
Подсказка: после каждого шага набирайте git status и читайте, что он советует в скобках. Это лучший способ запомнить команды.
3. История из трёх коммитов. Добавляйте в hello.py по одной функции за раз — сложение, вычитание, умножение — и после каждой делайте отдельный коммит. Затем посмотрите git log --oneline и git diff между состояниями.
Подсказка: чтобы увидеть, что изменилось в конкретном коммите, есть команда git show <первые-7-символов-хеша>.
4. Отмена и .gitignore. Испортите hello.py — удалите половину кода и сохраните. Убедитесь через git status и git diff, что Git это заметил, и верните файл командой git restore. Затем запустите программу так, чтобы появилась папка __pycache__ (для этого нужен второй файл, который импортирует первый), и добавьте .gitignore, чтобы Git перестал её показывать.
Подсказка: __pycache__ появляется при import. Создайте main.py со строкой import hello. Про импорт модулей подробнее — в статье Функции.
5. Ветка и слияние (со звёздочкой). Создайте ветку feature-divide, добавьте в ней функцию деления с проверкой на ноль, сделайте коммит. Вернитесь в main, поправьте там что-нибудь другое и тоже закоммитьте. Слейте ветку в main и посмотрите историю командой git log --oneline --graph --all.
Подсказка: ключ --graph рисует ветки псевдографикой прямо в терминале — вы увидите ту же картинку, что была на схеме выше. Если получите конфликт — отлично, это лучший способ научиться их решать: откройте файл, оставьте нужный вариант, удалите строки-разделители, git add, git commit.
Мини-итог
Терминал — способ управлять компьютером текстом. Он буквален и ничего не додумывает, но зато повторяем, работает удалённо и умеет всё, что нужно инструментам разработчика. Минимальный набор: pwd, ls, cd, mkdir, python файл.py. Плюс Tab для автодополнения, стрелка вверх для истории и Ctrl + C, чтобы прервать зависшую программу.
Git — история изменений проекта. Ключ к пониманию — четыре зоны: рабочая папка, индекс, локальная история, сервер. Ежедневный цикл умещается в три команды: git status, git add, git commit -m "...". Ветки позволяют экспериментировать, не ломая рабочую версию, а GitHub хранит копию в интернете и служит точкой обмена с коллегами.
Не пытайтесь выучить всё сразу. Пять команд, которыми вы пользуетесь каждый день, укладываются в голову за неделю практики, а остальное гуглится по мере надобности — это делают и разработчики с десятилетним стажем.
Куда идти дальше:
- Официальная книга Pro Git — бесплатно и на русском, глава 2 закрывает 90% повседневных задач.
- Learn Git Branching — интерактивный тренажёр веток прямо в браузере, лучший способ понять слияния.
- Oh Shit, Git!?! — короткий справочник «я всё сломал, что делать» по конкретным ситуациям.
- Документация GitHub на русском — про сам сайт: pull request, issues, совместная работа.
Что дальше
У вас теперь есть всё, что нужно для настоящей работы: вы знаете язык, умеете разбирать ошибки, запускаете код из терминала и храните его историю в Git. Не хватает одного — опыта пройти путь целиком.
Пора собрать всё вместе и написать проект от идеи до работающей программы: придумать, разбить на шаги, реализовать, отладить и выложить на GitHub.