Что такое fork
Fork (форк) на GitHub — это ваша личная копия чужого репозитория в вашем аккаунте. В ней вы можете делать что угодно, а в оригинал предлагаете изменения через pull request. Форк нужен, когда у вас нет права записи в чужой проект. В популярных open source проектах его нет ни у кого, кроме нескольких сопровождающих. В уроке вы форкнете учебный репозиторий, сделаете правку и пройдёте весь путь, как в настоящем проекте.
До сих пор вы работали в своём portfolio: там вам разрешено всё, включая push. Попробуйте сделать push в чужой репозиторий — GitHub откажет. Fork решает эту проблему так: вам не нужно разрешение, потому что вы работаете в собственной копии.
Простыми словами
В библиотеке нельзя писать в оригинальной книге. Зато можно сделать ксерокопию, поправить её и принести библиотекарю список правок с просьбой исправить оригинал. Fork — ксерокопия, pull request — список правок, библиотекарь — владелец оригинала.
Fork, clone и ветка: не путайте
| Понятие | Что это | Где живёт |
|---|---|---|
| Fork | Копия репозитория с сохранением связи с оригиналом | На GitHub, в вашем аккаунте |
| Clone | Копия репозитория с историей для работы | На вашем компьютере |
| Ветка | Параллельная линия истории внутри репозитория | Внутри одного репозитория |
Типичная цепочка в open source: fork (копия на GitHub), затем clone этого форка на компьютер, затем ветка, коммиты, push в форк и pull request из форка в оригинал.
Как сделать fork
- Откройте страницу репозитория и нажмите кнопку Fork в правом верхнем углу.
- В выпадающем списке Owner выберите свой аккаунт. Поле Repository name по умолчанию совпадает с названием оригинала, поле Description необязательное.
- Флажок Copy the DEFAULT branch only можно оставить: для работы хватает основной ветки.
- Нажмите Create fork.
Для тренировки возьмите репозиторий octocat/Spoon-Knife. Это учебный репозиторий самого GitHub (его описание: «This repo is for demonstration purposes only»), и его README прямо предлагает сделать fork и попрактиковаться. Свой portfolio форкать не нужно.
Fork, clone, ветка, pull request
После Create fork у вас появился репозиторий alex-ivanov/Spoon-Knife (со своим логином), а под названием — пометка, что это форк. Теперь клонируйте именно свой форк, а не оригинал. Из папки ~/projects, а не изнутри portfolio:
$ cd ~/projects
$ git clone https://github.com/alex-ivanov/Spoon-Knife.git
Cloning into 'Spoon-Knife'...
...
$ cd Spoon-Knife
$ git remote -v
origin https://github.com/alex-ivanov/Spoon-Knife.git (fetch)
origin https://github.com/alex-ivanov/Spoon-Knife.git (push)
Здесь origin — ваш форк, и вы можете в него писать. Работаем по привычной схеме, главное — не в main, а в отдельной ветке. Файл README.md между командами switch и add вы правите в редакторе: допишите в его конец строку, например «Alex Ivanov practiced forks here.»
$ git switch -c add-practice-line
Switched to a new branch 'add-practice-line'
$ git add README.md
$ git commit -m "Добавить строку в README"
[add-practice-line 47b9be0] Добавить строку в README
1 file changed, 1 insertion(+)
$ git push -u origin add-practice-line
To https://github.com/alex-ivanov/Spoon-Knife.git
* [new branch] add-practice-line -> add-practice-line
branch 'add-practice-line' set up to track 'origin/add-practice-line'.
Теперь откройте pull request. Так это выглядит в настоящем вкладе в чужой проект:
- Нажмите Compare & pull request в жёлтом баннере. Если баннера нет, используйте compare across forks на странице сравнения.
- В выпадающем списке base выберите ветку оригинала, в которую хотите влить правку, в списке head fork — свой форк, в списке compare — ветку
add-practice-line. - Заполните заголовок и описание. На форке, который принадлежит вам, можно оставить флажок Allow edits from maintainers: сопровождающие смогут сами поправить мелочи.
- Нажмите Create pull request.
Для тренировки отправляйте PR в свою копию
Пока вы осваиваетесь, не засоряйте оригинал: на странице создания PR откройте выпадающий список репозитория слева (base repository) и выберите свой форк. Тогда PR откроется внутри alex-ivanov/Spoon-Knife, и вы сами его слитите. Для настоящего вклада в чужой проект репозиторий слева остаётся оригинальным.
Upstream и Sync fork
Оригинал не стоит на месте: сопровождающие и другие участники вливают в него новые PR. Ваш форк сам не обновляется, и со временем он отстаёт. Чтобы получать новое, добавьте в клон второй удалённый репозиторий и назовите его upstream (по-русски «вышестоящий»: так принято называть оригинал).
$ git remote add upstream https://github.com/octocat/Spoon-Knife.git
$ git remote -v
origin https://github.com/alex-ivanov/Spoon-Knife.git (fetch)
origin https://github.com/alex-ivanov/Spoon-Knife.git (push)
upstream https://github.com/octocat/Spoon-Knife.git (fetch)
upstream https://github.com/octocat/Spoon-Knife.git (push)
Договорённость простая: origin — ваш форк, куда вы пушите, upstream — оригинал, откуда вы только забираете. Теперь можно подтянуть чужие новые коммиты. Допустим, у оригинала появился новый коммит:
$ git fetch upstream
From https://github.com/octocat/Spoon-Knife
4bc59d0..a941017 main -> upstream/main
$ git switch main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
$ git merge upstream/main
Updating 4bc59d0..a941017
Fast-forward
index.html | 1 +
1 file changed, 1 insertion(+)
$ git push origin main
To https://github.com/alex-ivanov/Spoon-Knife.git
4bc59d0..a941017 main -> main
Разбор по строкам
git fetch upstream— скачать новые коммиты оригинала; ничего не меняет в ваших файлах. Строка-> upstream/mainпоказывает запомненную копию ветки оригинала.git merge upstream/main— влить её в ваш локальныйmain; тот жеmerge, что вы знаете по веткам. Если у вас вmainбыли свои коммиты, возможен конфликт.git push origin main— отправить результат в ваш форк на GitHub: пока вы не сделаете push, обновился только ваш компьютер.
Есть путь без терминала. На главной странице форка над списком файлов нажмите выпадающее меню Sync fork, посмотрите, какие коммиты оригинала вы получите, и нажмите Update branch. Если обновление упирается в конфликт, GitHub предложит создать pull request, чтобы его решить. После обновления форка на GitHub у себя выполните git pull. Подробно — в документации GitHub: Syncing a fork.
Почему лучше не работать в main форка
Если вы правите только свои ветки, ваш main остаётся точной копией оригинала, и синхронизация проходит перемоткой без конфликтов. Правки в main форка превращают каждую синхронизацию в слияние.
Первый вклад в open source
Open source — программы, исходный код которых открыт и которым может помочь любой. Вклад не обязан быть сложным: часто начинают с опечатки в README. С чего начать:
- README проекта — что он делает и как запускается.
- CONTRIBUTING — файл с правилами для участников: как оформлять PR, какие проверки пройти. Прочитайте до того, как что-то менять.
- Issues с меткой
good first issue— задачи, которые авторы специально считают подходящими для новичков (метку вы видели среди стандартных).
Есть репозиторий, созданный именно для первых PR, — firstcontributions/first-contributions (его описание: «Help beginners to contribute to open source projects»). Его README пошагово ведёт через fork, clone, ветку, добавление своего имени в файл Contributors.md и pull request. Если захотите настоящий опыт, сделайте это по их инструкции: она повторяет всё, что вы проходите в этом уроке.
Вежливость в чужом проекте
- Сопровождающие, как правило, работают в свободное время. Ответа можно ждать дни, не торопите и не пишите «ну когда уже».
- Один PR — одно изменение, описание короткое и по делу.
- Следуйте правилам проекта, даже если вы бы сделали иначе.
- К отказу или замечаниям отнеситесь спокойно: это обычное ревью, как в прошлом уроке.
Практика у себя
- Откройте
https://github.com/octocat/Spoon-Knife, нажмите Fork, в Owner выберите свой аккаунт, нажмите Create fork. - На странице форка нажмите зелёную кнопку Code и скопируйте HTTPS-адрес.
- В терминале:
cd ~/projects, затемgit cloneи скопированный адрес, затемcd Spoon-Knife. Папкаportfolioостаётся нетронутой, вы работаете в соседней. - Добавьте оригинал:
git remote add upstream https://github.com/octocat/Spoon-Knife.git. Проверьте:git remote -vпечатает четыре строки (дваoriginи дваupstream). - Создайте ветку:
git switch -c add-practice-line. - Откройте
README.mdв VS Code, допишите в конец строку «Alex Ivanov practiced forks here.» (с вашим именем), сохраните. - Закоммитьте:
git add README.md,git commit -m "Добавить строку в README". Отправьте:git push -u origin add-practice-line. - На GitHub нажмите Compare & pull request. Проверьте, что репозиторий слева — ваш форк, а не оригинал, и создайте PR кнопкой Create pull request.
- Слейте его кнопками Merge pull request и Confirm merge, нажмите Delete branch.
- Обновите свой компьютер:
git switch main,git pull,git branch -d add-practice-line. - Синхронизация:
git fetch upstream, затемgit merge upstream/main. Скорее всего, оригинал не менялся, и Git ответитAlready up to date.— это нормально. Загляните и в меню Sync fork на странице форка и посмотрите, что оно показывает.
Если захотите настоящий вклад, повторите те же шаги для firstcontributions/first-contributions по их README.
Проверьте себя
git remote -vв клоне показываетorigin(ваш форк) иupstream(оригинал).- В вашем форке на
mainесть строка про практику вREADME.md; веткаadd-practice-lineудалена. - Вы знаете, чем отличаются fork, clone и ветка.
- Вы можете назвать два способа подтянуть обновления оригинала: Sync fork и пара
git fetch upstreamсgit merge upstream/main.
Частые ошибки
Клонировали оригинал вместо форка. Клон проходит, а на push GitHub отвечает отказом в доступе: примерно Permission to octocat/Spoon-Knife.git denied и error: 403. Причина: у вас нет права записи в оригинал. Исправление: сделайте fork и поменяйте адрес командой git remote set-url origin <адрес вашего форка>.
Работали в main форка. Тогда при синхронизации с оригиналом появляются лишние слияния и конфликты. Правки всегда в отдельной ветке.
Форк отстал от оригинала. Ваш PR показывает устаревшую базу или ссылается на давно переписанный код. Перед новой работой синхронизируйтесь: Sync fork или fetch и merge upstream/main.
PR ушёл не туда. Для тренировки вы собирались слить правку в свой форк, а GitHub предложил оригинал (или наоборот). Перед нажатием Create pull request прочитайте оба репозитория вверху формы.
Что важно запомнить
- Fork — ваша копия чужого репозитория на GitHub; clone — копия на компьютере; ветка — линия истории внутри репозитория.
- Путь вклада: Fork,
git cloneсвоего форка, ветка, коммиты,git push, Compare & pull request. origin— ваш форк,upstream— оригинал; обновления берут черезgit fetch upstreamиgit merge upstream/mainили кнопкой Sync fork.- В
mainфорка не работают: только в ветках. - В чужом проекте читают CONTRIBUTING, делают маленькие PR и спокойно ждут ответа.
Вы освоили все детали командной работы по отдельности: PR, ревью, issues, форки. Пора собрать их в один сценарий, да ещё и с конфликтом, ведь рано или поздно двое обязательно изменят одну строку. Этим займёмся в практикуме модуля.