Python и открытая разработка; использование Git
- (повторение) Свободное лицензирование и Python
- ⇒ Возможность открытой разработки
- Открытая разработка:
- Низкий порог входа-выхода
- Произвольная мотивация
- Динамическая профессиональная иерархия
- Свободное распространение как условие развития
- Распределённая совместная разработка
- Информационное пространство (документация/взаимодействие)
Сообщество Python и разработка
- Сам Python:
2026-02-10 740516 проектов 8042874 выпуска 17184594 файла 1008471 пользователь
2025-02-11 608063 проекта 6582028 выпусков 13316977 файлов 901794 пользователя
2024-02-12 513791 проект, 5363906 выпусков, 10269997 файлов, 784063 пользователя
Несколько сотен несвободных проектов, остальные — свободные
https://readthedocs.org — документация
- (никто не мешает использовать GH или вообще что угодно)
- См. выше про packaging
- Разработка стандартов (egg, wheel, pyproject.toml, …)
- Поддержка утилит (pip, setuptools, venv, pipx, pipenv, …)
- …
Python и непрограммисты: уровень культуры разработки в разных проектах очень разный.
Использование Git
Система контроля версий:
- Хранение
- Версионирование
- Файлов/объектов
Состояний всего корпуса кода
- История изменений
- Возможно, нелинейная (орграф, точнее — сеть)
- Создание информационного пространства вокруг исходного текста
Не путать (особенно в последнем пункте) GIT как DVCS с Git-хостингами (типа GitHUB) — там много сделано как раз для информационной связности.
Коротко о VCS/DVCS
VCS:
Цикл работы с VCS
Используется «централизованный репозиторий на всех»
- Синхронизация
- Редактирование / отладка
- Оформление коммита
- Публикация коммита
Проблема: совместная работа над одним корпусом текстов
- Интерференция изменений
- В частности взаимоблокировка merge/push
- Изменения опубликованных исходников задним числом
- Тактика «накопленных изменений»
Проблема решается введением дисциплины (например, вводится строгое время публикации, личные ветки разработки, права доступа и т. д.)
DVCS
Git
Работа с Git как с локальной VCS
Структура локального хранилища:
Рабочая копия — полный набор набор файлов из проекта
Поначалу этот набор соответствует определённому состоянию проекта (т. н. дереву)
- Модификация рабочей копии ничего не меняет (кроме того, что набор теперь не соответствует ничему)
Хранилище (репозиторий) — подкаталог .git (обычно в каталоге с рабочей копией)
Коммит делается всегда в локальное хранилище. Публикация (push) — независимая операция.
Цикл работы с локальным хранилищем
- Инициализация.
git init
- Изменение рабочей копии — редактирование/удаление/добавление файлов.
- Чтобы посмотреть, чем рабочая копия отличается от соответствующего дерева в репозитории:
git status
- Чтобы посмотреть, чем рабочая копия отличается от соответствующего дерева в репозитории:
- Подготовка коммита — надо пометить файлы, которые в него войдут.
git add список файлов
- Можно добавить сразу всё:
git add *
Если сейчас сделать git status, увидим изменения, которые будут добавлены в коммит
- Оформление коммита — создаём на основании изменений рабочей копии новое дерево и обновляем репозиторий
git commit
- В процессе коммита запускается редактор, в котором надо отредактировать коммит-сообщение
Чтобы поменять редактор с vim на что-нибудь иное, надо изменить файл .git/config. Это можно сделать, например, с помощью командной строки git config core.editor 'ваш любимый редактор'
Обратите внимание на то, что git запускает редактор в интерактивном (foreground) режиме, дожидается его завершения, и только потом продолжает работу. Поэтому просто gvim, например, не годится, используйте gvim -f
- При этом в репозитории создаётся три типа объектов
это новое дерево (список всех файлов) — tree
коммит-сообщение — commit
и все изменённые файлы (blob)
переход к п. 1.
Историю коммитов можно посмотреть командой git log. Для того, чтобы отключить постраничный просмотр, используйте git -P log.
Изменения, сделанные только в локальном репозитории, никто, кроме вас не видит. Это значит, что вы спокойно можете редактировать и изменять историю уже сделанных изменений, при условии, что изменяемые вами коммиты нигде не опубликованы.
Например, если вам не понравился последний коммит, и вы хотите в нём что-то поменять — переписать сообщение, поправить изменение в файле и т. п. — можно сделать нужные изменения и выполнить git commit --amend. Тогда новый коммит не добавится в историю, а заменит в ней старый. В него, разумеется, попадёт всё, чем текущая рабочая копия отличается от дерева в предпоследнем коммите.
Коммит отдельных изменений
В действительности добавлять можно даже не файлы, а отдельные изменения в них (см. FrBrGeorge/Using git add -p и git add --interactive):
1 $ cal -y > calend 2 $ git add . 3 $ git commit -a -m initial 4 $ sed -i 's/2026/Год 2026/' calend 5 $ date >> calend 6 $ git add -p 7 diff --git a/calend b/calend 8 index 817a13e..dd2b261 100644 9 --- a/calend 10 +++ b/calend 11 @@ -1,4 +1,4 @@ 12 - 2026 13 + Год 2026 14 15 Январь Февраль Март 16 Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс 17 (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? y 18 @@ -32,3 +32,4 @@ 19 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 20 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 21 30 22 +Вт 10 фев 2026 20:23:46 MSK 23 (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? n 24 25 $ git status 26 On branch master 27 Changes to be committed: 28 (use "git restore --staged <file>..." to unstage) 29 modified: calend 30 31 Changes not staged for commit: 32 (use "git add <file>..." to update what will be committed) 33 (use "git restore <file>..." to discard changes in working directory) 34 modified: calend 35 $ git commit -m "Chenge a year" 36 [master f1bca1d] Chenge a year 37 1 file changed, 1 insertion(+), 1 deletion(-) 38 $ git -P diff 39 diff --git a/calend b/calend 40 index 69c129e..ae1fc76 100644 41 --- a/calend 42 +++ b/calend 43 @@ -32,3 +32,4 @@ 44 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 45 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 46 30 47 +Вт 10 фев 2026 20:29:35 MSK 48
О структуре репозитория
Все объекты имеют уникальный ID (это SHA-1 хеш). Объект с ID, допустим, 8dccc7a1d248ea923156b2e762e576b44e07886a, хранятся в файле с именем .git/objects/8d/ccc7a1d248ea923156b2e762e576b44e07886a
Посмотреть содержимое объектов можно (но непонятно, зачем ☺), например, так:
python3 -c "import sys; import zlib; print(zlib.decompress(sys.stdin.buffer.read()))" < .git/objects/8d/ccc7a1d248ea923156b2e762e576b44e07886a
Иллюстрации по структуре объектов git-репозитория:
- Первый коммит с простой структурой (файлы в одном каталоге):
- Первый коммит с файлами в нескольких каталогах:
- История из нескольких последовательных коммитов:
Замечания по структуре объектов
Заголовок, в котором лежит строка вида «b"тип_объекта размер"», отделяется от содержимого нулевым байтом. Удобно пользоваться методом .partition(b'\x00')
Объект типа blob — это просто содержимое файла
Объект типа tree:
b'tree размер'
b'\x00'
b'атрибуты имя'
b'\x00'
ID = bytes[20]
b'атрибуты имя'
b'\x00'
ID = bytes[20]
…
b"атрибуты имя"
b'\x00'
ID = bytes[20]
Объект типа commit — текстовый, строки до первой пустой — служебные, вида b"Поле содержание" (нам важно поле parent, если оно есть)
Полей "parent" в коммите может быть любое (?) число, точно бывает 0, 1 и 2 штуки
Коммит ID, соответствующие HEAD различных веток, лежат в файле .git/refs/heads/имя_ветки
В нашем курсе рекомендуется пользоваться именно интерфейсом командной строки — командой git, утилитами из пакетов python и т. п., а не волшебной кнопкой «сделать мне хорошо» в IDE. Пока мы не до конца представляем себе, что именно происходит после нажатия этой кнопки, она приносит больше вреда, чем пользы.
Д/З
Создать публичный репозиторий (GitHub, GitLab, факультетский GitLab, sr.ht, где угодно
Для получения оценки необходимо зарегистрировать его тут
Установить и научиться пользоваться командной строкой git в объёме цикла «add → commit → push → pull → …»
Для windows рекомендуется официальный клиент, в состав которого входит unix-подобная командная строка — для совместимости с лекциями
