Git fork. Зачем нужны форки и как с ними работать

август 16 , 2019

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

Я не сторонник подхода "чо тут не понимать, тупой штоле" и попробую рассказать человеческими словами, что вообще такое форки, зачем они нужны и как с ними работать. А вы оцените, как получилось. Синьор git девелоперам статья покажется банальщиной, но тем, кто еще не успел обрести такой титул, будет полезно.

Начнем с примера.

Ты работаешь в компании Company в какой-то команде и со своими ребятами пишешь код, например, блога вашего сайта. Рядом сидят ребята из другой команды, которые занимаются админкой. У каждой команды отдельный репозиторий, вы работаете и друг другу не мешаете.

Вам приходит задача - дать возможность разрешать или запрещать комментировать статьи блога отдельным пользователям. Сами вы это сделать не можете. Такие данные о пользователях хранятся не на вашей стороне, а у ребят, занимающихся админкой. У них есть списки пользователей и все данные по ним. А вы тянете эти данные по апи. Прямо микросервисы, все как положено.

Доступа к их репозиторию нет, поэтому идете договариваться. Обсуждаете вместе детали. Так, нужно завести поле в базе, какое-нибудь булево isAllowedComments, соответственно, подготовить миграцию, вывести это поле отдельной колонкой в таблице пользователей, там поставить чекбокс и уметь сохранять это в базу. А еще в апи, которое вы дергаете, нужно добавить в респонсе это самое поле. Вроде немного, ребята говорят, окей, через пару дней сделаем. И на самом деле делают, все хорошо.

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

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

Вы с командой соглашаетесь. Ты клонируешь их репозиторий и пилишь фичи. Примерно так

    git clone git@bitbucket.org:company/adminka.git 
    cd adminka
    git checkout -b vasya/blog-comments
    ...
    git commit -m 'Added isAllowedComments for users'
    git push origin vasya/blog-comments

Дальше идешь в битбакеты-гитхабы, в репозиторий админки, делаешь мердж-реквест и ждешь, когда его примут. Обычная схема. Мердж-реквест примерно везде делается одинаково: ищешь кнопку "Создать мердж-реквест" или пулл-реквест, выбираешь свою ветку, затем выбираешь, куда сливать (обычно уже по умолчанию будет мастер) и жмешь "Отправить".

Проходит пара месяцев. Ты случайно замечаешь в репозитории админки ветку petya/update-email. Спрашиваешь ребят из админки, а что за Петя вам коммитит? Те говорят, а, это чувак из отдела емейлов, мы им тоже доступ дали, как и вам. Они тоже приходили к нам по 3 раза в месяц, мы задолбались и теперь с ними работаем по вашей схеме. Ничего, все довольны.

Проходит год. Команд, которые работают по такой схеме, уже десяток. В репозитории появляются ветки

  • vasya/blog-user-ban
  • petya-ivanov/email_new_field
  • email/migration
  • blog/hotfix
  • petrov/srochno-v-prod

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

Конечно, ребятам из админки не очень нравится такой мусор в их репозитории. Сначала они пытаются с этим бороться и проводить разъяснительные работы. Пытаются рассказать о правилах приличия в их репозитории. Пишут доку и официальное письмо всем программистам, где все подробно рассказывают. Как именовать ветки, как подписывать коммиты, не забывать удалять старые ветки, не заводить лишние ветки без надобности и прочее.

Это дело хорошее, но бесполезное. В компании полсотни разрабов, у каждого своя команда и свои правила работы с репозиторием. Люди приходят и уходят, эти правила уже никто не помнит, да и всем пофигу, главное фичу сделать, чего там заморачиваться с ветками и коммитами. Пусть у команды админки об этом голова болит. Главное, у нас все хорошо, в своем командном проекте, потому что мы никого к себе не пускаем, ахаха. Поэтому и ветки красиво называются, и коммиты адекватно подписаны. Нас тут 5 человек работают, уж между собой-то договоримся.

А между тем в репозитории админки образуется все больший трэш. То злодеи опять пушат ветки с названиями не по ГОСТу, и тимлида бесят. То сам тимлид с похмелья выдал новому чуваку доступы на пуш в мастер, а тот на радостях запушил миграцию, которая пол-сайта уронила. То по ошибке смерджили petya/hotfix вместо vasya/hotfix. В общем весело всем, кроме ребят из админки.

И вот однажды что-то изменилось. Тебе понадобилось запилить новую фичу и ты привычно набиваешь

    git checkout master
    git pull --rebase origin master
    git checkout -b vasya/fix-comments
    ...
    git push origin vasya/fix-comments
    waiting...
    
    Rejected

Опа, что за фигня? Пробуешь еще раз на всякий случай - снова rejected. Пишешь команде админки

  • репца, привет, я чот запушить вам не могу, вы права сняли?
  • привет, Петя, да, мы убрали права на пуш для всех не-членов нашей команды
  • эээ, ну во-первых, я Вася, а во-вторых, как мне теперь делать?
  • теперь все мердж-реквесты принимаются из форков
  • окей, а на фига это надо? Все равно же в мастер нельзя было запушить, все и так через мердж-реквесты было...
  • видишь ли, Вася, у нас тут столько народа, что мы уже не понимаем, кто Вася, а кто Петя, а кто вообще мимо проходил. И в ваших ветках мы тут просто тонем, git fetch невозможно сделать. Мы пытались донести до коллег, что это наш репозиторий и мы просим соблюдать простые правила работы с ним. Но народа много и все решили, что наш проект это помойка, в которой можно делать, что угодно. Все равно ж в мастер не попадет, а там разберутся. Ну и пара инцидентов с неправильно выданными правами. Да, наш косяк, но вас слишком много, чтобы за каждым уследить. Короче, форкайте репозиторий и резвитесь там, как хотите. А нам отправляйте только мердж-реквесты. Вам без разницы, а нам спокойней и в репозитории чище.
  • окей, понятно

Понятно-то оно понятно, но ты с форками не работал. Ладно, думаешь, разберешься же, не тупой. Мердж-реквест что ли из форка не отправишь? К тому же ты читал git-scm и знаешь, что форк - это просто копия репозитория. Начинаешь разбираться.

Сначала идешь в гитхаб-битбакет и ищешь там в нужном репозитории кнопку Fork. Обычно она недалеко от кнопки clone. Жмешь на fork и для тебя создается проект. Если исходный был company/adminka.git, то твой будет примерно vasya/adminka.git. Ну или примерно так. Дальше клонируешь его как обычно

    git clone git@bitbucket.org:vasya/adminka.git 

Естественно, свой форк клонируешь, а не оригинальный. Затем там создаешь привычно ветку и пушишь ее.

    git checkout -b blog/new-field
    ...
    git push origin blog/new-field

Заходишь в гитхаб-битбакет исходного репозитория, жмешь "Создать мердж-реквест", выбираешь свою ветку, она будет называться примерно vasya/adminka/blog/new-field, и ждешь, пока мердж-реквест примут.

Пока все ровно так, как ты привык, ничего нового. Мердж-реквест принимают и все хорошо.

Через месяц тебе нужно сделать еще одну задачу. Ты привычно подтягиваешь мастер и настораживаешься

    git pull --rebase origin master 
    From bitbucket.org:vasya/adminka
    Current branch master is up to date.

За месяц нет новых коммитов в мастере? Да не верю. Идешь в репозиторий админки, смотришь, там до фига коммитов, чуть не каждый день в мастер пушат. В чем дело?

Присматриваешься, откуда ты пулишься и видишь, что это vasya/adminka. Это твой репозиторий, твой форк. Конечно, ты его месяц не трогал и он ничего не знает о новых коммитах в исходном проекте. Их нужно подтянуть и только тогда создавать новую ветку. Можно сделать это так

    git pull --rebase git@bitbucket.org:company/adminka.git master 

То есть вместо origin указываешь адрес нужного репозитория. И вот теперь-то подтянется мастер именно исходного проекта, а не твоего. А еще лучше сделать так, чтобы не набивать каждый раз длинный адрес

    git remote add upstream git@bitbucket.org:company/adminka.git

Теперь у тебя есть origin - твой репозиторий, твой форк, а есть upstream - оригинальный репозиторий. И ты можешь пулиться, указывая сразу upstream

    git pull --rebase upstream master

Вот теперь твой мастер актуален, можешь создавать ветку и пушить в репозиторий. Пушить уже в origin, то есть свой, потому что в upstream, исходный, тебе пушить никто не даст. То есть еще раз, пулишь мастер так

    git pull --rebase upstream master

а пушишь свою ветку так

    git push origin branch-name

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

    git checkout master 
    git pull --rebase upstream master
    git checkout branch-name
    git rebase master
    git push -f origin branch-name

Тут можешь делать, как хочешь, твой форк, твои правила. Можешь пушить с форсом, как у меня в примере. Если не хочешь с форсом, то можешь создать отдельную ветку и положить коммит в нее. Как угодно. Главное, чтобы твои коммиты лежали поверх свежих коммитов из мастера. Тогда никто не будет возникать при рассмотрении мердж-реквеста, а ты будешь уверен, что у тебя самые свежие обновления.

Подробнее почитать про ребейз можно здесь - git merge и rebase.

И на этом все. Главное, что нужно сделать, это добавить upstream и четко понимать, в чем его отличие от origin.

С форками можно работать и в компании на полсотни разработчиков, но особенно это популярно в опенсорсе. Возьмите какой-нибудь проект, например, vuejs, у него больше 20 тысяч форков и 3 сотни контрибьюторов. Представьте, что бы творилось в репозитории, пусти всех этих энтузиастов пушить свои правки. А так они спокойно работают со своими форками и присылают пулл-реквесты, не засоряя проект.

Всем удачи. Любите гит, он совсем не страшный :-)

P.S. Пожалуй, это самая большая статья про форки, которую можно было написать =))

P.P.S. И небольшой опрос напоследок

Все статьи о git

Заходите в группу в контакте - https://vk.com/webdevkin
Анонсы статей, обсуждения интернет-магазинов, vue, фронтенда, php, гита.
Истории из жизни айти и обсуждение кода.
Как Вам статья? Оцените!