繁体   English   中英

如何更新或同步 GitHub 上的分叉存储库?

[英]How do I update or sync a forked repository on GitHub?

我分叉了一个项目,进行了更改,并创建了一个被接受的拉取请求。 新的提交后来被添加到存储库中。 我如何将这些提交放入我的分叉中?

在分叉存储库的本地克隆中,您可以将原始 GitHub 存储库添加为“远程”。 (“远程”就像存储库 URL 的昵称 - 例如, origin是其中之一。)然后您可以从该上游存储库中获取所有分支,并重新调整您的工作以继续处理上游版本。 就可能看起来像这样的命令而言:

# 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

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

如果您不想重写 master 分支的历史记录(例如,因为其他人可能已经克隆了它),那么您应该将最后一个命令替换为git merge upstream/master 但是,为了进一步提出尽可能干净的拉取请求,最好重新设置基准。


如果您已将分支重新定位到upstream/master上,您可能需要强制推送以便将其推送到您自己在 GitHub 上的分叉存储库。 你会这样做:

git push -f origin master

您只需要在重新定位后第一次使用-f即可。

从 2014 年 5 月开始,可以直接从 GitHub 更新分叉。 这在 2017 年 9 月仍然有效,它会导致一个肮脏的提交历史。

  1. 在 GitHub 上打开你的 fork。
  2. 单击拉取请求
  3. 单击新的拉取请求 默认情况下,GitHub 会将原始版本与您的 fork 进行比较,如果您未进行任何更改,则不应有任何可比较的内容。
  4. 如果您看到该链接,请单击切换基础 否则,手动将基叉下拉设置为您的前叉,将头叉设置为上游。 现在 GitHub 会将您的 fork 与原始版本进行比较,您应该会看到所有最新的更改。 在此处输入图像描述
  5. 创建拉取请求并为您的拉取请求分配一个可预测的名称(例如, Update from original )。
  6. 向下滚动到Merge pull request ,但不要单击任何内容。

现在您有三个选项,但每个选项都会导致提交历史不太干净。

  1. 默认将创建一个丑陋的合并提交。
  2. 如果您单击下拉菜单并选择“压缩并合并”,则所有介入的提交都将被压缩为一个。 这通常是您不想要的。
  3. 如果你点击Rebase and merge ,所有的提交都会和你一起进行,原来的 PR 会链接到你的 PR,GitHub 会显示This branch is X commits ahead, Y commits behind <original fork>

所以是的,你可以使用 GitHub Web UI 让你的 repo 更新到它的上游,但是这样做会破坏你的提交历史。 改用命令行- 这很容易。

这是 GitHub 关于Syncing a fork的官方文档:

同步分叉

设置

在同步之前,您需要添加一个指向上游存储库的远程。 当你最初分叉时,你可能已经这样做了。

提示:同步你的 fork 只会更新你的本地仓库副本; 它不会更新您在 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)

同步

将存储库与上游同步需要两个步骤:首先必须从远程获取,然后必须将所需的分支合并到本地分支。

抓取

从远程存储库中获取将引入其分支及其各自的提交。 这些存储在特殊分支下的本地存储库中。

 $ 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

我们现在将上游的 master 分支存储在本地分支 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 上的存储库,请按照此处的说明进行操作

很多答案最终会将您的 fork 移到父存储库之前的一个提交 此答案总结了此处找到的步骤,这些步骤会将您的 fork 移至与 parent 相同的提交

  1. 将目录更改为您的本地存储库。

    • 如果你不是git checkout master切换到 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

如果像我一样,你从不直接向 master 提交任何东西,你真的应该这样做,你可以执行以下操作。

从 fork 的本地克隆,创建上游远程。 你只需要这样做一次:

git remote add upstream https://github.com/whoever/whatever.git

然后,每当您想赶上上游存储库主分支时,您需要:

git checkout master
git pull upstream master

假设你自己从来没有在 master 上做过任何事情,你应该已经完成​​了。 现在,您可以将本地 master 推送到您的源远程 GitHub 分支。 您还可以在您现在最新的本地 master 上重新设置您的开发分支。

通过初始上游设置和主节点结帐,您需要做的就是运行以下命令以将您的主节点与上游同步: git pull upstream master

前言:你的 fork 是“起源”,而你 fork 的存储库是“上游”。

假设您已经使用以下命令将 fork 克隆到您的计算机:

git clone git@github.com:your_name/project_name.git
cd project_name

如果给出了,那么您需要按以下顺序继续:

  1. 将“上游”添加到您的克隆存储库(“来源”):

     git remote add upstream git@github.com:original_author/project_name.git
  2. 从“上游”获取提交(和分支):

     git fetch upstream
  3. 切换到 fork 的“master”分支(“origin”):

     git checkout master
  4. 存储“master”分支的更改:

     git stash
  5. 将“上游”的“master”分支的更改合并到“origin”的“master”分支中:

     git merge upstream/master
  6. 解决合并冲突(如果有)并提交合并

    git commit -am "Merged from upstream"
  7. 将更改推送到您的 fork

     git push
  8. 取回隐藏的更改(如果有)

     git stash pop
  9. 你完成了! 恭喜!

GitHub 还提供了有关此主题的说明:同步分叉

自 2013 年 11 月以来,GitHub 收到了一个非官方的功能请求,要求他们添加一种非常简单直观的方法来保持本地分支与上游同步:

https://github.com/isaacs/github/issues/121

注意:由于功能请求是非官方的,因此建议您联系support@github.com以添加您对要实现的此类功能的支持。 上面的非官方功能请求可以用作对此正在实施的兴趣量的证据。

GitHub 现在推出了一项功能,只需单击按钮即可同步分叉

转到您的 fork,单击Fetch upstream ,然后单击Fetch and merge以直接将您的 fork 与其父 repo 同步。

在此处输入图像描述

您也可以单击“ Compare ”按钮在合并之前比较更改。

参考:GitHub 的文档

有三种方法可以做到这一点:从 Web UI(选项 1)、从 GitHub CLI(选项 2)或从命令行(选项 3)。


选项 1 - 网页界面

  1. 在 GitHub 上,导航到要与上游存储库同步的分叉存储库的主页。

  2. 选择获取上游下拉菜单。

在此处输入图像描述

  1. 查看来自上游存储库的提交的详细信息,然后单击 Fetch and merge。

在此处输入图像描述


选项 2 - GitHub CLI

要从其父分支更新远程分支,请使用gh repo sync子命令并提供您的分支名称作为参数。

$ gh repo sync owner/cli-fork

如果上游存储库的更改导致冲突,则 GitHub CLI 无法同步。 您可以设置-force标志以覆盖目标分支。


选项 3 - 命令行

在将一个分支与上游存储库同步之前,必须在 Git 中配置一个指向上游存储库的远程

1 打开 Git Bash。

2 将当前工作目录更改为您的本地项目。

3 从上游存储库获取分支及其各自的提交。 对 BRANCHNAME 的提交将存储在本地分支 upstream/BRANCHNAME 中。

$ git fetch upstream
> 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/ORIGINAL_OWNER/ORIGINAL_REPOSITORY
>  * [new branch]      main     -> upstream/main

4 检查你的 fork 的本地默认分支 - 在这种情况下,我们使用 main。

$ git checkout main
> Switched to branch 'main'

5 将上游默认分支(在本例中为 upstream/main)中的更改合并到本地默认分支中。 这将使您的 fork 的默认分支与上游存储库同步,而不会丢失您的本地更改。

$ git merge upstream/main
> 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/main
> Updating 34e91da..16c56ad
> Fast-forward
>  README.md                 |    5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)

注意:同步一个人的分叉只会更新一个人的本地副本。 要在 GitHub.com 上更新一个分支,必须推送一个更改


来源: GitHub Docs - 同步分叉

截至本答案发布之日,GitHub 还没有(或者我应该不再说? )Web 界面中的此功能。 但是,您可以要求support@github.com添加您的投票。

与此同时,GitHub 用户 bardiharborow 创建了一个工具来做到这一点: https ://upriver.github.io/

来源在这里: https ://github.com/upriver/upriver.github.io

如果您使用 GitHub for Windows 或 Mac,那么现在它们具有一键更新 forks 的功能:

  1. 在 UI 中选择存储库。
  2. 单击顶部的“从用户/分支更新”按钮。

实际上,可以从浏览器中上游的任何提交在您的 fork 中创建一个分支:

在此处输入图像描述

然后,您可以将该分支获取到您的本地克隆,当您在该提交之上推送编辑时,您不必将所有数据推送回 GitHub。 或者使用 Web 界面更改该分支中的某些内容。

它是如何工作的(这是一个猜测,我不知道 GitHub 到底是怎么做的):forks 共享对象存储并使用命名空间来分隔用户的引用。 因此,您可以通过您的 fork 访问所有提交,即使它们在分叉时不存在。

请按照以下步骤操作。 我尝试了它们,它帮助了我。

结帐到您的分行

语法: git branch yourDevelopmentBranch
示例: git checkout master

拉取源代码库分支以获取最新代码

语法: 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

如果您不想将另一个远程端点添加到您的项目中,请使用此选项,就像此处发布的其他解决方案一样。

作为对这个答案的补充,我正在寻找一种方法来一次从上游分支更新我克隆的 repo ( origin ) 的所有远程分支。 我就是这样做的。

这假设您已经配置了一个指向源存储库( origin从中分叉的地方)的上游远程,并已将其与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

该命令的第一部分列出了上游远程 repo 中的所有头,并删除了 SHA-1,后跟refs/heads/分支名称前缀。

然后对于这些分支中的每一个,它将上游远程跟踪分支的本地副本(本地端的refs/remotes/upstream/<branch> )直接推送到端的远程分支(远程端的refs/heads/<branch> )。

这些分支同步命令中的任何一个都可能由于以下两个原因之一失败:上游分支已被重写,或者您已将该分支上的提交推送到您的 fork。 在第一种情况下,您没有向 fork 上的分支提交任何内容,强制推送是安全的(添加-f开关;即git push -f在上面的命令中)。 在另一种情况下,这是正常的,因为您的 fork 分支已经发散,并且在您的提交合并回upstream之前,您不能期望 sync 命令起作用。

“Pull”应用程序是一种自动设置和忘记的解决方案。 它会将你的 fork 的默认分支与上游存储库同步。

访问 URL,单击绿色的“安装”按钮并选择要启用自动同步的存储库。

该分支每小时直接在 GitHub 上更新一次,在您的本地机器上,您需要拉取 master 分支以确保您的本地副本是同步的。

如果你设置你的上游。 检查git remote -v ,就足够了。

git fetch upstream
git checkout master
git merge --no-edit upstream/master
git push

克隆分叉存储库后,转到克隆所在的目录路径和 Git Bash 终端中的几行。

$ 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”时,您才会被告知您的同事推送到远程服务器的更改。

您仍然可以访问此处进行进一步查询

假设你的 fork 是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. 在下一页上,滚动到页面底部,然后单击Merge pull requestConfirm merge

使用此代码段生成链接以同步您的分叉存储库:

 new Vue ({ el: "#app", data: { yourFork: 'https://github.com/me/foobar', originalRepo: 'https://github.com/someone/foobar' }, computed: { syncLink: function () { const yourFork = new URL(this.yourFork).pathname.split('/') const originalRepo = new URL(this.originalRepo).pathname.split('/') if (yourFork[1] && yourFork[2] && originalRepo[1]) { return `https://github.com/${yourFork[1]}/${yourFork[2]}/compare/master...${originalRepo[1]}:master` } return 'Not enough data' } } })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> Your fork URL: <input size=50 v-model="yourFork" /> <br /> Original repository URL: <input v-model="originalRepo" size=50 /> <br /> Link to sync your fork: <a :href="syncLink">{{syncLink}}</a> </div>

$ git remote add upstream https://github.com/....

$ git pull upstream main

$ git push

Android Studio 现在已经学会了使用 GitHub fork 存储库(您甚至不必通过控制台命令添加“上游”远程存储库)。

打开菜单VCSGit

并注意最后两个弹出菜单项:

  • Rebase 我的 GitHub 分支

  • 创建拉取请求

试试看。 我使用第一个来同步我的本地存储库。 无论如何,在您单击“Rebase my GitHub fork”后,将可以在 Android Studio 中访问来自父远程存储库(“上游”)的分支,并且您将能够轻松地使用它们进行操作。

(我使用带有“Git 集成”和“GitHub”插件的 Android Studio 3.0。)

在此处输入图像描述

这取决于您的存储库的大小以及您如何分叉它。

如果它是一个相当大的存储库,您可能希望以一种特殊的方式来管理它(例如删除历史记录)。 基本上,您可以获得当前版本和上游版本之间的差异,提交它们,然后将它们挑选回 master。

试试看 这个 它描述了如何处理大型 Git 存储库以及如何使用最新更改将它们上传到上游。

我想补充一下@krlmlr 的答案

最初,分叉的存储库有一个名为master的分支。 如果您正在开发新功能或修复,您通常会创建一个新的分支feature并进行更改。

如果您希望分叉存储库与父存储库同步,您可以为Pull 应用程序在功能分支中)设置一个配置文件( pull.yml ),如下所示:

version: "1"
rules:
  - base: feature
    upstream: master
    mergeMethod: merge
  - base: master
    upstream: parent_repo:master
    mergeMethod: hardreset

这使分叉存储库的master分支与父存储库保持同步。 它通过合并相同的分叉存储库的master分支来保持分叉存储库的feature分支更新。 这假设feature分支是包含配置文件的默认分支。

这里有两种合并hardreset mergemethods它有助于强制在分叉的 repo 的master分支中与父 repo 同步更改,另一种方法是merge 此方法用于合并您在feature分支中所做的更改以及由于master分支中的强制同步而完成的更改。 在合并冲突的情况下,拉取应用程序将允许您在拉取请求期间选择下一个操作过程。

您可以在此处阅读有关基本和高级配置以及各种mergemethods的信息。

我目前在我的分叉存储库中使用此配置,以确保此处请求增强功能保持更新。

试试这个,单击“获取上游”以从上游主同步您的分叉存储库。 在此处输入图像描述

保持分叉存储库始终保持更新有两个主要方面。

1. 从 fork master 创建分支在那里进行更改

因此,当您的Pull Request被接受时,您可以安全地删除分支,因为当您使用上游更新它时,您贡献的代码将存在于您的分叉存储库的主库中。 这样,您的 master 将始终处于干净状态,可以创建一个新分支来进行另一次更改。

2.为fork master创建一个计划的工作自动更新

这可以通过cron来完成。 如果您在 linux 中执行此操作,这是一个示例代码。

$ crontab -e

将此代码放在crontab file中,以每小时执行一次作业。

0 * * * * sh ~/cron.sh

然后创建cron.sh脚本文件和与ssh-agent和/或期望git 交互,如下所示

#!/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

在此处输入图像描述

使用这些命令(在幸运的情况下)

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

如果您使用 GitHub Desktop,只需 6 步(实际上只有 5 步)即可轻松完成。

打开 Github Desktop 并选择您的存储库后,

  1. 转到历史选项卡
  2. 点击搜索栏。 它将向您显示所有可用的分支(包括来自父存储库的上游分支)
  3. 选择相应的上游分支(它将是上游/主同步主分支)
  4. (可选)它将向您显示上游分支中的所有提交。 您可以单击任何提交以查看更改。
  5. 根据您的活动分支,在master / branch-name中单击 Merge。
  6. 等待 GitHub Desktop 施展魔法。

以下面的 GIF 为例:

从父存储库同步分叉存储库中的上游分支

如果你想让你的 GitHub 分支与各自的上游保持同步,还有专门为 GitHub 提供的这个 probot 程序: https ://probot.github.io/apps/pull/ 可以完成这项工作。 您需要在您的帐户中允许安装,这将使您的分叉保持最新。

如何在本地机器上更新你的分叉仓库?

首先,检查您的遥控器/主机

git remote -v

你应该有起源和上游。 例如:

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
rm -rf oldrepository
git clone ...

可能有更微妙的选择,但这是我确信我的本地存储库与上游相同的唯一方法。

从 github 页面删除您的远程开发人员

然后应用这些命令:

1) git branch -D dev
2) git fetch upstream
3) git checkout master
4) git fetch upstream && git fetch upstream --prune && git rebase upstream/master && git push -f origin master
5) git checkout -b dev
6) git push origin dev
7) git fetch upstream && git fetch upstream --prune && git rebase upstream/dev && 8) git push -f origin dev

要查看您的配置,请使用以下命令:

git remote -v

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM