Программирование и IT

Как создать репозиторий с нуля

Репозиторий — это папка проекта плюс скрытая папка `.git`, в которой хранится вся история. Создаётся одной командой, но между ней и первым осмысленным коммитом есть несколько шагов, которые потом трудно переделать: имя ветки, список игнорируемых файлов, привязка к серверу.

Обновлено
В этой статье

Что создаёт git init#

$ mkdir invoice-tool && cd invoice-tool
$ git init
Initialized empty Git repository in /home/user/invoice-tool/.git/

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

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

Есть второй вид — голый репозиторий, у которого нет рабочей копии, только
база:

git init --bare /srv/git/invoice-tool.git

Такой создают на сервере, чтобы в него отправляли изменения. На своей машине
он не нужен.

Имя ветки по умолчанию#

До git 2.28 первая ветка всегда называлась master. Теперь имя настраивается,
и у большинства сервисов по умолчанию main. Договориться с самим собой
удобнее один раз и навсегда:

$ git config --global init.defaultBranch main
$ git init
Initialized empty Git repository in /home/user/invoice-tool/.git/
$ git branch --show-current
main

Если репозиторий уже создан со старым именем, ветку переименовывают:
git branch -m master main. Это работает и до первого коммита, когда ветка
ещё «не родилась»: переименовывается сама ссылка HEAD.

Первый коммит#

Три шага: представиться, отобрать файлы, зафиксировать.

$ git config --global user.name "Мария Ковалёва"
$ git config --global user.email "m.kovaleva@example.com"
$ git add .
$ git commit -m "каркас проекта"
[main (root-commit) 4a1d7c9] каркас проекта
 3 files changed, 41 insertions(+)
 create mode 100644 README.md
 create mode 100644 app.py
 create mode 100644 requirements.txt

Пометка root-commit означает, что у коммита нет родителя: это самое начало
истории. Имя и почту git подставит в каждый коммит, и позже переписать их у
готовой истории трудно, поэтому заполнять стоит до первого коммита.

Проверить, что получилось, помогает
просмотр истории через git log — после первого коммита он
покажет ровно одну строку.

.gitignore до первого add#

Самая частая беда новичка — закоммитить виртуальное окружение, папку сборки и
файл с паролями, а потом вычищать это из истории. Проще написать список
исключений заранее, обычным текстовым файлом .gitignore в корне:

venv/
node_modules/
__pycache__/
dist/
.env
*.local.yml
.DS_Store
.idea/

Здесь четыре группы подряд: окружение и сборка, секреты и локальные настройки,
мусор системы и редактора. Пояснения в файле пишут строкой, начинающейся с
решётки.

Правило простое: в репозиторий идёт то, что написано человеком; всё, что
порождается командой сборки или установкой зависимостей, остаётся снаружи.

Проверить, что файл действительно игнорируется, можно так:

$ git check-ignore -v .env
.gitignore:5:.env	.env

Вывод показывает, какая строка какого файла сработала. Пусто — значит файл не
игнорируется.

Оговорка: .gitignore действует только на неотслеживаемые файлы. Если файл
уже попал в индекс, его сначала убирают оттуда, сохранив на диске:
git rm --cached .env.

Превратить существующую папку в репозиторий#

Отличий от пустого проекта всего два: сначала пишется .gitignore, потом
смотрится, что именно попадёт в первый коммит.

$ cd ~/projects/old-site
$ git init
$ printf 'node_modules/\ndist/\n' > .gitignore
$ git add .
$ git status -s
A  .gitignore
A  index.html
A  styles/main.css
$ git commit -m "перенос проекта под контроль версий"

Строку git status -s пропускать не стоит: ровно здесь ловятся забытые
гигабайтные архивы и чужие ключи. Лишнее убирается из индекса
git restore --staged <файл>, и правится список исключений.

Привязка к серверу и первая отправка#

Репозиторий на своей машине уже полноценный: коммиты, ветки, история работают
без всякой сети. Сервер нужен только для копии и совместной работы. Создай
на нём пустой проект (без README, чтобы не разошлись истории) и подключи:

$ git remote add origin https://github.com/user/invoice-tool.git
$ git remote -v
origin	https://github.com/user/invoice-tool.git (fetch)
origin	https://github.com/user/invoice-tool.git (push)
$ git push -u origin main

Флаг -u связывает локальную main с серверной, после чего хватает короткого
git push. Если сервер отвечает Updates were rejected because the remote contains work that you do not have locally, значит там уже что-то есть —
обычно автосозданный README. Забери его: git pull --rebase origin main, и
отправляй снова. Форсировать отправку в этот момент нельзя, это сотрёт
содержимое на сервере.

Частые ошибки#

git init запущен не в той папке. Признак — git status показывает сотни
чужих файлов, а в домашней папке появилась .git. Лечится удалением: rm -rf ~/.git (внимательно проверь путь), после чего git init повторяется уже
внутри проекта.

Вложенный репозиторий. git init внутри папки, которая уже под контролем
версий, создаёт второй репозиторий; родитель начинает видеть эту папку как
единый объект и не отслеживает её содержимое. Проверить текущий корень:
git rev-parse --show-toplevel.

Секрет уже в коммите. Удалить файл следующим коммитом мало — в истории он
останется. Если коммит ещё не отправлен, помогает
отмена коммита; если отправлен, пароль считается
скомпрометированным и его меняют, а историю чистят отдельными инструментами.

План по этапам

  1. Настроить git один разuser.name, user.email и init.defaultBranch main через git config --global.
  2. Создать репозиторийgit init в папке проекта; проверить корень через git rev-parse --show-toplevel.
  3. Написать .gitignoreЗависимости, сборка, секреты, мусор редактора — до первого git add.
  4. Сделать первый коммитgit add ., просмотр git status -s, затем git commit -m с осмысленным сообщением.
  5. Подключить серверgit remote add origin <адрес> и git push -u origin main.

Начать изучать эту тему у себя

План ляжет в твой репозиторий: отмечай этапы, веди конспект — история изменений покажет, как ты продвинулся.

Начать план

Проверь себя

1.Какая команда превращает обычную папку в репозиторий git?

2.Файл .env уже был закоммичен. Что уберёт его из-под наблюдения git, но оставит на диске?

3.Что означает пометка root-commit в выводе git commit?

Источники

  • Справка git initЧто именно создаётся и какие есть режимы
    бесплатно
  • Pro Git, русское изданиеГлавы «Введение» и «Основы Git» — установка, настройка, первый репозиторий
    бесплатно
  • Справка gitignoreСинтаксис шаблонов, порядок правил, отрицания
    бесплатно

Было полезно?

Ещё темы

Программирование и IT git clone Команда git clone забирает репозиторий с сервера целиком — со всей историей, ветками и тегами — и кладёт копию в новую папку на твоём компьютере. С неё начинается работа с любым уже существующим проектом, своим или чужим. Программирование и IT git branch Ветка в git — это подвижный указатель на коммит, а не копия файлов. Поэтому завести её ничего не стоит, а команда git branch отвечает за список веток, их создание, переименование и удаление. Программирование и IT Python: классы Класс описывает, из каких данных состоит объект и что он умеет делать. Конструктор `__init__` заполняет новый объект, `self` — ссылка на него самого. Ниже — минимальный рабочий класс, разница между атрибутом класса и атрибутом экземпляра и способы сделать код короче. Программирование и IT git push Пока ты не выполнил git push, твои коммиты существуют только на твоём диске. Команда отправляет их в удалённый репозиторий и сдвигает там указатель ветки — поэтому она же чаще всего и отказывает, если кто-то успел отправить своё раньше. Программирование и IT git commit Коммит — это сохранённое состояние проекта с автором, временем и сообщением. Команда git commit берёт то, что ты заранее отобрал командой git add, и записывает это в историю одной неделимой порцией. Программирование и IT git merge Слияние переносит работу из одной ветки в другую. Команда git merge берёт указанную ветку и соединяет её историю с текущей — иногда просто сдвигая указатель, иногда создавая отдельный коммит, а иногда останавливаясь и прося помощи.

Ещё сценарии