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 года, НО это приведет к грязной истории коммитов.

  1. Откройте вилку на GitHub.
  2. Нажмите на Запросы на извлечение.
  3. Нажмите на новый запрос на извлечение. По умолчанию GitHub будет сравнивать оригинал с вашим форком, и не должно быть ничего для сравнения, если вы не внесли никаких изменений.
  4. Нажмите переключение базы, если вы видите эту ссылку. В противном случае вручную установите опорную вилку вниз на вилку, а головную вилку - вверх по течению. Теперь GitHub будет сравнивать ваш форк с оригиналом, и вы должны увидеть все последние изменения.
  5. Создайте pull-запрос и назначьте предсказуемое имя для вашего pull-запроса (например, Update from original).
  6. Прокрутите вниз до Merge pull request, но пока ничего не нажимаете.

Теперь у вас есть три варианта, но каждый из них приведет к менее чистой истории фиксации.

  1. По умолчанию будет создан уродливый коммит слияния.
  2. Если вы щелкнете по раскрывающемуся списку и выберете "Squash and merge", все промежуточные коммиты будут сведены в один. Это чаще всего то, что вы не хотите.
  3. Если вы нажмете "Перебазировать и объединить", все коммиты будут сделаны "с вами", оригинальные 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, следуйте инструкциям здесь

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

  1. Перейдите в локальный репозиторий.

    • Переключитесь на главную ветку, если вы не git checkout master
  2. Добавьте родителя в качестве удаленного хранилища, git remote add upstream <repo-location>

  3. вопрос git fetch upstream
  4. вопрос git rebase upstream/master

    • На этом этапе вы проверяете, что фиксирует то, что будет объединено, набрав git status
  5. вопрос 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

Если это дано, вам нужно продолжить в следующем порядке:

  1. Добавьте "upstream" в ваш клонированный репозиторий ("origin"):

    git remote add upstream git@github.com:original_author/project_name.git
    
  2. Получить коммиты (и ветки) из "вверх по течению":

    git fetch upstream
    
  3. Переключитесь на ветку "master" вашего форка ("origin"):

    git checkout master
    
  4. Храните изменения вашей "главной" ветки:

    git stash
    
  5. Объедините изменения из "master" ветви "upstream" в вашу "master" ветку вашего "origin":

    git merge upstream/master
    
  6. Разрешите конфликты слияния, если они есть, и зафиксируйте слияние

    git commit -am "Merged from upstream"
    
  7. Нажмите изменения в вашей вилке

    git push
    
  8. Верните свои скрытые изменения (если есть)

    git stash pop
    
  9. Вы сделали! Поздравляем!

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, то теперь у них есть возможность одним щелчком мыши обновить вилки:

  1. Выберите хранилище в пользовательском интерфейсе.
  2. Нажмите кнопку "Обновить от пользователя / филиала" вверху.

На самом деле, можно создать ветку в вашем форке из любого коммита восходящего потока в браузере:

  • открыто https://github.com/<repo>/commits/<hash>где repo - это ваш форк, а hash - полный хеш коммитов, который вы можете найти в вышестоящем веб-интерфейсе. Например, я могу открыть https://github.com/max630/linux/commits/0aa0313f9d576affd7747cc3f179feb097d28990, который указывает на linuxmaster как время написания.
  • Нажмите на кнопку "Дерево: ....".
  • Введите название новой ветки и нажмите 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

  1. Посетите https://github.com/me/foobar/compare/master...someone:master.

  2. Если вы видите зеленый текст Able to mergeзатем нажмите Create pull request

  3. На следующей странице прокрутите страницу вниз и нажмите « Объединить запрос на извлечение» и « Подтвердить объединение» .

Как обновить разветвленное репо на локальном компьютере?

Сначала проверьте свой пульт / мастер

      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 (вам даже не нужно добавлять "восходящий" удаленный репозиторий по команде консоли).

Откройте меню VCSGit

И обратите внимание на два последних пункта всплывающего меню:

  • Перебазировать мою вилку 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 здесь.

Я в настоящее время использую эту конфигурацию в моем раздвоенном репо здесь, чтобы убедиться, что усиление запрошенными здесь остается обновляется.

Попробуйте это, нажмите «Fetch upstream», чтобы синхронизировать ваше разветвленное репо с вышестоящим мастером.

Если вы хотите, чтобы ваши форки GitHub были в актуальном состоянии с соответствующими восходящими потоками, также существует эта пробная программа специально для GitHub: https://probot.github.io/apps/pull/, которая выполняет эту работу. Вам нужно будет разрешить установку в своей учетной записи, и это будет поддерживать ваши вилки в актуальном состоянии.

Это зависит от размера вашего хранилища и от того, как вы его разветвили.

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

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

Если вы используете GitHub Desktop, вы можете легко сделать это всего за 6 шагов (на самом деле всего 5).

Как только вы откроете Github Desktop и выберете свой репозиторий,

  1. Перейти на вкладку История
  2. Щелкните по строке поиска. Он покажет вам все доступные ветки (включая восходящие ветки из родительского репозитория)
  3. Выберите соответствующую восходящую ветвь (это будет восходящая / основная ветвь для синхронизации главной ветки)
  4. (НЕОБЯЗАТЕЛЬНО) Он покажет вам все коммиты в восходящей ветке. Вы можете нажать на любой коммит, чтобы увидеть изменения.
  5. Нажмите Объединить master / branch-name, на основе вашей активной ветки.
  6. Подождите, пока 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
Другие вопросы по тегам