如何更新GitHub分叉存储库?


3600

我最近分叉了一个项目,并应用了多个修复程序。然后,我创建了一个请求请求,该请求随后被接受。

几天后,另一位贡献者进行了另一项更改。因此,我的前叉不包含该更改。

我怎样才能把零钱放到我的叉子上?当我有其他更改要贡献时,是否需要删除并重新创建我的fork?还是有更新按钮?


120
这也可以从github UI中完成。我想赞扬[此其他海报] [1]。[1]:stackoverflow.com/a/21131381/728141
Mike Schroll 2014年

2
关于此的另一篇不错的博客文章- 保持GitHub叉更新
Arup Rakshit 2014年

3
在Github帮助文章中找到了此内容:help.github.com/articles/syncing-a-fork
Pranav


这是一个视频演示,使用两个github帐户youtube.com/watch?v=kpE0gTX4ycE
lifebalance 2016年

Answers:


3975

在您的分支存储库的本地克隆中,您可以将原始GitHub存储库添加为“远程”。(“ Remotes”就像是存储库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,
# 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

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


如果您已将分支重新建立基础upstream/master,则可能需要强制执行推送才能将其推送到GitHub上您自己的分叉存储库中。您可以这样做:

git push -f origin master

-f重新设定基准后,您只需要在第一次使用。


94
由于您的fork仅存在于github上,而github没有通过Web界面进行合并的工具,因此正确的答案是在本地进行上游合并并将更改推送回您的fork。
Tim Keating 2012年

29
这是我在使用github时发现的很棒的教程:gun.io/blog/how-to-github-fork-branch-and-pull-request
Tim Keating

50
简要说明一下,您不必重新建立自己的master分支以确保从干净状态开始,您可能应该在单独的分支上进行工作并从中发出拉取请求。这样可以使您的母版在以后的合并中保持干净,并且使您不必重写历史记录,-f而使所有可能克隆您的版本的人都陷入混乱。
Mateusz Kowalczyk

11
我没有使用rebase命令,而是使用了以下命令: git merge --no-ff upstream/master这样,您的提交不再是最重要的了。
Steckdoserich '16

51
另一个Git失败。如果该工具应支持分布式协作,那么为什么执行基本工作流程如此困难?400万人和2200次投票意味着该工具失败了。“您可以将原始的GitHub存储库添加为“远程” -为什么甚至必须这样做?为什么在派生过程中没有完成?这个工具有什么
坏处

738

从2014年5月开始,可以直接从GitHub更新fork。到2017年9月,它仍然有效,但是会导致肮脏的提交历史。

  1. 在GitHub上打开fork。
  2. 点击Pull Requests
  3. 点击New Pull Request。默认情况下,GitHub会将原始内容与您的fork进行比较,如果您未进行任何更改,则不应有任何可比较的内容。
  4. switching the base如果您看到该链接,请单击。否则,请手动将base fork下拉菜单设置为fork,将其head fork设置为上游。现在,GitHub将把您的fork与原始的进行比较,您应该会看到所有最新的更改。 在此处输入图片说明
  5. Create pull request并为您的提取请求分配一个可预测的名称(例如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对其仓库进行上游更新,但是这样做可以确保您的提交历史记录。坚持使用命令行 -这很容易。


19
这一次很棒。第二次,此过程的工作方式不同:“切换基础”链接未显示。当我点击“单击以创建请求请求”时,它在SOURCE存储库上创建了PR。不是我想要的..
javadba 2014年

29
仍然有效(Marchi 2015),尽管“切换基础”链接不再存在。您必须更改“ Base”下拉列表的位置,使它们都指向您的fork,然后提示“ Compare through repos”,这将带您到所需的位置。
mluisbrown 2015年

8
2015年4月。作品。谢谢。我确实得到了“切换到基础”。但是,步骤6是“创建请求请求”->输入注释->“创建请求请求”。最终比原始提交1次。
cartland 2015年

5
@cartland(或其他)-是的,它说“此分支比...早1个提交”。这是否值得担心?是否有可能摆脱该信息?
RenniePet 2015年

11
只需更新或同步按钮,会不会更好!
变形金刚

456

这是GitHub上有关同步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分支存储在本地分支中,上游/ 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
这将更新我的本地fork,但是我在Github.com上的fork仍然显示“ 43 commits after”。我必须使用lobzik的技术为自己创建拉取请求,以将主更改合并到我的Github.com分支中。
Michael McGinnis 2015年

11
@MichaelMcGinnis在本地合并后,您必须将更改推送到github。git push origin master
jumpnett'2

1
可能会很聪明地推送--follow-tagsstackoverflow.com/a/26438076/667847
kenny 2015年

1
我必须分别为所有分支机构执行此操作git merge upstream/master,然后签出以开发分支机构并进行git merge upstream/develop
Shobi,

stackoverflow.com/a/14074925/470749对我有所帮助,因为Permission denied (publickey). fatal: Could not read from remote repository.尝试从Facebook的Github帐户上游获取信息时会遇到问题。
瑞安

98

许多答案最终导致将叉子一次提交移到父存储库之前。该答案总结了此处找到的步骤这些步骤会将您的fork移至与父代相同的提交

  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


13
@MT:不过,您在哪里输入这些命令?据我了解,该问题的要点是如何将您的个人GitHub fork与主项目重新同步,并通过GitHub完成所有操作。换句话说,如何在没有本地存储库的情况下更新远程fork ?
约翰Y

4
@JohnY使用GitHub将始终创建一个额外的提交。您需要在本地存储库的shell中执行所有这些操作,以避免额外的提交。
乔纳森·克罗斯

48

前言:您的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. 存放“主”分支的更改:

    git stash
    
  5. 将更改从“上游”的“主”分支合并到“来源”的“主”分支中:

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

    git commit -am "Merged from upstream"
    
  7. 将更改推送到你的叉子

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

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

GitHub还提供了有关该主题的说明:同步fork


1
部分获得帮助:git remote add upstream git@github.com:original_author/project_name.git仅仅是的别名git remote add upstream https://github.com/original_author/project_name.git吗?

2
Wolf,猜想您现在已经知道了,但是为了后代……这是ssh的格式。help.github.com/articles/configuring-a-remote-for-a-fork
Brad Ellis,

2
非常感谢你。git stash并且git stash pop非常有帮助
1919年

这工作了。在git merge上游/主服务器之后,由于未合并的路径,自动合并失败了,我必须运行git add -A然后git commit -m“ message”然后它是最新的。
highcenbug '19

47

如果像我一样,您从未真正将任何事情直接提交给master,那么您应该执行以下操作。

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

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

然后,无论何时要赶上上游存储库主分支,都需要:

git checkout master
git pull upstream master

假设您自己从未对master做出任何承诺,那么您应该已经完成​​。现在,您可以将本地主机推送到源远程GitHub分支。您还可以将开发分支基于最新的本地主数据库。

在完成初始上游设置和master检出之后,您所需要做的就是运行以下命令将您的master与上游同步:git pull上游master


45

自2013年11月以来,GitHub公开了一个非正式的功能请求,要求他们添加一种非常简单直观的方法来使本地fork与上游保持同步:

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

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


23

截至本答案发布之日,GitHub 在Web界面中尚未(或我不再说吗?)此功能。但是,您可以要求support@github.com增加对此的投票。

同时,GitHub用户bardiharborow创建了一个工具来执行此操作: https ://upriver.github.io/

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


2
虽然我确实找到了该工具的一个好主意,但事实是这样的。它确实从我的帐户中仅加载了20个存储库,甚至页脚也重定向到了一个不存在的网站。如果这是固定的,我将是一个坚定的拥护者。
索林

2
从今天开始,我已经成功地使用了upriver来将fork与上游repo进行同步,因此它可以满足我的目的,并且我将继续使用它。
NauticalMile

1
@sorin这20个仓库/分支限制(现在是30个)来自GitHub默认分页设置。为了处理此问题,需要对代码进行一些调整。
安德烈亚斯(Andreas)'18年


11

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

在此处输入图片说明

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

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


2
这很棒!这避免了将这些提交完全毫无意义地上传到github。
Rotsor

9

请遵循以下步骤。我尝试了一下,对我有帮助。

结帐至您的分行

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


1
如果您使用的是GitHub,则可能还希望将更改推送到GitHub分支。 git push HttpsForYourForkOfTheRepo BRANCH_NAME
user3731622 '16

9

我用这一行更新我的分叉存储库:

git pull https://github.com/forkuser/forkedrepo.git branch

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


2
这有限制吗?即,它仅适用于自上次更新以来您尚未添加提交,合并,拉取请求或将拉取请求合并到上游的情况吗?
LightCC

1
它的工作方式就像从远程分支正常拉出一样。如果您在本地存储库中进行了X提交,而现在您在原始存储库后面是Y提交,它将把Y提交带入您的本地分支,并可能使您遇到一些冲突来解决。
R.Bravo

1
@LightCC这与从先前添加的遥控器中拉出没有什么不同,除了您尚未添加remote。因此,缺点是您每次需要输入完整的存储库URL pull
Marc.2377 '19

1
如果您不必从原始存储库中拉很多次,或者分叉的项目相对简单,那么这是一个完美的解决方案。
AxeEffect

7

作为此答案的补充,我正在寻找一种方法,可以一口气从上游分支更新克隆的回购()的所有远程分支。这就是我做的。

假设您已经配置了指向源存储库(是从其派生的)的上游远程服务器,并且已与同步。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>在远程)上的远程分支。

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


6

“拉”应用是自动设置和忘记的解决方案。它将把fork的默认分支与上游存储库同步。

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

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


2
请注意,使用基本设置,您可能会丢失分叉存储库中所做的更改。要保留更改,请设置配置文件并指定一个mergemethod。更多关于此这里
SAURABH P班达里

1
我确实注意到,基本设置发送拉取请求并合并它们(与文档中所述相反)。这有点烦人,但是解决了数据丢失的问题?
krlmlr

4

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

打开菜单VCSGit

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

  • 重新整理我的GitHub fork

  • 创建请求请求

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

(我将Android Studio 3.0与“ Git集成”和“ GitHub”插件一起使用。)

在此处输入图片说明


4

克隆了分支的存储库后,转到克隆所在的目录路径以及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”时,您才会被告知同事推送到远程服务器的更改。

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


4

如果您设置上游。用选中git remote -v,然后就足够了。

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

2

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

如果它是一个很大的存储库,则您可能想以一种特殊的方式(例如删除历史记录)对其进行管理。基本上,您可以获取当前版本和上游版本之间的差异,提交它们,然后将其挑选回主版本。

尝试阅读这一本。它描述了如何处理大型Git存储库以及如何通过最新更改将其上游。


2

我想补充@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。如果发生合并冲突,则拉应用程序将允许您在拉请求期间选择下一个操作过程。

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

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


1

保持分支存储库始终保持最新状态主要有两件事。

1.从fork master 创建分支,然后在其中进行更改

因此,当您的请求请求被接受时,您可以安全地删除分支,因为当您使用上游更新它时,您贡献的代码将保存在您的分支存储库的主目录中。这样,您的母版将始终处于干净状态,以创建新分支来进行其他更改。

2.创建一个计划任务,以供fork主服务器自动更新

这可以使用cron完成。如果您在linux中进行操作,这是示例代码。

$ crontab -e

将此代码放在crontab file每小时执行一次的工作上。

0 * * * * sh ~/cron.sh

然后创建cron.sh脚本文件和与ssh-agentgit交互和/或期望如下

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

在此处输入图片说明


0

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

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.