Путь контрибьютора


Успех Гитхаба в большой степени обеспечила простота и лёгкость нанесения пользы в небезразличные тебе проекты — форкай да пуллриквесть!

Действительно, внести одно небольшое изменение в сторонний репозиторий очень просто. Но после того, как ты форкнул репозиторий, ты уже не можешь просто взять и притянуть к себе порцию новых изменений из апстрима. Как результат — конфликты в коде и головная боль. К сожалению, в интерфейсе Гитхаба никак нельзя синхронизировать свой форк с апстримом (а может и можно, но куда-то далеко запрятано). Вот и сейчас в проекте словаря терминов по фронтенду висят пара пулл-риквестов, в которые нужно притянуть изменения из основной ветки.

Как эту проблему решаю отдельно взятый я? Покажу на примере вышеупомянутого проекта.

Шаг 1. Форк репозитория. Ну, вы все это умеете — нажал кнопочку — и понеслась. Потом клонируем репозиторий к себе на жёсткий диск.

$ git clone git@github.com:h4/dictionary.git ~/projects/wst-dictionary

Обратите внимание, я явно указал назване каталога в который будет склонирован репозиторий. Слово dictionary слишком общее, вдруг я потом буду работать над каким-то другим словарём.

Шаг 2. Добавляем второй репозиторий. Делаем это для того, чтобы в любой момент иметь возможность получить актуальные файлы из апстрма.

$ git remote add wst git@github.com:web-standards-ru/dictionary.git

Теперь, если выполнить команду git remote -v мы увидим, что наша рабочая копия может получать данные из двух удалённых репозиториев:

origin  git@github.com:h4/dictionary.git (fetch)
origin  git@github.com:h4/dictionary.git (push)
wst git@github.com:web-standards-ru/dictionary.git (fetch)
wst git@github.com:web-standards-ru/dictionary.git (push)

Шаг 3. Создаём новую ветку. Каждый свой вклад в общий проект мы будем оформлять в виде отдельного пулл-риквеста. Пусть все изменения сразу живут в отдельной ветке.

$ git checkout -b fix_typo

Вообще, никогда, вы слышите, никогда не делайте две разных фичи в одной ветке. Если одна из них окажется годной, а другая — не очень, как вы будете всё это разруливать? И называйте ветку осмысленно, а не patch-4.

Шаг 4. После того, как сделали всю нужную работу — отправим изменения в наш репозиторий.

$ git push origin fix_typo

Гит отправит изменения в ваш репозиторий (github.com:h4/dictionary в моём случае) и создаст там новую ветку. Теперь можно идти в веб-интерфейс гитхаба и оформлять пулл-риквест. Если вдруг мантейнер скажет, что что-то нужно ещё подправить — не нужно создавать новой ветки. Делаем изменения в ветке fix_typo, снова проталкиваем в свой репозиторий и магия гитхаба обновит ваш пулл-риквест. Возможно, придётся сделать несколько изменений, прежде чем ваш пулл-риквест примут.

Шаг 5. Ура, наш пулл-риквест принят, теперь можно нужно синхронизировать наш репозиторий с апстримом. Вот тут-то нам и пригодится наш второй ремоут.

$ git pull wst master:master

Этой командой мы говорим гиту — возьми из репозитория wst ветку master и слей с локальной веткой master (соответствие веток задаётся последним аргументом, через двоеточие).

Шаг 6. Проталкиваем изменения в наш удалённый репозитоий.

$ git push origin master

Всё, теперь ветка master в нашей рабочей копии синхронизирована с апстримом и нашим собственным репозиторием. Можно продолжать наносить пользу.

Если в процессе работы над первой фичей вы вдруг понимаете, что неплохо было бы прямо сейчас сделать ещё пару совершенно других улучшений, то прежде всего синхронизируемся с апстримом:

$ git pull wst master:master

Теперь мы можем создать новую ветку и переключиться в неё:

$ git checkout -b add_section_term master

Мы в явном виде указываем, что ветку add_section_term нужно отпочковать от ветки master которую мы только что слили с апстримом. Теперь можно выполнить шаги с 4-го по 6-й.

Разрешение конфликтов

Допустим, случилась такая история — вы создали ветку `refactor`, долго и плодотворно в ней работали, а когда решили создать пулл-риквест, оказалось, что апстрим убежал далеко вперёд и теперь у вас конфликты версий. Что делать? Ответ — подлить апстрм в свою ветку и разрешить конфликты.

Шаг 1. Синхронизируем master с апстримом:

$ git pull wst master:master

Шаг 2. Вливаем изменения в нашу ветку `refactor`. Убедитесь, что вы находитесь в этой ветке.

$ git merge master

Если на этом шаге мы получаем конфликты, то нужно их разрешить и завершить слияние коммитом. После чего можно со спкойной душой отправить пулл-риквест.

И да пребудет с вами опенсорс!