我分叉了一个项目,进行了更改,并创建了一个被接受的拉取请求。新的提交后来被添加到存储库中。我如何将这些提交放入我的分叉中?
在分叉存储库的本地克隆中,您可以将原始 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 月仍然有效,但它会导致一个肮脏的提交历史。
在 GitHub 上打开你的 fork。单击拉取请求。单击新的拉取请求。默认情况下,GitHub 会将原始版本与您的 fork 进行比较,如果您未进行任何更改,则不应有任何可比较的内容。如果您看到该链接,请单击切换基础。否则,手动将基叉下拉设置为您的前叉,将头叉设置为上游。现在 GitHub 会将您的 fork 与原始版本进行比较,您应该会看到所有最新的更改。创建拉取请求并为您的拉取请求分配一个可预测的名称(例如,从原始更新)。向下滚动到合并拉取请求,但不要单击任何内容。
现在您有三个选项,但每个选项都会导致提交历史不太干净。
默认将创建一个丑陋的合并提交。如果您单击下拉菜单并选择“压缩并合并”,则所有介入的提交都将被压缩为一个。这通常是您不想要的。如果你点击 Rebase and merge,所有的提交都会“和”你一起进行,原来的 PR 会链接到你的 PR,GitHub 会显示 This branch is X commits ahead, Y commits behind
所以是的,你可以使用 GitHub Web UI 让你的 repo 更新到它的上游,但是这样做会破坏你的提交历史。请改用 the command line - 这很简单。
这是 GitHub 在 Syncing a fork 上的官方文档:
同步一个 fork 设置 在同步之前,您需要添加一个指向上游存储库的远程。当你最初分叉时,你可能已经这样做了。提示:同步你的 fork 只会更新你的本地仓库副本;它不会更新您在 GitHub 上的存储库。 $ git remote -v # 列出当前遥控器 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 # 设置一个新的远程 $ git remote -v # 验证新的远程源 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 # 抓取上游远程的分支 remote: Counting objects: 75, done。远程:压缩对象:100% (53/53),完成。远程:总共 62 个(增量 27),重复使用 44 个(增量 9) 拆包对象:100% (62/62),完成。来自 https://github.com/otheruser/repo * [new branch] master -> upstream/master 我们现在将上游的 master 分支存储在本地分支中,upstream/master $ git branch -va # 列出所有本地和远程-tracking branches * master a422352 我的本地提交 remotes/origin/HEAD -> origin/master remotes/origin/master a422352 我的本地提交 remotes/upstream/master 5fdff0f 一些上游提交 Merging 现在我们已经获取了上游存储库,我们想要将其更改合并到我们的本地分支中。这将使该分支与上游同步,而不会丢失我们的本地更改。 $ git checkout master # 查看我们本地的 master 分支 Switched to branch 'master' $ git merge upstream/master # 合并上游的 master 到我们自己的 Updating a422352..5fdff0f Fast-forward README | 9 -------- 自述文件.md | 7 ++++++ 2 个文件更改,7 个插入(+),9 个删除(-)删除模式 100644 README 创建模式 100644 README.md 如果您的本地分支没有任何唯一提交,git 将改为执行“快进”:$ git merge upstream/master 更新 34e91da..16c56ad 快进 README.md | 5 +++-- 1 个文件更改,3 个插入 (+),2 个删除 (-) 提示:如果您想在 GitHub 上更新您的存储库,请按照此处的说明进行操作
git push origin master
--follow-tags
推送可能很聪明:stackoverflow.com/a/26438076/667847
git merge upstream/master
,然后签出开发分支并做git merge upstream/develop
很多答案最终会将您的 fork 一个提交提前移到父存储库。此答案总结了 here 找到的步骤,这些步骤将将您的 fork 移动到与父级相同的提交。
将目录更改为您的本地存储库。如果您不是 git checkout master 则切换到 master 分支将父级添加为远程存储库, git remote add upstream
有关这些命令的更多信息,请参阅 step 3。
如果像我一样,你从来没有直接向 master 提交任何东西,你真的应该这样做,你可以执行以下操作。
从 fork 的本地克隆,创建上游远程。你只需要这样做一次:
git remote add upstream https://github.com/whoever/whatever.git
然后,每当您想赶上上游存储库主分支时,您需要:
git checkout master
git pull upstream master
假设你自己从来没有在 master 上做过任何事情,你应该已经完成了。现在,您可以将本地 master 推送到您的源远程 GitHub 分支。您还可以在您现在最新的本地 master 上重新设置您的开发分支。
通过初始上游设置和 master 结帐,您需要做的就是运行以下命令将 master 与上游同步:git pull upstream master。
git checkout my-dev-branch
切换到您的开发分支,然后运行 git rebase master
。您也可以只运行 git rebase master my-dev-branch
,它基本上结合了这两个命令。请参阅git rebase docs。
前言:你的 fork 是“起源”,而你 fork 的存储库是“上游”。
假设您已经使用以下命令将 fork 克隆到您的计算机:
git clone git@github.com:your_name/project_name.git
cd project_name
如果给出了,那么您需要按以下顺序继续:
将“上游”添加到您的克隆存储库(“origin”): git remote add upstream git@github.com:original_author/project_name.git 从“上游”获取提交(和分支): git fetch upstream 切换到“ master”分支(“origin”): git checkout master 存储“master”分支的更改:git stash 将“upstream”的“master”分支的更改合并到你的“master”分支中"origin": git merge upstream/master 解决合并冲突(如果有)并提交你的合并 git commit -am "Merged from upstream" 将更改推送到你的 fork git push 取回你隐藏的更改(如果有的话) git stash pop 你是完毕!恭喜!
GitHub 还提供了有关此主题的说明:Syncing a fork
git remote add upstream git@github.com:original_author/project_name.git
只是 git remote add upstream https://github.com/original_author/project_name.git
的别名吗?
git stash
和 git stash pop
部分非常有帮助
自 2013 年 11 月以来,GitHub 收到了一个非官方的功能请求,要求他们添加一种非常简单直观的方法来保持本地分支与上游同步:
https://github.com/isaacs/github/issues/121
注意:由于该功能请求是非官方的,因此建议您联系 support@github.com
以添加您对要实施的此类功能的支持。上面的非官方功能请求可以用作对此正在实施的兴趣量的证据。
GitHub 现在引入了一项功能,只需单击按钮即可同步分叉。
转到您的 fork,点击 Fetch upstream
,然后点击 Fetch and merge
直接将您的 fork 与其父 repo 同步。
https://i.stack.imgur.com/NKEzt.png
您也可以点击 Compare
按钮来比较合并前的更改。
参考:GitHub 的 documentation
有三种方法可以做到这一点:从 Web UI(选项 1)、从 GitHub CLI(选项 2)或从命令行(选项 3)。
选项 1 - 网页界面
在 GitHub 上,导航到要与上游存储库同步的分叉存储库的主页。选择获取上游下拉菜单。
https://i.stack.imgur.com/KrwzJ.png
查看来自上游存储库的提交的详细信息,然后单击 Fetch and merge。
https://i.stack.imgur.com/Yzcz1.png
选项 2 - GitHub CLI
要从其父级更新远程分叉,请使用 gh repo sync
子命令并提供您的分叉名称作为参数。
$ gh repo sync owner/cli-fork
如果上游存储库的更改导致冲突,则 GitHub CLI 无法同步。您可以设置 -force
标志来覆盖目标分支。
如何安装 GitHub CLI
GitHub CLI 手册
选项 3 - 命令行
在将自己的分叉与上游存储库同步之前,必须在 Git 中configure a remote that points to the upstream repository。
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'
将上游默认分支(在本例中为 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 - Syncing a fork
截至本答案发布之日,GitHub 尚未 (or shall I say no longer?) 在 Web 界面中提供此功能。但是,您可以要求 support@github.com
对此投票。
与此同时,GitHub 用户 bardiharborow 创建了一个工具来执行此操作: https://upriver.github.io/
来源在这里:https://github.com/upriver/upriver.github.io
如果您使用 GitHub for Windows 或 Mac,那么现在它们具有一键更新 forks 的功能:
在 UI 中选择存储库。单击顶部的“从用户/分支更新”按钮。
实际上,可以从浏览器中上游的任何提交在您的 fork 中创建一个分支:
打开 https://github.com/
单击“树:....”按钮。
输入新分支的名称,然后按 Enter
https://i.stack.imgur.com/gFNOd.png
然后,您可以将该分支获取到您的本地克隆,当您在该提交之上推送编辑时,您不必将所有数据推送回 GitHub。或者使用 Web 界面更改该分支中的某些内容。
它是如何工作的(这是一个猜测,我不知道 GitHub 到底是怎么做的):forks 共享对象存储并使用 namespaces 来分隔用户的引用。因此,您可以通过您的 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 push HttpsForYourForkOfTheRepo BRANCH_NAME
我用这一行更新了我的分叉回购:
git pull https://github.com/forkuser/forkedrepo.git branch
如果您不想将另一个远程端点添加到您的项目中,请使用此选项,就像此处发布的其他解决方案一样。
pull
时都必须输入完整的存储库 URL。
作为对这个答案的补充,我正在寻找一种方法来一次从上游分支更新我的克隆仓库(来源)的所有远程分支。我就是这样做的。
这假设您已经配置了一个 upstream 远程指向源存储库(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
该命令的第一部分列出了 upstream 远程 repo 中的所有头,并删除了 SHA-1 后跟 refs/heads/
分支名称前缀。
然后对于这些分支中的每一个,它将 upstream 远程跟踪分支(本地端的 refs/remotes/upstream/<branch>
)的本地副本直接推送到 origin 上的远程分支({2 } 在远程端)。
这些分支同步命令中的任何一个都可能由于以下两个原因之一失败:upstream 分支已被重写,或者您已将该分支上的提交推送到您的 fork。在第一种情况下,您没有向 fork 上的分支提交任何内容,强制推送是安全的(添加 -f 开关;即上面命令中的 git push -f
)。在另一种情况下,这是正常的,因为您的 fork 分支已经发散,并且在您的提交合并回 upstream 之前,您不能期望同步命令起作用。
"Pull" app 是一种自动设置和忘记的解决方案。它会将你的 fork 的默认分支与上游存储库同步。
访问 URL,单击绿色的“安装”按钮并选择要启用自动同步的存储库。
该分支每小时直接在 GitHub 上更新一次,在您的本地机器上,您需要拉取 master 分支以确保您的本地副本是同步的。
mergemethod
。有关此here的更多信息
如果你设置你的上游。检查 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”时,您才会被告知您的同事推送到远程服务器的更改。
您仍然可以访问 here 进行进一步查询
$ git remote add upstream https://github.com/....
$ git pull upstream main
$ git push
假设您的 fork 是 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 在下一页上,滚动到页面底部并单击 Merge拉取请求并确认合并。
使用此代码段生成链接以同步您的分叉存储库:
新 Vue ({ el: "#app", data: { yourFork: 'https://github.com/me/foobar', originalRepo: 'https://github.com/someone/foobar' }, 计算: { 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 '没有足够的数据' } } }) < div id="app"> 你的分叉 URL:
原始存储库 URL:
同步你的 fork 的链接:{{syncLink}}
Android Studio 现在已经学会了使用 GitHub fork 存储库(您甚至不必通过控制台命令添加“上游”远程存储库)。
打开菜单 VCS → Git
并注意最后两个弹出菜单项:
Rebase 我的 GitHub 分支
创建拉取请求
试试看。我使用第一个来同步我的本地存储库。无论如何,在您单击“Rebase my GitHub fork”后,将可以在 Android Studio 中访问来自父远程存储库(“上游”)的分支,并且您将能够轻松地使用它们进行操作。
(我使用带有“Git 集成”和“GitHub”插件的 Android Studio 3.0。)
https://i.stack.imgur.com/2poHE.png
这取决于您的存储库的大小以及您如何分叉它。
如果它是一个相当大的存储库,您可能希望以一种特殊的方式来管理它(例如删除历史记录)。基本上,您可以获得当前版本和上游版本之间的差异,提交它们,然后将它们挑选回 master。
尝试阅读this one。它描述了如何处理大型 Git 存储库以及如何使用最新更改将它们上传到上游。
最初,分叉的存储库有一个名为:master
的分支。如果您正在开发新功能或修复,您通常会创建一个新分支 feature
并进行更改。
如果您希望分叉存储库与父存储库同步,您可以为 Pull app(在功能分支中)设置一个配置文件 (pull.yml
),如下所示:
version: "1"
rules:
- base: feature
upstream: master
mergeMethod: merge
- base: master
upstream: parent_repo:master
mergeMethod: hardreset
这使分叉存储库的 master
分支与父存储库保持同步。它通过合并相同的分叉存储库的 master
分支来更新分叉存储库的 feature
分支。这假定 feature
分支是包含配置文件的默认分支。
这里有两个 mergemethods
,一个是 hardreset
,它有助于强制将分叉存储库的 master
分支中的更改与父存储库同步,另一种方法是 merge
。此方法用于合并您在 feature
分支中所做的更改和由于在 master
分支中强制同步而完成的更改。在合并冲突的情况下,拉取应用程序将允许您在拉取请求期间选择下一个操作过程。
您可以阅读基本和高级配置以及各种 mergemethods
here。
我目前在我的分叉存储库 here 中使用此配置,以确保请求的增强功能 here 保持更新。
https://i.stack.imgur.com/GPkH4.png
保持分叉存储库始终保持更新有两个主要方面。
1. 从 fork master 创建分支并在那里进行更改。
因此,当您的拉取请求被接受时,您可以安全地删除分支,因为当您使用上游更新它时,您贡献的代码将存在于您的分叉存储库的主控中。这样,您的 master 将始终处于干净状态,可以创建一个新分支来进行另一次更改。
2. 为 fork master 创建一个计划作业以自动更新。
这可以通过 cron 来完成。如果您在 linux 中执行此操作,这是一个示例代码。
$ crontab -e
将此代码放在 crontab file
上以每小时执行一次作业。
0 * * * * sh ~/cron.sh
然后使用 ssh-agent 和/或 expect 创建 cron.sh
脚本文件和 git interaction,如下所示
#!/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`
检查您的分叉存储库。它会不时显示此通知:
这个分支甚至是
https://chetabahana.github.io/images/github/screencapture-github.png
使用这些命令(在幸运的情况下)
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
git add
命令的解析。此外,如果有问题的 repo 是一个分叉的,那么某人必须首先定义 upstream
: git remote add upstream https://...git
,其中 git 是用于分叉的 repo。
如果您使用 GitHub Desktop,只需 6 步(实际上只有 5 步)即可轻松完成。
打开 Github Desktop 并选择您的存储库后,
转到历史选项卡 单击搜索栏。它将向您显示所有可用的分支(包括来自父存储库的上游分支)选择相应的上游分支(它将是上游/主同步主分支)(可选)它将向您显示上游分支中的所有提交。您可以单击任何提交以查看更改。根据您的活动分支,单击在 master / branch-name 中合并。等待 GitHub Desktop 施展魔法。
以下面的 GIF 为例:
https://i.stack.imgur.com/EVrU2.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 ...
可能有更微妙的选择,但这是我确信我的本地存储库与上游相同的唯一方法。
-f
重写历史记录,这会弄乱所有可能克隆您的版本的人。git merge --no-ff upstream/master
这样您的提交就不再是最重要的了。