Руководство для контрибьюторов в проекты с открытым исходным кодом

Пошаговое руководство для желающих внести свои изменения в открытый проект и правильно оформить запрос на слияние (Pull Request).

Зависимости

  • Скачать и установить git под вашу ОС

Минимальная настройка git для работы

  • Установить Имя автора, от которого будут совершаться изменения

    git config --global user.name "Ivan Ivanov"
    
  • Установить email, от которого будут совершаться изменения

    git config --global user.email ivan-ivanov@gmail.com
    
  • Установить имя интеграционной ветки по умолчанию

    git config --global init.defaultBranch main
    
  • Установить настройку корректного отображения кириллицы в путях

    git config --global core.quotePath false
    
  • При необходимости изменить редактор по умолчанию вместо стандартного редактора vim, на тот который вам по душе (редактор используется для ввода сообщений коммитов)

    git config --global core.editor code
    
  • Посмотреть текущие настройки git

    git config --list --show-origin
    

Найдите проект на GitHub

  • Найти интересущий вас проект на GitHub
  • Изучить документацию проекта и правила по его доработке (если таковые есть)

Создайте issue под задачу

Каждая новая функция или исправление бага должны быть привязаны к issue (задаче, тикету). Это помогает организовать работу в одном месте: там можно найти всю историю запросов на слияние (Pull Request), комментарии участников и принять участие в обсуждении задачи.

  • В оригинальном проекте автора на GitHub зайти в раздел issue
  • Убедиться, что под задачу, над которой вы собираетесь работать есть issue
  • Если issue существует - убедиться, что никто не взял его в работу
  • Если issue не существует - создать, перед этим ознакомится с кратким руководством GitHub issues
  • Оставить комментарий, чтобы другие участники знали, что вы работаете над этой задачей

Сделайте Fork репозитория проекта

Fork - это не команда Git, это функция хостингов репозитория (например GitHub). Fork делает копию проекта из профиля автора в ваш профиль. При этом адрес репозитория, в который вы будете вносить доработки физически меняется - он теперь в вашем профиле. Эта технология позволяет легко производить доработки проекта, отправляя их затем в ваши форк-репозитория, так как вам не потребуется запрашивать права, чтобы внести изменения в оригинальный репозиторий автора.

  • В оригинальном репозитории автора в правом верхнем углу страницы нажать на меню Fork и выбрать Create a new fork

Если форк репозитория уже был создан ранее перейдите к следующему шагу.

Синхронизируйте Fork из веб интерфейса GitHub

Синхронизировать ваш fork-репозиторий необходимо чтобы поддерживать его в актуальном состоянии относительно оригинального репозитория автора. Синхронизируя fork-репозиторий мы догоняем по изменениям оригинальный репозиторий проекта.

  • Из своего профиля на GitHub перейдите к fork-репозиторию, который вы создали на прошлом шаге
  • Над списком файлов нажмите на меню Sync fork затем Update branch
  • Если синхронизация выполнена успешно или fork-репозиторий содержит последние изменения из оригинальногое репозитория, то при последующем нажатии на Sync fork вы увидите надпись This branch is not behind the upstream

Склонируйте Fork на локальную машину

Клонирование на локальную машину необходимо для непосредственного внесения доработок по вашей задаче (issue)

  • В вашем fork-репозитрии на GitHub нажмите на кнопку Code (находится над кнопкой Sync fork) и скопируйте ссылку на закладке HTTPS, обычно она имеет вид https://github.com/ваш-профиль/форк-репозиторий.git
  • Откройте консоль на вашей локальной машине
  • Перейдите в папку где хранятся (или планируете хранить) git проекты
  • Склонируйте fork-репозиторий с помощью команды

    git clone https://github.com/ваш-профиль/fork-репозиторий.git
    
  • При успешном клонировании вы увидите созданную директорию с названием проекта

Если клон репозитория уже был создан ранее перейти к следующему шагу.

Создайте функциональную ветку под задачу в локальном репозитории

Ветки позволяют разработчику сохранять разные изменения полностью независимо друг от друга. Вы можете работать над разными вещами одновременно, не смешивая изменения между собой. Ветка отражает историю коммитов. Ветки - это разные истории коммитов. Ветка - это просто ссылка на коммит по его ID, эта ссылка каждый раз обновляется когда вы делаете новый коммит. В любой момент времени можно создать новую ветку, переключиться между ветками, отказаться от ветки (т.е. отказаться от всей работы, которую вы в неё вложили), объединить ветки.

  • Перейти в рабочий каталог (локальный репозиторий)

    cd projects/название-склонированного-репозитрия
    
  • Переключиться на ветку main

    git checkout main
    
  • Догнать в локальном репозитории изменения fork-репозитория

    git pull
    
  • Создать локальную ветку под задачу

    git checkout -b feat/37/issue-name
    
    • feat - тип коммита (соглашение о коммитах)
    • 37 - номер задачи issue в основном репозитории проекта на GitHub, позволяет при использовании команды git status сразу держать его перед глазами не тратя времени на поиски задачи
    • issue-name - наименование задачи, обычно просто берется название задачи (issue) на GitHub переводится в нижний регистр, пробелы заменяются на дефисы и осталвяют только значимые слова. Помните давая четкое, но краткое описание задачи, вы облегчаете себе понимание о чем это задача, или на каком моменте вы остановились, переключаясь между ветками

Внесите изменения в локальный репозиторий по задаче

  • Напишите код, который решает вашу задачу
  • Проверьте, что ваш код работает и ничего не ломает (проведите unit-тестирование)
  • При необходимости дополните документацию проекта описывающую ваши изменения

Добавьте ваши изменения по задаче в локальном репозитории в индекс

Команда git add создаёт копию файла, помещает его в индекс (специальную область для временного хранения данных) и начинает отслеживать все последующие изменения. Файлу присваивается статус “подготовленный” (staged), что означает его готовность к фиксации в коммите. Индекс можно сравнить с черновиком, где вы можете вносить правки до момента, пока не решите зафиксировать изменения. Каждый зафиксированный коммит сохраняет состояние файлов таким, каким оно было на момент добавления в индекс.

  • После изменений проверьте состояние вашего репозитория, и убедитесь что изменения коснулись только файлов над которыми вы работали

    git status
    
  • При необходимости посмотрите детали по вашим изменениям (разницу между текущим состоянием репозитория и последним коммитом)

    git diff
    
  • Добавьте изменения в индекс

    git add file-1 file-2
    
    • Можно добавить все измененные файлы в индекс в текущей директории без ручного перечисления командой git add .

Зафиксируйте ваши изменения по задаче в локальном репозитории

Команда git commit фиксирует все изменения в файлах, предварительно добавленных в индекс (git add), сохраняя их в объектной базе Git и помечая как неизменяемые. Каждый коммит представляет собой фиксацию состояния файлов на определённый момент времени. По сути, коммит — это снимок всех изменений, которые были включены в индекс. Он сохраняет состояние индекса в тот момент, когда вы решили зафиксировать изменения. Важно сопровождать коммит пояснительным сообщением, описывающим внесённые изменения. В процессе создания коммита формируется объект, который содержит метаданные, такие как ссылка на зафиксированные файлы, имя и электронная почта автора, временная метка коммита и текстовое сообщение.

  • Проверьте состояния репозитория после добавления измененных файлов в индекс, текст вывода должен содержать сообщение Changes to be commited под которым будет список файлов, которые были добавлены в индекс

    git status
    
  • Зафиксируйте (commit) изменения

    git commit
    
  • После ввода команды откроется встроенный редактор для редактирования сообщения коммита
  • Введите сообщение коммита

    feat: добавить обработчик редактирования текста (#37)
    
    • feat - тип коммита (соглашение о коммитах)
    • 37 - номер задачи issue в основном репозитории, необходимо чтобы привязать коммит к issue на GitHub

Правила написания хороших сообщений коммитов

  • Всегда пишите осмысленные сообщения коммитов, это позволит вам легко понять цель внесённых изменений, если в будущем потребуется вернуться к этому коммиту в истории проекта
  • Рекомендуется использовать повелительное наклонение в сообщениях коммитов. Вместо фраз вроде “обновлена документация проекта” или “исправлена ошибка авторизации”, формулируйте сообщения так, будто вы даёте команду компьютеру. Например, напишите “обновить документацию проекта” или “исправить ошибку авторизации”.
  • Используйте команду git commit без флага -m и каких либо флагов вообще - это вызовет открытие вашего редактора для сообщения коммита по умолчанию, где вы можете написать осмысленное хорошее сообщение коммита. Плюс данного подхода так же в том, что в редакторе можно вводить спец символы, которые достаточно сложно бывает экранировать при вводе сообщение коммита прямо в командной строке
  • Пишите сообщение коммита так же, как вы пишите электронное письмо - с заголовком и, необязательно, с телом
  • Заголовок коммита от тела отделяется пустой строкой
  • В заголовке коммита постарайтесь кратко описать, о чем этот коммит
  • Если вам нужно уточнить, почему было сделано это изменение опишите это в теле коммита
  • Сообщение коммита должно фокусироваться на “причинах” изменения, а не на том “как” или “что” сделано. Конечно, это не всегда возможно, но об этом стоит помнить
  • Тип коммита обычное следует из типа задачи, которую вам поставили, лучше заранее посоветоваться с командой и задокументировать список типов, чтобы использовать их единообразно
  • Помните что опечатку в тексте коммита, можно исправить применением флага --amend

Отправьте свои изменения из локального репозитория в удаленный Fork репозиторий на GitHub

  • Отправьте изменения в ваш удаленный fork-репозиторий на GitHub

    git push -u origin feat/37/issue-name
    

Создайте запрос на слияние (Pull Request) из Fork репозитория в оригинальный репозиторий проекта

Pull Request позволяет создать запрос на слияние одной ветки в другую (в обычном случае запрос на слияние рабочей ветки в интеграционную) в удаленном репозитории. Создавая pull request мы показываем коллегам свои намерения выгрузить свою работу в интеграционную ветку, и они видят какие изменения будут внесены. Запрос на слияние также дает возможность вашим коллегам предложение о том, как бы вы могли улучшить или изменить вашу работу. Можно назначать конкретных рецендентов, отвественных за просмотр запроса и принятия решения о том, что работа выполнена качественно и точно. Вы можете рассматривать запрос на слияние, как публичное слияние с голосованием - ваши коллеги получат возможность просмотреть вашу работу, прежде чем она станет частью целого.

  • Перейдите в свой fork-репозиторий на GitHub и нажмите Pull Request
  • Выберите свою ветку
  • В комментарии напишите Close #37 - это позволит связать запрос на слияние (Pull Request) и задачу (issue) по ее номеру, и если ваши дороботки будут слиты с интеграционной веткой - задача будет автоматически закрыта благодаря такому связыванию

Если после запроса на слияние вам делают замечание, которое надо исправить, вы можете открыть свою локальную ветку внести в нее требуемые изменения сделать коммит и повторно выгрузить ветку в удаленный репозиторий, и снова подать запрос на слияние, при этом старый запрос (pull request) будет автоматически обновлен, чтобы отразить все коммиты в вашей ветке, и ваши коллеги могут посмотреть его повторно, чтобы убедиться что замечание было устранено.

Ожидайте реакции автора оригинального репозитория

  • В идеальном случае ваши доработки будут одобрены и слиты в интеграционную ветку оригинального проекта
  • Автор так же вправе сделать вам предложения доработать ваши изменения, если он посчитает, что изменения в них нуждаются

Удалите функциональную ветку

Удаление функциональных веток после слияния не приносит никакого вреда - история коммитов остаётся. Удаление функциональной ветки до слияния завершится ошибкой.

  • После слияния вашей функциональной ветки с интеграционной веткой автора, синхронизируйте (догоните) эти изменения в вашем fork-репозитории
  • Удалите функциональную ветку в fork-репозитории в разделе branches (https://github.com/имя-профиля/проект/branches)
  • Обновите ваш локальный репозиторий из fork-репозитория:
    • переключитесь на интеграционную ветку
      git checkout main
    
    • обновите локальный репозиторий
      git pull
    
  • Так как теперь интеграционная ветка содержит все последние изменения, включая ваши доработки, удалите функциональную ветку
  git branch -d имя-функциональной-ветки

Обновить ветки слежения

  • Очистите все ветки слежения (remote), у которых больше нет объекта в удаленном репозитории и получите все новые ветки и коммиты, которые отображаются на удаленном сервере следующей командой:
  git fetch --prune

Ссылки на полезные материалы