How do I update a GitHub forked repository?
Недавно я разработал проект и применил несколько исправлений. Затем я создал запрос на извлечение, который затем был принят.
Несколько дней спустя другое изменение было внесено другим участником. Так что моя вилка не содержит этого изменения.
Как я могу получить это изменение в моей вилке? Нужно ли мне удалять и заново создавать свой форк, когда у меня появятся дальнейшие изменения? Или есть кнопка обновления?
31 ответ
В локальном клоне вашего разветвленного репозитория вы можете добавить исходный репозиторий GitHub в качестве "удаленного". ("Remotes" подобны псевдонимам для URL репозиториев - origin
например, один.) Затем вы можете извлечь все ветви из этого репозитория upstream и перебазировать свою работу, чтобы продолжить работу над версией upstream. С точки зрения команд, которые могут выглядеть так:
# Add the remote, call it "upstream":
git remote add upstream https://github.com/whoever/whatever.git
# Fetch all the branches of that remote into remote-tracking branches,
# such as upstream/master:
git fetch upstream
# Make sure that you're on your master branch:
git checkout master
# Rewrite your master branch so that any commits of yours that
# aren't already in upstream/master are replayed on top of that
# other branch:
git rebase upstream/master
Если вы не хотите переписывать историю вашей основной ветки (например, потому что другие люди могли ее клонировать), тогда вам следует заменить последнюю команду на git merge upstream/master
, Тем не менее, для того, чтобы сделать дальнейшие пул-запросы, которые были бы максимально чистыми, вероятно, лучше сделать ребаз.
Если вы перебазировали свою ветку на upstream/master
вам может потребоваться принудительное использование push для того, чтобы перенести его в свой собственный разветвленный репозиторий на GitHub. Вы бы сделали это с:
git push -f origin master
Вам нужно только использовать -f
в первый раз после того, как вы перебазировали.
Начиная с мая 2014 года можно обновлять форк напрямую с GitHub. Это все еще работает с сентября 2017 года, НО это приведет к грязной истории коммитов.
- Откройте вилку на GitHub.
- Нажмите на Запросы на извлечение.
- Нажмите на новый запрос на извлечение. По умолчанию GitHub будет сравнивать оригинал с вашим форком, и не должно быть ничего для сравнения, если вы не внесли никаких изменений.
- Нажмите переключение базы, если вы видите эту ссылку. В противном случае вручную установите опорную вилку вниз на вилку, а головную вилку - вверх по течению. Теперь GitHub будет сравнивать ваш форк с оригиналом, и вы должны увидеть все последние изменения.
- Создайте pull-запрос и назначьте предсказуемое имя для вашего pull-запроса (например,
Update from original
). - Прокрутите вниз до Merge pull request, но пока ничего не нажимаете.
Теперь у вас есть три варианта, но каждый из них приведет к менее чистой истории фиксации.
- По умолчанию будет создан уродливый коммит слияния.
- Если вы щелкнете по раскрывающемуся списку и выберете "Squash and merge", все промежуточные коммиты будут сведены в один. Это чаще всего то, что вы не хотите.
- Если вы нажмете "Перебазировать и объединить", все коммиты будут сделаны "с вами", оригинальные PR свяжутся с вашим PR, и GitHub отобразит
This branch is X commits ahead, Y commits behind <original fork>
,
Так что да, вы можете поддерживать свое репо в обновленном состоянии с помощью веб-интерфейса GitHub, но это приведет к потере истории ваших коммитов. Вместо этого придерживайтесь командной строки - это легко.
Вот официальный документ GitHub по синхронизации форка:
Синхронизация вилки
Настройка
Прежде чем вы сможете синхронизировать, вам нужно добавить удаленный, который указывает на обратный репозиторий. Возможно, вы сделали это, когда изначально разветвлялись.
Совет: Синхронизация вашего форка только обновляет вашу локальную копию хранилища; он не обновляет ваш репозиторий на GitHub.
$ git remote -v # List the current remotes origin https://github.com/user/repo.git (fetch) origin https://github.com/user/repo.git (push) $ git remote add upstream https://github.com/otheruser/repo.git # Set a new remote $ git remote -v # Verify new remote origin https://github.com/user/repo.git (fetch) origin https://github.com/user/repo.git (push) upstream https://github.com/otheruser/repo.git (fetch) upstream https://github.com/otheruser/repo.git (push)
Синхронизации
Существует два шага, необходимых для синхронизации вашего репозитория с апстримом: сначала вы должны извлечь данные с удаленного компьютера, затем вы должны объединить нужную ветку с вашей локальной веткой.
Fetching
Извлечение из удаленного хранилища приведет к его ветвям и их соответствующим коммитам. Они хранятся в вашем локальном хранилище в специальных ветках.
$ git fetch upstream # Grab the upstream remote's branches remote: Counting objects: 75, done. remote: Compressing objects: 100% (53/53), done. remote: Total 62 (delta 27), reused 44 (delta 9) Unpacking objects: 100% (62/62), done. From https://github.com/otheruser/repo * [new branch] master -> upstream/master
Теперь у нас есть главная ветка upstream, хранящаяся в локальной ветке upstream/master.
$ git branch -va # List all local and remote-tracking branches * master a422352 My local commit remotes/origin/HEAD -> origin/master remotes/origin/master a422352 My local commit remotes/upstream/master 5fdff0f Some upstream commit
сращивание
Теперь, когда мы загрузили вышестоящий репозиторий, мы хотим объединить его изменения с нашей локальной веткой. Это позволит синхронизировать эту ветку с восходящим потоком, не теряя наших локальных изменений.
$ git checkout master # Check out our local master branch Switched to branch 'master' $ git merge upstream/master # Merge upstream's master into our own Updating a422352..5fdff0f Fast-forward README | 9 ------- README.md | 7 ++++++ 2 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 README create mode 100644 README.md
Если в вашем локальном филиале не было уникальных коммитов, вместо этого git выполнит "ускоренную перемотку вперед":
$ git merge upstream/master Updating 34e91da..16c56ad Fast-forward README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Совет: если вы хотите обновить свой репозиторий на GitHub, следуйте инструкциям здесь
Множество ответов в конечном итоге перемещают ваш форк на один коммит вперед от родительского репозитория. Этот ответ суммирует шаги, найденные здесь, которые переместят ваш форк в тот же коммит, что и родительский.
Перейдите в локальный репозиторий.
- Переключитесь на главную ветку, если вы не
git checkout master
- Переключитесь на главную ветку, если вы не
Добавьте родителя в качестве удаленного хранилища,
git remote add upstream <repo-location>
- вопрос
git fetch upstream
вопрос
git rebase upstream/master
- На этом этапе вы проверяете, что фиксирует то, что будет объединено, набрав
git status
- На этом этапе вы проверяете, что фиксирует то, что будет объединено, набрав
вопрос
git push origin master
Для получения дополнительной информации об этих командах обратитесь к шагу 3.
Если, как и я, вы никогда не делаете что-либо напрямую, чтобы овладеть, что вам действительно нужно, вы можете сделать следующее.
Из локального клона вашего форка создайте свой удаленный пульт. Вам нужно сделать это только один раз:
git remote add upstream https://github.com/whoever/whatever.git
Тогда всякий раз, когда вы хотите догнать основную ветку репозитория, вы должны:
git checkout master
git pull upstream master
Предполагая, что вы никогда ничего не совершали на хозяина, вам уже покончено. Теперь вы можете перенести локального мастера на исходную удаленную вилку GitHub. Вы также можете переназначить свою ветку разработки на своем современном локальном мастере.
Итак, после начальной настройки восходящего потока и проверки мастера все, что вам нужно сделать, это запустить следующую команду, чтобы синхронизировать ваш мастер с вышестоящим: git pull upstream master.
Предисловие: ваш форк - это "источник", а репозиторий, из которого вы разветвлены, - "восходящий".
Давайте предположим, что вы уже клонировали свой форк на свой компьютер с помощью команды, подобной этой:
git clone git@github.com:your_name/project_name.git
cd project_name
Если это дано, вам нужно продолжить в следующем порядке:
Добавьте "upstream" в ваш клонированный репозиторий ("origin"):
git remote add upstream git@github.com:original_author/project_name.git
Получить коммиты (и ветки) из "вверх по течению":
git fetch upstream
Переключитесь на ветку "master" вашего форка ("origin"):
git checkout master
Храните изменения вашей "главной" ветки:
git stash
Объедините изменения из "master" ветви "upstream" в вашу "master" ветку вашего "origin":
git merge upstream/master
Разрешите конфликты слияния, если они есть, и зафиксируйте слияние
git commit -am "Merged from upstream"
Нажмите изменения в вашей вилке
git push
Верните свои скрытые изменения (если есть)
git stash pop
Вы сделали! Поздравляем!
GitHub также предоставляет инструкции по этой теме: Синхронизация форка
Есть способ сделать это из веб-приложения GitHub.
Давайте рассмотрим следующий пример.
Для начала откройте репо, которое вы хотите обновить.
Видно предупреждение
Эта ветка на 157 коммитов стоит за GoogleCloudPlatform: master.
Справа две кнопки
Pull request
и . Нажмите
Compare
.
Так как сравнивать, наверное, не с чем, нажмите
switching the base
Появится список всех изменений, и можно будет создать запрос на перенос, нажав кнопку
Create pull request
Дайте ему название, скажем "Обновить репо"
И создайте запрос на перенос.
После создания запроса прокрутите вниз и нажмите
Merge pull request
.
Подтвердите слияние и все!
GitHub теперь представил функцию для синхронизации вилки одним нажатием кнопки .
Зайдите в свою вилку, нажмите на
Fetch upstream
а затем нажмите на
Fetch and merge
чтобы напрямую синхронизировать вилку с родительским репо.
Вы также можете нажать на
Compare
кнопку, чтобы сравнить изменения перед объединением.
Ссылка : GitHubтвит
С ноября 2013 года в GitHub был открыт неофициальный запрос на добавление очень простого и интуитивно понятного метода для синхронизации локального разветвления с восходящим:
https://github.com/isaacs/github/issues/121
Примечание: так как запрос функции является неофициальным, также желательно связаться support@github.com
чтобы добавить вашу поддержку для реализации подобной функции. Вышеупомянутый неофициальный запрос может быть использован в качестве доказательства заинтересованности в этом.
На момент получения этого ответа у GitHub нет ( или я больше не буду говорить?) Этой функции в веб-интерфейсе. Вы можете, однако, спросить support@github.com
добавить свой голос за это.
Тем временем, пользователь GitHub bardiharborow создал инструмент для этого: https://upriver.github.io/
Источник находится здесь: https://github.com/upriver/upriver.github.io
Если вы используете GitHub для Windows, то теперь у них есть возможность одним щелчком мыши обновить вилки:
- Выберите хранилище в пользовательском интерфейсе.
- Нажмите кнопку "Обновить от пользователя / филиала" вверху.
На самом деле, можно создать ветку в вашем форке из любого коммита восходящего потока в браузере:
- открыто
https://github.com/<repo>/commits/<hash>
где repo - это ваш форк, а hash - полный хеш коммитов, который вы можете найти в вышестоящем веб-интерфейсе. Например, я могу открыть https://github.com/max630/linux/commits/0aa0313f9d576affd7747cc3f179feb097d28990, который указывает наlinux
master
как время написания. - Нажмите на кнопку "Дерево: ....".
- Введите название новой ветки и нажмите Enter
Затем вы можете извлечь эту ветку в свой локальный клон, и вам не нужно будет отправлять все эти данные обратно в GitHub, когда вы вносите изменения поверх этого коммита. Или используйте веб-интерфейс, чтобы что-то изменить в этой ветке.
Как это работает (это предположение, я не знаю, как именно GitHub это делает): вилки совместно используют хранилище объектов и используют пространства имен для разделения ссылок пользователей. Таким образом, вы можете получить доступ ко всем коммитам через ваш форк, даже если они не существовали на момент разветвления.
$ git remote add upstream https://github.com/....
$ git pull upstream main
$ git push
Выполните следующие шаги. Я попробовал их, и это помогло мне.
Оформить заказ в вашем филиале
Синтаксис: git branch yourDevelopmentBranch
Пример: мастер git checkout
Потяните ветку репозитория исходного кода для получения последней версии кода.
Синтаксис: git pull https://github.com/tastejs/awesome-app-ideas master
Пример: git pull https://github.com/ORIGINAL_OWNER/ORIGINAL_REPO.git BRANCH_NAME
Я обновляю свои разветвленные репо этой строкой:
git pull https://github.com/forkuser/forkedrepo.git branch
Используйте это, если вы не хотите добавлять другую удаленную конечную точку в ваш проект, как другие решения, опубликованные здесь.
В качестве дополнения к этому ответу я искал способ обновить все удаленные ветви моего клонированного репо (источника) из вышестоящих веток за один раз. Вот как я это сделал.
Это предполагает, что вы уже настроили удаленный источник, указывающий на исходный репозиторий (откуда был разветвлен источник), и синхронизировали его с git fetch upstream
,
Затем запустите:
for branch in $(git ls-remote --heads upstream|sed 's#^.*refs/heads/##'); do git push origin refs/remotes/upstream/$branch:refs/heads/$branch; done
Первая часть этой команды перечисляет все головы в удаленном репо восходящего направления и удаляет SHA-1, за которым следует refs/heads/
префикс имени ветви.
Затем для каждой из этих ветвей она выталкивает локальную копию восходящей ветви удаленного отслеживания (refs/remotes/upstream/<branch>
на локальной стороне) непосредственно в удаленную ветку на источнике (refs/heads/<branch>
на удаленной стороне).
Любая из этих команд синхронизации веток может завершиться с ошибкой по одной из двух причин: либо ветка upstream была переписана, либо вы передали коммиты в этой ветке на ваш форк. В первом случае, когда вы ничего не добавили в ветку на своей вилке, безопасно нажимать принудительно (добавьте ключ -f; git push -f
в команде выше). В другом случае это нормально, так как ваша ветвь ветвления разошлась, и вы не можете ожидать, что команда sync будет работать до тех пор, пока ваши коммиты не будут объединены с апстримом.
Приложение "Pull" - это автоматическое решение, которое можно настроить и забыть. Он синхронизирует ветвь по умолчанию вашей вилки с вышестоящим репозиторием.
Посетите URL-адрес, нажмите зеленую кнопку "Установить" и выберите репозитории, в которых вы хотите включить автоматическую синхронизацию.
Ветка обновляется раз в час непосредственно на GitHub, на вашем локальном компьютере вам нужно вытащить основную ветку, чтобы синхронизировать вашу локальную копию.
Если вы установите свой апстрим. Проверить с git remote -v
тогда этого будет достаточно.
git fetch upstream
git checkout master
git merge --no-edit upstream/master
git push
Когда вы клонировали свой разветвленный репозиторий, перейдите в каталог, где находится ваш клон, и в несколько строк в вашем Git Bash Terminal.
$ cd project-name
$ git remote add upstream https://github.com/user-name/project-name.git
# Adding the upstream -> the main repo with which you wanna sync
$ git remote -v # you will see the upstream here
$ git checkout master # see if you are already on master branch
$ git fetch upstream
И вот вам хорошо идти. Все обновленные изменения в основном репозитории будут помещены в ваш репозиторий fork.
Команда "fetch" необходима для того, чтобы быть в курсе последних событий проекта: только при выполнении "git fetch" вы будете информированы об изменениях, которые ваши коллеги отправили на удаленный сервер.
Вы все еще можете посетить здесь для дальнейших запросов
Предполагая, что ваша вилка https://github.com/me/foobar, а исходный репозиторий - https://github.com/someone/foobar
Посетите https://github.com/me/foobar/compare/master...someone:master.
Если вы видите зеленый текст
Able to merge
затем нажмите Create pull requestНа следующей странице прокрутите страницу вниз и нажмите « Объединить запрос на извлечение» и « Подтвердить объединение» .
Как обновить разветвленное репо на локальном компьютере?
Сначала проверьте свой пульт / мастер
git remote -v
У вас должны быть origin и upstream. Например:
origin https://github.com/your___name/kredis.git (fetch)
origin https://github.com/your___name/kredis.git (push)
upstream https://github.com/rails/kredis.git (fetch)
upstream https://github.com/rails/kredis.git (push)
После этого перейдите на главную:
git checkout main
и слить из апстрима в основной:
git merge upstream/main
Android Studio теперь научилась работать с репозиториями вилок GitHub (вам даже не нужно добавлять "восходящий" удаленный репозиторий по команде консоли).
Откройте меню VCS → Git
И обратите внимание на два последних пункта всплывающего меню:
Перебазировать мою вилку GitHub
Создать запрос на извлечение
Попробуйте их. Я использую первый, чтобы синхронизировать мой локальный репозиторий. В любом случае ветки из родительского удаленного репозитория ("upstream") будут доступны в Android Studio после того, как вы нажмете "Перебазировать мой GitHub fork", и вы сможете легко с ними работать.
(Я использую Android Studio 3.0 с подключаемыми модулями Git и GitHub.)
Я хотел бы добавить к krlmlr ответа.
Изначально у разветвленного репозитория есть одна ветка с именем: master
. Если вы работаете над новой функцией или исправлением, вы обычно создаете новую веткуfeature
и внесите изменения.
Если вы хотите, чтобы разветвленный репозиторий синхронизировался с родительским репозиторием, вы можете настроить файл конфигурации (pull.yml
) для приложения Pull (в ветке функций), например:
version: "1"
rules:
- base: feature
upstream: master
mergeMethod: merge
- base: master
upstream: parent_repo:master
mergeMethod: hardreset
Это сохраняет master
ветка разветвленного репо в актуальном состоянии с родительским репо. Он сохраняетfeature
ветка разветвленного репо, обновленная через master
ветвь разветвленного репо путем слияния того же самого. Это предполагает, чтоfeature
ветка - ветка по умолчанию, содержащая файл конфигурации.
Здесь два mergemethods
в игру, один hardreset
что помогает принудительно синхронизировать изменения в master
ветвь разветвленного репо с родительским репо, а другой метод - merge
. Этот метод используется для объединения изменений, сделанных вами вfeature
ветвь и изменения, сделанные из-за принудительной синхронизации в master
ветвь. В случае конфликта слияния приложение pull позволит вам выбрать следующий курс действий во время запроса на включение.
Вы можете прочитать о базовых и расширенных конфигурациях и различных mergemethods
здесь.
Я в настоящее время использую эту конфигурацию в моем раздвоенном репо здесь, чтобы убедиться, что усиление запрошенными здесь остается обновляется.
Если вы хотите, чтобы ваши форки GitHub были в актуальном состоянии с соответствующими восходящими потоками, также существует эта пробная программа специально для GitHub: https://probot.github.io/apps/pull/, которая выполняет эту работу. Вам нужно будет разрешить установку в своей учетной записи, и это будет поддерживать ваши вилки в актуальном состоянии.
Это зависит от размера вашего хранилища и от того, как вы его разветвили.
Если это довольно большой репозиторий, вы, возможно, захотите управлять им особым образом (например, история удаления). По сути, вы можете получить различия между текущей и исходной версиями, зафиксировать их и затем снова выбрать мастер.
Попробуйте прочитать это. В нем описывается, как обращаться с большими репозиториями Git и как добавлять их с последними изменениями.
Если вы используете GitHub Desktop, вы можете легко сделать это всего за 6 шагов (на самом деле всего 5).
Как только вы откроете Github Desktop и выберете свой репозиторий,
- Перейти на вкладку История
- Щелкните по строке поиска. Он покажет вам все доступные ветки (включая восходящие ветки из родительского репозитория)
- Выберите соответствующую восходящую ветвь (это будет восходящая / основная ветвь для синхронизации главной ветки)
- (НЕОБЯЗАТЕЛЬНО) Он покажет вам все коммиты в восходящей ветке. Вы можете нажать на любой коммит, чтобы увидеть изменения.
- Нажмите Объединить
master
/branch-name
, на основе вашей активной ветки. - Подождите, пока GitHub Desktop сотворит чудеса.
В качестве примера ознакомьтесь с приведенным ниже GIF-файлом:
Есть две основные вещи о том, чтобы держать разветвленный репозиторий всегда обновлять навсегда.
1. Создайте ветки из master-вилки и внесите в них изменения.
Таким образом, когда ваш запрос на извлечение будет принят, вы можете безопасно удалить ветку, так как ваш введенный код будет жить в вашем мастере вашего разветвленного репозитория, когда вы обновите его с помощью апстрима. Таким образом, ваш мастер всегда будет в чистом состоянии, чтобы создать новую ветку, чтобы сделать еще одно изменение.
2. Создайте запланированное задание, чтобы мастер разветвления автоматически обновлялся.
Это можно сделать с помощью cron. Вот пример кода, если вы делаете это в Linux.
$ crontab -e
поставить этот код на crontab file
выполнять работу почасово.
0 * * * * sh ~/cron.sh
затем создайте cron.sh
файл сценария и git-взаимодействие с ssh-agent и / или ожидаемо, как показано ниже
#!/bin/sh
WORKDIR=/path/to/your/dir
REPOSITORY=<name of your repo>
MASTER="git@github.com:<username>/$REPOSITORY.git"
UPSTREAM=git@github.com:<upstream>/<name of the repo>.git
cd $WORKDIR && rm -rf $REPOSITORY
eval `ssh-agent` && expect ~/.ssh/agent && ssh-add -l
git clone $MASTER && cd $REPOSITORY && git checkout master
git remote add upstream $UPSTREAM && git fetch --prune upstream
if [ `git rev-list HEAD...upstream/master --count` -eq 0 ]
then
echo "all the same, do nothing"
else
echo "update exist, do rebase!"
git reset --hard upstream/master
git push origin master --force
fi
cd $WORKDIR && rm -rf $REPOSITORY
eval `ssh-agent -k`
Проверьте ваш разветвленный репозиторий. Время от времени он всегда будет показывать это уведомление:
Эта ветка даже с
<upstream>
: master.
https://chetabahana.github.io/images/github/screencapture-github.png
rm -rf oldrepository
git clone ...
Могут быть более тонкие варианты, но это единственный способ, которым я могу быть уверен, что мой локальный репозиторий совпадает с исходным.
Используйте эти команды (в удачном случае)
git remote -v
git pull
git fetch upstream
git checkout master
git merge upstream/master --no-ff
git add .
git commit -m"Sync with upstream repository."
git push -v