Skip to content

Github进行fork后如何与原仓库同步:重新fork很省事,但不如反复练习版本合并 #67

Open
@liujuanjuan1984

Description

@liujuanjuan1984
Contributor

下面2楼和3楼,都可能是你需要的。

Activity

changed the title [-]guideline for merge[/-] [+]Github进行fork后如何与原仓库同步/重新fork很麻烦?试试合并吧。。[/+] on Mar 15, 2019
liujuanjuan1984

liujuanjuan1984 commented on Mar 15, 2019

@liujuanjuan1984
ContributorAuthor

Github进行fork后如何与原仓库同步

实在是……有太多人同时在帮忙修订错别字或优化 xiaolai 的 the-craft-of-selfteaching 了。如果你提交的 pull request 未被接受且得到回复说:“重新fork”,其实是你遇到一个问题:

  • 在你 fork 之后, xiaolai 的仓库又更新了;
  • 但 github 不会自动帮你把 xiaolai 的仓库 同步给你 fork 后的仓库;
  • 导致你提交 pull request 时的版本和 xiaolai 的版本不一致。

这个问题,用显得更“专业点”的说法,叫做:Github进行fork后如何与原仓库同步。那到底怎么做呢?

最省事的办法可能是:

  • 在你fork的仓库setting页翻到最下方,然后delete这个仓库;
  • 然后重新fork xiaolai 的仓库,并 git clone 到你的本地。

有时候,你需要用到这个省事的办法,比如 xiaolai 的仓库再次整理了 commit 。但在更多情况下,删掉自己fork的库,应该是你的最后选择,而不应该是首选。

和很多人一起向 xiaolai 提交 pull request,这实在是一个反复练习 merge (中文说法:合并,或版本合并)的机会。毫不夸张地讲,版本管理是软件工程极其重要的规范,也是极其基础的必备技能。而 merge 则是版本管理中最必须也最常用的场景。

那要不然,就多练练?以下是傻瓜版操作步骤,还细心配了截图,保管你从 0 也能上手。至于原理嘛,慢慢再搞懂吧。

merge前的设定

step 1、进入到本地仓库的目录。

下面所有操作,如无特别说明,都是在你的本地仓库的目录下操作。比如我的本地仓库为/from-liujuanjuan-the-craft-of-selfteaching

image

step 2、执行命令 git remote -v 查看你的远程仓库的路径:

image

如果只有上面2行,说明你未设置 upstream (中文叫:上游代码库)。一般情况下,设置好一次 upstream 后就无需重复设置。

step 3、执行命令 git remote add upstream https://github.com/selfteaching/the-craft-of-selfteaching.git 把 xiaolai 的仓库设置为你的 upstream 。这个命令执行后,没有任何返回信息;所以再次执行命令 git remote -v 检查是否成功。

image

step 4、执行命令 git status 检查本地是否有未提交的修改。如果有,则把你本地的有效修改,先从本地仓库推送到你的github仓库。最后再执行一次 git status 检查本地已无未提交的修改。

git add -A 或者 git add filename
git commit -m "your note"
git push origin master
git status

注1:这一步作为新手,建议严格执行,是为了避免大量无效修改或文本冲突带来的更复杂局面。

注2:如果你已经在fork后的仓库提交了大量对 xiaolai 的仓库并没有价值的修改,那么想要pull request,还是重新回到本文最初的“最省事办法”吧。

merge 的关键命令

以下操作紧接着上面的步骤。

step 5、执行命令 git fetch upstream 抓取 xiaolai 原仓库的更新:

image

step 6、执行命令 git checkout master 切换到 master 分支:

image

step 7、执行命令 git merge upstream/master 合并远程的master分支:

image

step 8、执行命令 git push 把本地仓库向github仓库(你fork到自己名下的仓库)推送修改

如果担心自己不小心改了哪里,可以再次执行命令 git status 检查哪些文件有变化。这个操作仅是检查,不会改变任何状态,放心用。

image

现在你已经解决了fork的仓库和原仓库版本不一致的问题。可以放心向 xiaolai 发起 pull request 了。如果以上操作你花了不少时间,而 xiaolai 的仓库 又恰好更新了。很好,一次新的练习机会来了……

ZoomQuiet

ZoomQuiet commented on Mar 15, 2019

@ZoomQuiet
Contributor

是也乎,( ̄▽ ̄)

增补之前想增补到 ipynb 中的阐述

PS: 如何优雅的获得上游最新内容?

... 必须重新弄一个当前最新版本到本地

这是一个常见 github 操作, 但是, 其操作涉及复杂的 git 概念,
所以, 在此简要描述一下最小过程(MVP):

1: 首先, 新增 remote (远程上游仓库), 即, 将本书仓库, 追加为 fork 仓库的上游仓库

git remote add upstream https://github.com/selfteaching/the-craft-of-selfteaching.git

此时检验本地工作复本仓库的配置就可以看到变化:

$  cat .git/config

...

[branch "master"]
	remote = origin
	merge = refs/heads/master
[remote "upstream"]
	url = https://github.com/selfteaching/the-craft-of-selfteaching.git
	fetch = +refs/heads/*:refs/remotes/upstream/*

在底部追加了 upstream (上游)仓库信息, 可以用 branch 命令来检验

$  git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/upstream/master

2: 同步上游修订, 使用 fetch 命令

$  git fetch upstream
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Total 12 (delta 2), reused 2 (delta 2), pack-reused 10
Unpacking objects: 100% (12/12), done.
From https://github.com/selfteaching/the-craft-of-selfteaching
   7b3aeea..4646cc8  master     -> upstream/master

然后, 在此基础上进行修订, 以及 Pull-Request 才是正义的.

简单的说:

  • 声明上游仓库
  • 每次进行修订前先 fetch 上游修订
  • 如果和本地有冲突, 先在本地解决冲突

PPS:

软件工程中协同方式原则

在哪些情况下可以直接使用master branch来提交Pull Request:

你只想为主项目贡献某一处代码,贡献完自己的repo就可以扔的那种。
你打算为主项目长期贡献代码,而且希望追随原项目的主线开发,不保留自己的特性。
你打算为主项目长期贡献代码,默认master branch追随原项目主线,把自己的特性放到别的branch中。

在哪种情况下应该使用主题branch来提交Pull Request:

想用master branch完全来做自己的开发。在这种情形下:会从上游库合并更新,但是这些merge本身的commits显然不可能作为返还到上游库的Pull Request的一部分。
存在自己的(未被merge或者不想被merge到上游库的)commits。

鉴于Git的分布式开发哲学,每一个库均可以看作是一个独立的项目,显然是后一种(为每一个新特性建立一个专门的主题branch来向主项目推送Pull Request)的贡献方式更可取。
解释完毕(`・ω・´)

引用自: 如何参与Tianchi(天池)项目以及如何贡献代码 - QTCN开发网 - Powered by phpwind

changed the title [-]Github进行fork后如何与原仓库同步/重新fork很麻烦?试试合并吧。。[/-] [+]Github进行fork后如何与原仓库同步:重新fork很省事,但不如反复练习版本合并[/+] on Mar 15, 2019
yingca1

yingca1 commented on Mar 16, 2019

@yingca1

如果远程主仓库的历史 commits 被修改整理过,而自己在未同步远程主仓库的情况下有新的 PR 需要提交,可以有两个方案处理:

  1. fork 最新的远程主仓库,重新提交
    1.1 备份自己的改动
    1.2 删除自己的 fork 的仓库,重新 fork 远程主仓库
    1.3 将最新改动的应用到新 fork 的仓库,然后提交 PR

  2. 强制同步远程主仓库的所有历史 commits,处理冲突,再次提交
    1.1 备份自己的改动(可以选择用一个新的分支或者直接将问题复制到本地存储的其他文件目录)
    1.2 添加远程主仓库为自己本地仓库的一个 upstream(如命名为 origin),使用以下命令强制同步
    git fetch origin && git reset --hard origin/master && git clean -f -d
    1.3 将自己的改动应用到强制同步过的分支,如果使用的其他分支备份,可以使用 rebase 命令合并过来,如果有冲突,处理冲突
    1.4 检查自己的 commits 是否正确合理,无问题则可重新提交 PR

zhzja

zhzja commented on Mar 16, 2019

@zhzja

反复练习

gantrol

gantrol commented on Mar 16, 2019

@gantrol
Contributor

分享一个命令,直接强制同步源仓库(upstream),就不用删了。。

git fetch upstream && git reset --hard upstream/master && git push -f

git push -f确实是很粗暴,这种方法也只适用于不用保存自己的版本的情况而已。

blockchain-onlooker

blockchain-onlooker commented on Mar 16, 2019

@blockchain-onlooker

#144

@realcaiying 我就纳闷为啥楼主会作死去用rebase,原来是你挖的坑……

楼上 git push -f 其实也不是很可取的方案,虽然比直接删除仓库强。真不怕初学者习惯了,然后用这招破坏掉多人协作库么,为了防止这种情况,企业内部gitlab我都默认master分支不允许 git push -f

frostming

frostming commented on Mar 17, 2019

@frostming

不明白为啥要push -f, 如果你打算用git reset --hard upstream/master让master永远与上游同步的话。完全不用推到自己的fork,我本地开发一般都是这样的:以上游为主

git clone <upstream_repo_url>
git remote add fork <fork_repo_url>
git fetch origin
git reset --hard origin/master
git checkout -b feature-1
# do some change, commits
git push -u fork

每次同步上游就切到master执行git fetch origin && git reset --hard upstream/master,并不push 回去的啊。feature分支的冲突再用merge/rebase解决就好了。所以一般fork的master都是落后上游并从不更新。

PS: 此用法仅针对使用github-flow贡献的情况,即每次PR都是从feature分支发起,不适用上文提到的用master进行fork开发(不返回上游库)。

yingca1

yingca1 commented on Mar 17, 2019

@yingca1

#144

@realcaiying 我就纳闷为啥楼主会作死去用rebase,原来是你挖的坑……

楼上 git push -f 其实也不是很可取的方案,虽然比直接删除仓库强。真不怕初学者习惯了,然后用这招破坏掉多人协作库么,为了防止这种情况,企业内部gitlab我都默认master分支不允许 git push -f

git push -f 确实是很危险的操作,主仓库也只会开放给少数人这个权限。

显然本地仓库与主仓库的历史不一致是经常会出现的,在企业开发中,如果开发人数达到一定规模,代码回滚、整理历史 commits、测试主分支切换功能测试等可能造成自己仓库和主仓库历史不一致。

使用 git 达到同一个目的的方案有很种。提交 PR 的人不一定需要 git push -f 更改自己的远程仓库,其实楼主这个情况,只需要保证提交 PR 的分支与远程主仓库历史 commits 同源即可,方案很多可以选择。

richardchen0954

richardchen0954 commented on Mar 24, 2019

@richardchen0954
Contributor

在自己的 fork 页面 PullRequest,然后把 base 和 head 顺序调换一下,把源头的更新 merge 到自己 fork 的版本中,然后,pull 到本地也能同步。只不过节点看上去没有“一条龙”的样子好看。
反pull

sxuya

sxuya commented on Apr 11, 2019

@sxuya
Contributor

这些 fetch、commit 的命令操作,和在图形化应用 Github Desktop 上面进行点击操作,效果是一样的吧?

难道觉得这种点击操作太 low 了?

43 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @ZoomQuiet@lemonbox@qwfys@zhaopan@lhmwzy

        Issue actions

          Github进行fork后如何与原仓库同步:重新fork很省事,但不如反复练习版本合并 · Issue #67 · selfteaching/the-craft-of-selfteaching