From da55b27ab377126d312bc0ddf26a558b47bc0dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B0=D0=B3=D0=B8=D1=80=20=D0=95=D0=BD=D0=B8=D0=BA?= =?UTF-8?q?=D0=B5=D0=B5=D0=B2?= Date: Thu, 6 Feb 2025 18:55:11 +0300 Subject: [PATCH] [TASK] git #22 (https://github.com/SENATOROVAI/docs/issues/22) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #22 (https://github.com/SENATOROVAI/docs/issues/22) В файле git.ipynb сделан конспект главы про Git из книги Эла Свейгарта "Чистый код" --- git.ipynb | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 git.ipynb diff --git a/git.ipynb b/git.ipynb new file mode 100644 index 0000000..a53bba4 --- /dev/null +++ b/git.ipynb @@ -0,0 +1,368 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Git и организация программных проектов.\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Системы контроля версий представляют собой программные средства, которые регистрируют все изменения в исходном коде и позволяют легко восст\n", + "\n", + "Система контроля версий управляет файлами при внесении в них изменений\n", + "\n", + "Git, Mercurial и Subversion — популярные приложения контроля версий, хотя система Git остается самой популярной\n", + "\n", + "\n", + "### Коммиты и репозитории\n", + "\n", + "Git позволяет сохранить состояние файлов проекта при внесении в них изменений. Такие сохранения называются снимками (snapshots) или коммитами (commits).\n", + "\n", + "Система контроля версий управляет исходным кодом проекта, который хранится в специальной папке — репозитории (repo).\n", + "\n", + "\n", + "### Создание новых проектов Python с использованием Cookiecutter\n", + "\n", + "В терминологии Git папка, содержащая весь исходный код, документацию, тесты и другие файлы, относящиеся к проекту, называется рабочим каталогом или рабочим деревом, а в более общей терминологии — папкой проекта. Файлы в рабочем каталоге в совокупности называются рабочей копией.\n", + "\n", + "Для проектов Python действуют определенные соглашения по поводу имен папок и иерархий. Более простая программа может содержать один файл .py. Но когда проекты усложнятся, в них будут включаться дополнительные файлы .py, файлы данных, документация, модульные тесты и т. д. Как правило, корневая папка проекта содержит папку src для файлов с исходным кодом .py, папку tests для модульных тестов и папку docs для документации (например, сгенерированной системой документирования Sphinx). Другие файлы содержат информацию о проекте и конфигурации системы\n", + "\n", + "Чтобы ускорить выполнение рутинных операций, можно использовать модуль Python cookiecutter для автоматического создания этих файлов и папок. Полная документация по модулю и программе командной строки Cookiecutter доступна на https://cookiecutter.readthedocs.io/.\n", + "\n", + "Чтобы установить Cookiecutter, выполните команду pip install --user cookiecutter\n", + "(в системе Windows) или pip3 install --user cookiecutter (в macOS и Linux).\n", + "\n", + "```powershell\n", + "pip install --user cookiecutter\n", + "```\n", + "\n", + "Модуль cookiecutter использует шаблоны для создания начальных файлов для различных видов проектов. Часто шаблон представляет собой простую ссылку на GitHub.com\n", + "\n", + "```powershell\n", + "python -m cookiecutter gh:asweigart/cookiecutter-basicpythonproject\n", + "```\n", + "\n", + "В разделе https://github.com/cookiecutter/cookiecutter вы найдете шаблоны для многих языков программирования. Так как шаблоны Cookiecutter часто размещаются на GitHub, вы также можете ввести gh: как сокращение для https://github.com/ в аргументе командной строки.\n", + "\n", + "\n", + "### Установка Git\n", + "\n", + "Git уже установлена на компьютере. Чтобы узнать это, вводим команду ```git --version``` в командной строке. Если получаем сообщение вида ```git version 2.29.0.windows.1```, значит, программная поддержка Git уже установлена. Если сообщение «команда не найдена» - Git придется установить (в системе Windows перейдите на страницу https://git-scm.com/download, загрузите и запустите программу установки Git; в Ubuntu или Debian Linux выполните команду sudo apt install git-all из окна терминала).\n", + "\n", + "\n", + "### Работа с Git\n", + "\n", + "Работа с репозиторием Git состоит из нескольких этапов:\n", + "\n", + "1. Создание репозитория Git:\n", + " + командой git init инициализируем гит в новом проекте\n", + " + командой git clone копируем удалённый репозиторий на локальную машину\n", + "2. Добавление файлов в репозиторий для отслеживания:\n", + " + командой git add <имя_файла>\n", + "3. Сохранение файлов:\n", + " + командой git commit -am \"<сообщение, описывающее содержание коммита>\"\n", + "\n", + "Справку по каждой из этих команд можно посмотреть командой git help <команда> — например, git help init или git help add.\n", + "\n", + "\n", + "### Как Git отслеживает статус файлов\n", + "\n", + "1. Отслеживаемые файлы:\n", + " + В **сохраненном** (закрепленном) состоянии файл в рабочей копии идентичен последнему коммиту в репозитории. (Иногда это состояние называется неизмененным, или чистым.)\n", + " + В **измененном** состоянии файл в рабочей копии отличается от последнего коммита в репозитории.\n", + " + В **индексированном**, или подготовленном (staged), состоянии файл был изменен и помечен для включения в следующий коммит. Также говорят, что файл находится в индексной области (или кэше).\n", + "2. Неотслеживаемые файлы:\n", + " + Для репозитория Git **неотслеживаемые** файлы в рабочей копии не существуют\n", + " + Для перехода в отслеживаемого необходимо добавить его с помощью команды git add\n", + "\n", + "Переход файла между четырьмя возможными состояниями\n", + "\n", + "1. Добавляем **неотслеживаемый** файл в репозиторий Git, после чего он становится отслеживаемым и **индексированным**\n", + "2. Сохраняем **индексированные** файлы, чтобы перевести их в **индексированное** состояние\n", + "3. Для перевода файла в измененное состояние никакие команды Git не нужны; как только файл изменяется, он автоматически помечается как **измененный**\n", + "\n", + "На любом этапе после создания репозитория выполните команду ```git status``` для\n", + "просмотра текущего статуса репозитория и состояния его файлов\n", + "\n", + "\n", + "### Для чего нужно индексирование?\n", + "\n", + "С технической точки зрения область индексирования содержит не столько файлы,\n", + "сколько описания изменений. Это может привести к следующим особым случаям:\n", + "\n", + "+ файл может быть изменен после того, как он был проиндексирован, в результате чего файл существует как в измененном, так и в индексированном состоянии\n", + "+ одни части измененного файла могут быть индексированы, а другие — нет\n", + "\n", + "Чтобы избежать сложностей, необходимо использовать команду ```git commit -am``` для индексирования и закрепления измененных файлов на одном шаге. В этом случае файлы переходят из измененного состояния сразу же в чистое.\n", + "\n", + "\n", + "#### Создание репозитория Git на компьютере\n", + "\n", + "Git является распределенной системой контроля версий. Это приводит к следующиму:\n", + "+ коммиты и метаданные репозиториев хранятся локально на компьютере в папке с именем .git.\n", + "+ не нужно подключаться к серверу по интернету для сохранения данных\n", + "+ Git работает быстро и остается доступной при автономной работе\n", + "\n", + "Сценарий создания локального репозитория\n", + "1. Создаём папку с проектом, если нет:\n", + "\n", + " + Windows:\n", + " ```powershell\n", + " md project\n", + " ```\n", + "\n", + " + Linux, MacOS:\n", + " ```bash\n", + " mkdir project\n", + " ```\n", + "\n", + "2. Заходим в папку проекта:\n", + "\n", + " ```bash\n", + " cd project\n", + " ```\n", + "\n", + "3. Инициализируем гит-репозиторий:\n", + "\n", + " ```bash\n", + " git init\n", + " ```\n", + "\n", + "Для папки project команда ```git init``` создает папку ```project/.git``` с метаданными репозитория Git. Имя ```.git``` присваивается ей из-за того, что многие операционные системы автоматически скрывают папки и файлы, имена которых начинаются с точки.\n", + "Все файлы в папке ```project``` в исходном состоянии являются _неотслеживаемыми_.\n", + "\n", + "Репозиторий на нашем компьютере называется локальным; репозиторий на другом компьютере называется удаленным.\n", + "\n", + "После того как репозиторий будет создан, команда git может использоваться для добавления файлов и отслеживания изменений в рабочем каталоге. Выполнив команду git status в созданном репозитории, мы увидим, что в репозитории еще ничего не сохранено.\n", + "\n", + "\n", + "#### Добавление файлов для отслеживания\n", + "\n", + "Только отслеживаемые файлы можно сохранять, откатывать к предыдущей версии или выполнять иные операции командой git.\n", + "\n", + "Процесс сохранения файлов в репозиториии состоит из двух этапов:\n", + "1. Выполнение команды ```git add``` для каждого сохраняемого файла\n", + "2. Выполнение команды ```git commit``` для создания коммитов всех этих файлов.\n", + "После того как файл будет сохранен, Git начинает его отслеживать.\n", + "\n", + "Команда ```git add``` переводит файлы из неотслеживаемого или измененного состояния в индексированное состояние. Можно выполнить команду git add для каждого файла, который нужно проиндексировать, перечислив названия файлов после команды, но лучше воспользоваться подстановочным символом * для добавления сразу нескольких файлов. Например, команда git add *.py добавляет все файлы .py из текущего рабочего каталога и его подкаталогов. Чтобы добавить все неотслеживаемые файлы, используйте точку (git add .)\n", + "\n", + "Команда ```git commit -m \"Adding new files to the repo.\"``` сохраняет все выбранные в команде ```git add``` файлы в репозитории.\n", + "\n", + "Файлы, перечисленные в файле .gitignore, не включаются в индексирование.\n", + "\n", + "\n", + "#### Игнорирование файлов в репозитории\n", + "\n", + "В процессе написания кода некоторые файлы можно исключить из системы контроля версий, чтобы предотвратить их случайное отслеживание. К этой категории относятся:\n", + "+ временные файлы в папке проекта;\n", + "+ файлы .pyc, .pyo и .pyd, генерируемые интерпретатором Python при выполнении программ .py;\n", + "+ папки .tox, htmlcov и другие папки, генерируемые различными средствами разработчика;\n", + "+ другие откомпилированные или сгенерированные файлы, которые можно сгенерировать заново (потому что репозиторий предназначен для исходных файлов, а не для производных файлов, которые генерируются на их основе);\n", + "+ файлы с исходным кодом, содержащие пароли баз данных, маркеры аутентификации, номера кредитных карт или другие конфиденциальные данные.\n", + "\n", + "Перечисленные в файле с именем .gitignore файлы и папки не отслеживаются Git. Git автоматически исключает их из команд ```git ad```d или ```git commit```, и они не будут отображаться при выполнении команды ```git status```. В файле .gitignore символ * используется для шаблонов, а # — для комментариев.\n", + "\n", + "Файл .gitignore следует добавить в репозиторий Git, чтобы он был у других программистов, клонировавших репозиторий.\n", + "\n", + "Команда ```git ls-files --other --ignored --exclude-standard``` позволяет просмотреть список игнорируемых файлов на основании настроек в .gitignore\n", + "\n", + "\n", + "#### Сохранение изменений\n", + "\n", + "```git add .``` + ```git commit -m <сообщение>``` = ```git commit -am <сообщение>``` - созраним все изменения в репозитории\n", + "```git commit -m <сообщение> file1.py file2.py``` сохраним изменения только в выбранных файлах\n", + "\n", + "Не поддавайтесь искушению написать короткое обобщенное сообщение вида «Обновленный код», «Исправлены некоторые ошибки» или просто «x» (потому что пустые сообщения запрещены). Через три недели, когда вам захочется вернуться к более ранней версии вашего кода, подробные сообщения в каждом коммите сэкономят вам немало времени, когда вы будете выбирать, к какой именно версии следует вернуться.\n", + "\n", + "Если забыли написать сообщение коммита, открывшееся в этом случае окно Vim закрываем (Esc -> ввод qa! -> Enter) и коммитим заново с вводом сообщения\n", + "\n", + "Хороший пример коммитов - веб-фреймворк Django (https://github.com/django/jango/commits/master. Так как Django является большим проектом с открытым кодом, коммиты выполняются часто, а сообщения коммитов формализованы.\n", + "\n", + "В репозитории Git нельзя сохранять папки. Git автоматически включает папки в репозитории при сохранении хранящихся в них файлов, но сохранить пустую папку не получится.\n", + "\n", + "Если допущена ошибка в последнем сообщении коммита, его можно переписать командой ```git commit --amend -m \"<новое_сообщение>\"```\n", + "\n", + "\n", + "#### Просмотр изменений перед коммитом\n", + "\n", + "Для просмотра различий между рабочей копией кода и последним сохраненным кодом можно воспользоваться командой ```git diff command```. В отчёте команды строки, начинающиеся со знака '-', были удалены; строки, начинающиеся со\n", + "знака '+', были добавлены.\n", + "\n", + "\n", + "#### Просмотр изменений в графическом приложении командой git difftool\n", + "\n", + "Изменения проще просматривать в программе с графическим интерфейсом:\n", + "\n", + "+ для Windows можно загрузить ```WinMerge``` (https://winmerge.org/)\n", + "+ в Linux можно установить:\n", + " + ```Meld```\n", + " ```bash\n", + " sudo apt-get install meld\n", + " ```\n", + " + ```Kompare```\n", + " ```bash\n", + " sudo apt-get install kompare\n", + " ```\n", + "+ macOS для установки программы ```tkdiff``` необходимо установить Homebrew (менеджер пакетов для установки программ), а затем с помощью Homebrew установить ```tkdiff```:\n", + " ```bash\n", + " /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/\n", + " master/install.sh)\"\n", + " brew install tkdiff\n", + " ```\n", + "\n", + "Командой ```git config diff.tool <название приложения>``` настраиваем Git для использования приложение ```winmerge```, ```tkdiff```, ```meld``` или ```kompare```\n", + "\n", + "Чтобы система Git не запрашивала подтверждения каждый раз, когда запускаем программу просмотра изменений, настраиваем Git командой ```git config --global difftool.prompt false```\n", + "\n", + "\n", + "#### Частота сохранения изменений\n", + "\n", + "Код следует сохранять:\n", + "1. При завершении блока функциональности, класса\n", + "2. Исправления ошибки\n", + "\n", + "Не следует сохранять код:\n", + "1. Содержащий синтаксические ошибки\n", + "2. Неработоспособный\n", + "\n", + "Всегда выполняйте все модульные тесты перед сохранением. В идеале все тесты должны проходить (а если они не проходят, упомяните об этом в сопроводительном сообщении)\n", + "\n", + "\n", + "#### Удаление файлов из репозитория\n", + "\n", + "Рекомендуется удалять файл из папки проекта и репозитория командой ```git rm <название файла>```. Это равносильно простому удалению файла из папки проекта (```rm/del <название файла>```) с добавлением этого изменения в проекте в индекс с помощью команды ```git add <название файла>```.\n", + "\n", + "Команда ```git rm``` работает только с файлами, находящимися в чистом, сохраненном, состоянии без каких-либо изменений. В противном случае Git предложит сохранить изменения или отменить их командой ```git reset HEAD <имя_файла>```\n", + "\n", + "\n", + "#### Переименование и перемещение файлов из репозитория\n", + "\n", + "Команда ```git mv``` показывает гиту, что файл был переименован/перемещён, а не удалён и создан новый файл с тем же содержимым, что и удалённый.\n", + "\n", + "\n", + "### Просмотр журнала коммитов\n", + "\n", + "Команда ```git log``` выводит список всех коммитов с подробным описанием каждого.\n", + "\n", + "Хеш коммита — строка из 40 шестнадцатеричных цифр (0–9 и буквы A–F), которая\n", + "служит уникальным идентификатором коммита (yа практике обычно используются только первые семь знаков)\n", + "\n", + "Чтобы вернуться к более старому коммиту, надо заранее узнать его хеш с помощью команды ```git log```.\n", + "\n", + "Ключ ```--oneline``` укорачивает вывод до сокращенных хешей и первой строки каждого сообщения коммита, ведь со временем журнал может стать очень длинным.\n", + "```bash\n", + "git log --oneline```\n", + "```\n", + "\n", + "Чтобы вывести содержимое файла на момент конкретного коммита, можно задать команду ```git show <хеш>:<имя_файла>```\n", + "\n", + "\n", + "### Восстановление старых изменений\n", + "\n", + "Система контроля версий позволяет вернуть рабочую копию к состоянию более раннего коммита. Конкретная команда зависит от состояния файлов в рабочей копии.\n", + "\n", + "\n", + "#### Отмена несохраненных локальных изменений\n", + "\n", + "Команда ```git restore<имя_файла>``` возвращает выбранный файл к состоянию, сохранённому в последнем коммите. Фактически это операция отмены изменений, внесенных в файл (который еще не был проиндексирован или сохранен).\n", + "\n", + "Важно: невозможно отменить эту «отмену», чтобы вернуть последние изменения\n", + "\n", + "Хотя Ctrl+z в открытом файле сработает:)\n", + "\n", + "\n", + "#### Деиндексирование проиндексированного файла\n", + "\n", + "Команда ```git restore --staged <имя_файла>``` исключает выбранный файл из списка индексированных файлов\n", + "\n", + "\n", + "#### Отмена последних коммитов\n", + "\n", + "Команда ```git revert -n HEAD~<количество коммитов назад относительно текущего>..HEAD``` отменяет конкретное число последних коммитов\n", + "\n", + "Репозитории Git обычно только добавляют информацию, поэтому при отмене коммитов они остаются в истории коммитов. Если потребуется «отменить отмену», можно снова вернуться к нужному состоянию командой ```git revert```.\n", + "\n", + "\n", + "#### Возврат к конкретному коммиту для отдельного файла\n", + "\n", + "Команда ```git show <хеш>: <имя_файла>``` выведет выбранный файл в состоянии, соответствующем коммиту с введённым хешем.\n", + "\n", + "Команда ```git checkout <хеш> -- <имя_файла>``` вернёт содержимое выбранного файла в состоянии, соответствующем коммиту с введённым хешем. Эта команда изменяет только рабочую копию. Чтобы сохранить изменения нужно проиндексировать и закоммитить этот файл.\n", + "\n", + "\n", + "#### Перезапись истории коммитов\n", + "\n", + "Если случайно сохранён файл, содержащий конфиденциальную информацию (пароли, ключи API, номера кредитных карт), недостаточно вычеркнуть эту информацию и создать новый коммит. Каждый, кто имеет доступ к репозиторию на компьютере или к удаленному репозиторию, сможет вернуться к версии, содержащей эту информацию.\n", + "\n", + "Удалить информацию из репозитория так, чтобы ее было невозможно восстановить, непросто, но возможно:\n", + "\n", + "1. командой git filter-branch\n", + "2. программой [BFG Repo-Cleaner](https://help.github.com/en/articles/removing-sensitivedata-from-a-repository.)\n", + "\n", + "Простейшая превентивная мера — разместить конфиденциальную информацию в файле с именем secrets.txt, conidential.py или что-нибудь в этом роде. Файл включается в .gitignore, чтобы он никогда не был сохранен в репозитории.\n", + "\n", + "\n", + "#### GitHub и команда git push\n", + "\n", + "Mногие бесплатные веб-сайты позволяют размещать клоны локальных репозиториев в интернете, чтобы другие люди могли легко загрузить проекты и участвовать в работе над ними. Самый большой из таких сайтов — GitHub.\n", + "\n", + "Плюсы:\n", + "+ другие люди могут участвовать в работе над проектом\n", + "+ коллеги смогут дополнять код, даже если компьютер с локальным репозиторием отключен\n", + "+ клонированная копия фактически выполняет роль резервной копии\n", + "\n", + "**ПРИМЕЧАНИЕ**\n", + "Чтобы избежать путаницы с терминами: Git — система контроля версий, которая поддерживает репозиторий и включает команду git. GitHub — веб-сайт для размещения репозиториев Git в интернете.\n", + "\n", + "Веб-страница для репозиториев будет располагаться по адресу https://github.com/<имя_пользователя>/<имя_репозитория>\n", + "\n", + "\n", + "#### Отправка существующего репозитория на GitHub\n", + "\n", + "Команда ```git remote add origin https://github.com/<имя_пользователя>/<имя_репозитория>``` добавляет GitHub как удаленный репозиторий, соответствующий локальному репозиторию. \n", + "\n", + "Команда ```git push -u origin master``` отправляет все изменения, внесенные в локальном репозитории, в удаленный.\n", + "\n", + "Следующие коммиты можно отправлять командой ```git push```\n", + "\n", + "Хорошая практика - отправлять копии на GitHub после каждого коммита: она гарантирует синхронизацию удаленного репозитория на GitHub с локальным репозиторием. Однако, она не обязательна.\n", + "\n", + "\n", + "#### Клонирование существующего репозитория GitHub\n", + "\n", + "Можно создать новый репозиторий на GitHub и клонировать его на компьютер. Для этого необходимо при создании нового репозитория на веб-сайте GitHub установить флажок ```Initialize this repository with a README```.\n", + "\n", + "Команда ```git clone ``` позволяет клонировать репозиторий на локальный компьютер. Url репозитория можно получить на странице репозитория на GitHub, щелкнув на кнопке Clone или Download: откроется окно с URL-адресом вида https://github.com/<пользователь_github>/<название репозитория>.\n", + "\n", + "Команда ```git clone``` также пригодится в том случае, если ваш локальный репозиторий оказался в состоянии, когда не ясно, что с ним делать и как отказаться от последних изменений. И хотя такое решение далеко не идеально, всегда можно сохранить копию файлов в рабочем каталоге, удалить локальный репозиторий и воспользоваться командой git clone для повторного создания репозитория.\n", + "\n", + "\n", + "### Итоги\n", + "\n", + "Две бесплатные книги, которые можно найти в интернете:\n", + "1. [«Pro Git» Скотта Чаркона (Scott Charcon)](https://git-scm.com/book/en/v2)\n", + "2. [«Version Control by Example» Эрика Синка (EricSink)](https://ericsink.com/vcbe/index.html)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}