查看【Git】专题可浏览更多内容
如果我们直接对一个第三方的 Github 项目进行推送将会看到这样的提示:
ERROR: Permission to github/repo.git denied to Example.
致命错误:无法读取远程仓库。
请确认您有正确的访问权限并且仓库存在。
解决这个权限问题的办法有两种:
作为 Collaborator
如果这个 Github 项目实际上是团队或公司的一个项目,那么可以让项目的所有人邀请你,给予你权限。
在项目的「Settings」的「Access」下的「Collaborators」中,可以通过「Add People」添加 Github 用户:
在添加后拥有了这个仓库的权限,就可以正常推送了。
除了这个方法还有一种常见的场景是,你遇到了一个开源在 Github 上的项目,但它有点小问题而你恰好知道解决办法,那么除了提 Issue 也可以自己改进好然后申请提交给项目主,这就是第二种方法
使用 Fork 及 Pull Request
Fork
首先,我们先进行 Fork
点击要参与贡献的项目右上角的「Fork」,然后可选修改 Fork 到你 Github 帐户上的仓库名
所谓「Fork」仓库类似于复制仓库,用于更改项目而不影响原始仓库。 之后可以通过拉取请求从原始仓库提取更新,或者提交更改到原始仓库。
注意左上角,可以看到现在这个项目来源于哪个帐户下的什么仓库
然后就可以根据你的方式选择 HTTPS 或 SSH 将仓库克隆到本地计算机上,如果你没有做过这方面的验证可以查看 使用 SSH 或 Token 向 GitHub 进行身份验证 一文
创建特性/开发分支
在克隆自己帐户上 Fork 而来的远程仓库到本地后,第一步应该是创建一个特性分支用于改动,而不是直接在主分支 (master
或 main
) 上改动
# 创建并切换到名为 feature 的分支
git switch -c feature
然后就可以做改动并推送 feature
:
git add .
git commit -m '改动标题' -m '改动内容描述'
# 推送 feature 分支
git push -u origin feature
到这里,你的 Github 帐户的仓库就有了 feature
分支
原仓库有了更新
在我们进行本地修改的时候,很可能原仓库有了别的更新,这时候要如何同步原仓库的改动?
你可以选择 Github 页面上的「Sync fork」功能点点鼠标:
之后你要从 feature
分支切换回主分支,然后 git pull origin master
拉取下来
或者通过命令行实现:
首先我们要在本地计算机的仓库上添加原仓库的远程信息:
# 添加原仓库的远程信息,将原仓库命名为 upstream
git remote add upstream https://github.com/github/repo.git
# 查看下远程仓库信息
git remote -v
origin https://github.com/Nobody/repo.git (fetch)
origin https://github.com/Nobody/repo.git (push)
upstream https://github.com/github/repo.git (fetch)
upstream https://github.com/github/repo.git (push)
origin
表示我们 Github 帐户上 Fork 而来的仓库,upstream
表示所 Fork 的原仓库
接着获取原仓库数据:
git fetch upstream
然后要合并原仓库的更新到本地主分支上了,当前是不是还在feature
分支上开发呢?
# 切换到主分支
git switch master
并不是所有的项目的主分支都叫 master
,因为「政治正确」现在许多新项目改叫 main
了,根据你的实际情况来吧
然后将改动合并到本地当前分支:
git merge upstream/master
同样的,这里如果原项目中的主分支为 main
就要修改为 upstream/main
现在你本地仓库的 master
分支已经和原仓库的更新同步了,但你 Github 上 Fork 而来的仓库还没有,所以如果有必要就进行推送 master
:
git push origin master
推送特性/开发分支
同步了原仓库的改动后,现在回到 feature
分支,假设现在改动也改动好了可以推送了,那么:
# 回到 feature 分支
git switch feature
# 先把原仓库同步到本地 master 分支的最新修改放进来,再放上自己的修改
git rebase master
# 使用以上命令后可以使用 git log 看看历史记录的变化
# 然后推送 feature 到 github
git push -f origin feature
为什么最后一步加了 -f
选项,不是都说最好不用该选项吗?
首先这个操作只是在自己的项目上,其次如果在 git rebase
操作之前如上示例,在拉取原仓库最新修改前有过一次推送,那么当前本地 feature 和你 Github 上的 feature 是有所不同的。
你本地 feature 的历史中多了原仓库的更新,和之前推送不一样了。
创建 Pull Request
前往你的 Github 项目,点击「Pull requests」
点击右侧的「New pull request」按钮创建一个 Pull Request
如上图,主要是三个部分:
- 请求的项目为
github/repo
,从我的 Github 项目Nobody/repo
的feature
分支合并修改 - 然后是填写请求的标题及内容,为什么要做这些、大概做了什么修改进行描述一下;
- 在页面底部还有修改前后的修改对比部分,不过这部分不是本文重点就不截图了;
在确定后就可以点击「Create pull request」了
管理 Pull Request
现在转换身份,如果你是一个项目主,该如何处理 Pull Request 呢?
你可以在这个界面预览修改、改动了什么文件、有哪些提交,也可以使用右侧列表的功能,比如加上标签等等
你还可以在 Commit 中的具体一行通过点击蓝色加号按钮添加评论,例如说你认为某段代码可以进一步改进等等
最后如果你觉得这次请求并不合理可以选择「Close pull request」,或点击绿色按钮进行 Merge
Pull Request 的几种合并有什么不同?
在 Merge 按钮的右侧有个下拉按钮,你可以看到有几种不同的合并方式,那么它们有什么不同呢?
「Create a merge commit」:
* commit 686785618ac8795a7eaa412049e7f859869ed8f3 (HEAD -> master, origin/master, origin/HEAD)
|\ Merge: 9ef96c8 94fd1f1
| | Author: Github <[email protected]>
| |
| | Merge pull request #1 from Nobody/repo
| |
| * commit 94fd1f1f76b3c6a0a296ea64f0983aafc141230d
| | Author: Nobody <[email protected]>
| |
| | docs: Fix content
| |
| * commit 8f832d016c82b0b5d1f8dad27aba0b507f468052
|/ Author: Nobody <[email protected]>
|
| docs: Fix title
|
* commit f6112e6c5721a95d204f215227c48c9f7d33dee1
| Author: Github <[email protected]>
|
| docs: add README.md
|
* commit b36602c3bf6c3be2a989d48e35834a14757b2550
Author: Github <119[email protected]>
Initial commit
可以看到,使用「Create a merge commit」除了贡献者自己的提交,还会多一个合并提交,即「Merge pull request #1 from Nobody/repo」
并且可以看到支线有分开在合并的记录
「Squash and merge」:
* commit b27cfa1afdafea6d740f01668d7ace5de0cb4eab (HEAD -> master, origin/master, origin/HEAD)
| Author: Nobody <[email protected]>
|
| docs: Fix format error
|
* commit f6112e6c5721a95d204f215227c48c9f7d33dee1
| Author: Github <[email protected]>
|
| docs: add README.md
|
* commit b36602c3bf6c3be2a989d48e35834a14757b2550
Author: Github <119[email protected]>
Initial commit
而使用「Squash and merge」会将贡献者的提交合并成一条提交
「Rebase and merge」
* commit 94fd1f1f76b3c6a0a296ea64f0983aafc141230d (HEAD -> master, origin/master, origin/HEAD)
| Author: Nobody <[email protected]>
|
| docs: Fix content
|
* commit 8f832d016c82b0b5d1f8dad27aba0b507f468052
| Author: Nobody <[email protected]>
|
| docs: Fix title
|
* commit f6112e6c5721a95d204f215227c48c9f7d33dee1
| Author: Github <[email protected]>
|
| docs: add README.md
|
* commit b36602c3bf6c3be2a989d48e35834a14757b2550
Author: Github <119[email protected]>
Initial commit
使用「Rebase and merge」会将贡献者的提交记录直接合并入分支,而且可以看到分支是一条直线