Не только Git…

(повторение) Git: DVCS

  1. Версионирование
  2. Хранение
  3. Работа с историей изменений в виде орграфа (сети)
    • Ветки
    • Изменение истории
  4. Информационное пространство:
    • Описание процесса (коммит сообщения)

    • Маркировка отдельных точек (теги)
      • В т. ч. аннотированные и подписанные теги

Организация взаимодействия при совместной разработке

Модели ведения репозитория

Классическая модель

Открытая модель:

Модель общего хостинга:

Централизованная модель:

Принятие коммитов в репозиторий

Запрос на объединение

(merge request, pull request, …) — часть дисциплины распределённой совместной разработки, в которой предполагается, что у каждого разработчика имеется собственный репозиторий, и только в него можно делать коммиты. Для того, чтобы другой разработчик смог вовремя синхронизировать свой репозиторий с результатами работы первого, его нужно уведомить о том, что работа проделана.

Ревью
(code reviwew) — часть дисциплины совместной разработки, в которой никакой коммит не появляется в истории, пока его не одобрит специально выбранный для этой роли участник. Это может быть лид или просто ещё одинчлен команды
  • Для централизованной модели отсутствие ревью фатально (как и отсутствие многих других элементов дисциплины)
  • Для распределённых моделей ревью «подразумевается» (кто-то же должен сделать merge commit)

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

Ветки и индивидуальные публичные репозитории — ортогональные сущности

В централизованной схеме ветки играют обе роли.

Пример параллельной разработки

На примере самого Python

Работа с несколькими удалёнными репозиториями

При использовании схемы «Precious source» — минимум двумя (свой и апстримный).

git remote (ещё тут)

Пример:

Пользователь

Локальный репозиторий

Публичный репозиторий

Разработчик

owner

http://localhost:8000/repo

Коммиттер

committer

http://localhost:8000/comm_repo

  1. Оба участника заводят пустые репозитории, подготавливают их к публикации и публикуют
       1 srv:~/joined$ git init --bare repo
       2 srv:~/joined$ cp repo/hooks/post-update.sample repo/hooks/post-update
       3 srv:~/joined$ git init --bare comm_repo                              
       4 srv:~/joined$ cp comm_repo/hooks/post-update.sample comm_repo/hooks/post-update 
       5 srv:~/joined$ python3 -m http.server &
    
  2. В нашем случае запушить по протоколу http: нельзя, но зато можно запушить в соседний каталог
       1 srv:~/joined$ git clone repo owner
       2 srv:~/joined$ cd owner 
       3 srv:~/joined/owner$ cal > calendar
       4 srv:~/joined/owner$ git add .
       5 srv:~/joined/owner$ git commit -m "Initiail"
       6 srv:~/joined/owner$ git push     
       7 srv:~/joined/owner$ cd ..
    
  3. Коммиттер добавляет публичный репозиторий разработчика как второй remote, что-то меняет и публикует изменения в своём публичном репозитории
       1 srv:~/joined$ git clone comm_repo committer
       2 srv:~/joined$ cd committer 
       3 srv:~/joined/committer$ git remote add upstream http://localhost:8000/repo
       4 srv:~/joined/committer$ git remote -v
       5 srv:~/joined/committer$ git pull upstream master 
       6 srv:~/joined/committer$ date >> calendar 
       7 srv:~/joined/committer$ git commit -a -m "Add date"
       8 srv:~/joined/committer$ git push                
    
  4. Комиттер как-то даёт знать разработчику о том, что пора принимать работу.

  5. Разработчик добавляет публичный репозиторий коммиттера как второй remote, и мержится с ним (pull — это fetch + merge)
       1 srv:~/joined/committer$ cd ../owner 
       2 srv:~/joined/owner$ git remote add comm http://localhost:8000/comm_repo
       3 srv:~/joined/owner$ git pull comm master 
    

Обычно коммиттер сообщает разработчику ещё commit ID — тогда pull превращается в fetch + merge commitID

Резюме: чего не умеет Git?

Пример: pre-commit hook

Есть даже целый пакет — pre-commit

Cmd и асинхронные сообщения

Проблема: ввод командной строки с помощью readline, подстановка в cmd и прочее — синхронные операции. Предположим, пользователь вводит команду, а в это время прилетает сообщение. Что делать?

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

Решение: воспользуемся тем, что полученное сообщение надо просто вывести на экран.

   1 import cmd
   2 import threading
   3 import time
   4 import readline
   5 
   6 class simple(cmd.Cmd):
   7 
   8     def do_echo(self, arg):
   9         print(arg)
  10 
  11 def spam(cmdline, timeout, count):
  12     for i in range(count):
  13         time.sleep(timeout)
  14         print(f"\nI'm a message № {i}!\n{cmdline.prompt}{readline.get_line_buffer()}", end="", flush=True)
  15 
  16 
  17 cmdline = simple()
  18 timer = threading.Thread(target=spam, args=(cmdline, 3, 10))
  19 timer.start()
  20 cmdline.cmdloop()

Д/З

Основное задание

  1. Написать простой netcat-образный клиент для «коровьего чата» из задания по прошлой лекции. Достаточно совместить последний пример из лекции и «тупой netcat» из предыдущей. Написать cmd-поддержку команд чата в клиенте и обеспечить completion по именам коров.

    • В login completion должен сначала выполнять cows на сервере, и предлагать результаты оттуда

    • Аналогично, в say completion должен сначала выполнять who на сервере, и предлагать результаты оттуда

  2. Разработку клиента вести согласно дисциплине оформления коммитов в подкаталоге 06_SocialProject отчётного репозитория по Д/З

<!> Обратите внимание на то, что это сравнительно невинное изменение меняет протокол работы с сервером: помимо «просто» сообщений из чата появляется сообщение-ответ на определённую команду-запрос. Самый простой способ не запутаться — это ввести уникальный «номер запроса» и сопровождать ответ им. Например, номер запроса в сообщении от других пользователей всегда 0, а ответ на команду — номер поданной в данном сеансе команды.

Регистрация семестрового проекта

  1. Завести один «precious source» репозиторий для merge и публикации проекта и персональные — для разработки (лидеру проекта допустимо вести разработку в отдельной ветке, заводить ещё один репозиторий не надо)
  2. Разработать драфт проектного задания;
    • Постановка решаемой задачи: один абзац или список фич
    • Описание предполагаемых инструментов решения: какие сторонние модули будут использоваться, в рамках каких сервисов (если предполагаются)
    • Макет интерфейса (обратите внимание на то, что от проекта требуется локализация ⇒ какой-то интерфейс с человеком должен быть

      • GUI/TUI — общий вид окошек, что в целом они делаю и как попадают из одного в другое
      • Text — команды, диагностика (в общем плане — когда возникает и как посмотреть), режимы работы
      • Поместить проектное задание в README (или README.md) публичного репозитория
  3. Зарегистрировать публичный репозиторий проекта в качестве вашего персонального issue на странице репозитория PythonDevelopment2026. В issue указать:

    • Короткую формулировку сути проекта
    • Ссылку на публичный репозиторий проекта

    • Список участников проекта в виде:
      1. ФИО_1, группа_1 (факультет_1, если не ВМК) и nick_1, под которым появляются коммиты в репозитории
      2. ФИО_2, группа_2 (факультет_2, если не ВМК) и nick_2, под которым появляются коммиты в репозитории
  4. См. требования к защите проекта

<!> В семестровом проекте требуется использовать схему с precious source репозиторием для публикации и отдельными репозиториями разработчиков.

LecturesCMC/PythonDevelopment2026/06_SocialProject (последним исправлял пользователь FrBrGeorge 2026-03-18 16:54:08)