概述
Git 除了可以操作本地仓库中的内容,还可以将本地仓库中的内容推送到远程仓库上。所谓的远程仓库,其实就是指代码托管平台,常有:
- Github
- Gitlab
- Gitee
- …
代码托管平台也可以从网络环境上进行划分:
- 局域网环境(自建 Gitlab)
- 公网环境,多人协作工作(Gitlab、Github、Gitee)
从项目角度来说:
- 开源的项目
- 闭源的私有项目
本地仓库与远程仓库的关系
第一种情况
团队内部协作,通常适用于私有项目:
第一次创建远程库,里面是空的,需要负责人手动 push
,同时建立团队且分配权限,邀请其他人加入团队。后面的开发人员加入团队后需要先 clone
远程库,当对项目做了修改后 push
到远程仓库,负责人就可以 pull
了。
第二种情况
跨团队协作,通常适用于开源项目:
团队领导者 A 给成员 B 下发一个工作任务,但 B 能力有限,可是他认识在这方面经验丰富的朋友 C,朋友 C 需要首先 Fork 项目到自己的远程仓库中,在正常的 clone
、push
操作之后,需要在 Github 中需要提交 pull request(一个通知机制,告诉源项目团队成员你做了哪些修改)。当代码通过审核后,就能在 A 的远程库中合并。
Fork 的意思是指复制一份所有者是你本人的副本项目,Fork 之后,您拥有该副本项目的所有权,即在遵守开源许可证协议的前提下,您可以做任何修改且不受权限控制,因为您就是该副本项目的所有者。
远程仓库的相关命令
常见命令有:
git clone
– 将远程仓库的项目克隆到本地的一个目录中git pull
– 先从远程仓库 "拉取" 最新的变更到本地,然后将变更合并到相应的分支中,等同于git fetch
和git merge
这两步操作git push
– 将所做的修改 "推送" 到远程仓库git remote
– 对远程仓库进行管理git ls-remote
– 查询远程仓库中的引用
示例
当您注册了 Github,可以创建全新的项目(项目可以是私有的,也可以是公开的):
从上到下依次是:
- 项目名称
- 项目说明
- 项目的状态(公开或私有)
- 是否添加 README 自述文件
- 是否添加 .gitignore 文件
- 是否添加开源许可证协议
# 将项目克隆到本地的一个目录中
PS > git clone https://github.com/xxxxx/xxxxxx.git
remote: Enumerating objects: 33264, done.
remote: Counting objects: 100% (723/723), done.
remote: Compressing objects: 100% (345/345), done.
Receiving objects: 2% (666/33264), 580.00 KiB | 47.00 KiB/s
# 默认情况下,我们远程仓库的名称为 origin,你也可以更改
PS > git remote show
origin
# 更改默认远程仓库名称的语法
PS > git remote rename <old> <new>
# 最终你本地仓库的分支会与远程仓库的分支相对应
PS > git branch -a
* m_cn
remotes/origin/HEAD -> origin/m_cn
remotes/origin/fix
remotes/origin/m_cn
remotes/origin/p1
remotes/origin/p2
PS > git switch fix
branch 'fix' set up to track 'origin/fix'.
Switched to a new branch 'fix'
PS > git switch p1
branch 'p1' set up to track 'origin/p1'.
Switched to a new branch 'p1'
PS > git switch p2
branch 'p2' set up to track 'origin/p2'.
Switched to a new branch 'p2'
PS > git remote show origin
* remote origin
Fetch URL: https://github.com/xxxx/xxxxx.git
Push URL: https://github.com/xxxxx/xxxx.git
HEAD branch: m_cn
Remote branches:
fix tracked
m_cn tracked
p1 tracked
p2 tracked
Local branches configured for 'git pull':
fix merges with remote fix
m_cn merges with remote m_cn
p1 merges with remote p1
p2 merges with remote p2
Local refs configured for 'git push':
fix pushes to fix (up to date)
m_cn pushes to m_cn (up to date)
p1 pushes to p1 (up to date)
p2 pushes to p2 (up to date)
比如你在本地仓库的 m_cn 分支上对文件做了一些修改,则可以这样推送到远程仓库:
PS > git add ./
PS > git commit -m "修改 README 文件的内容"
# 请注意!默认情况下不会推送标签相关的内容到远程仓库
PS > git push origin m_cn
# 假如还有相关的标签(轻量标签或附注标签)需要一次性推送到远程仓库
## 以轻量标签为例
PS > git tag new feef7d4
PS > git push origin m_cn --tags
# 删除远程仓库的标签
PS > git tag -d new
PS > git push origin m_cn -d :refs/tags/new
假如您直接在 Github 网页那边修改且更新了 m_cn 分支下的一些文件,要将远程仓库的文件变更取回本地,则可以这样操作:
# 这是一种简单的但不太安全的快捷方法
PS > git switch m_cn
PS > git pull origin m_cn
# 习惯上,我们需要先 fetch 抓取到本地,在比较了文件差异之后再 merge 合并,这种方式会更加安全
PS > git switch m_cn
PS > git fetch origin m_cn
PS > git merge origim/m_cn
为开源项目做贡献
Fork 项目之后,clone
到本地,做修改并推送到远程仓库。由于 Fork 之后的项目与上游的源项目存在一些内容变更的地方,我们可以在自己远程仓库的页面上点击 "contribute" 按钮并创建 PR ,在源项目的团队成员审核之后,您的 PR 可能会关闭,也可能合并到主分支或相关分支上。需要注意的是,绝大部分的开源项目都支持 PR 这种方式来做贡献,但有些开源项目并不支持这种方式的贡献,具体需要阅读开源项目的贡献说明。
- PR(Pull Request):Github 中一种通知机制,告诉源项目团队成员你做了哪些修改。
- MR(Merge Request):Gitlab 中一种通知机制,等同于 Github 中的 PR
Fork 项目之后,您需要跟随上游的提交记录的步伐,可以点击 "Sync fork" 按钮将当前分支的提交记录与上游的提交记录同步。如上图所示,我当前分支 m_cn 分支就落后于上游的提交记录(1 commit behind),需要进行同步。
Q:有时您做了贡献之后,您远程仓库的某一分支会出现提交记录既落后(behind)又超前(ahead)的情况,这是什么意思?
假设当时在你 Fork 时,上游 main 分支的提交记录处于 C1,而你是在 C1 这个提交记录之上创建了 PR(比如有 2 个 commit,C1-1 和 C1-2)。1 天之后,您的 PR 还在审核,但上游 main 分支的提交记录已经更新到了 C3,于是会出现既落后又超前的情况:
main: C1 -----------------------> C2 ---> C3
│
▼
m_cn: C1 ---> C1-1 ---> C1-2
- 落后 – 是指您当前远程仓库的某一分支的提交记录落后于源项目的提交记录
- 超前 – 因为您的 PR 还在审核当中,对于上游的源项目而言,这是超前的提交记录
若您的 PR 已经被人处理(关闭或合并),可以执行以下操作:
# 将这个特殊分支进行版本回退
PS > git switch <branch>
PS > git reset --hard <commit id>
# 强制推送到远程仓库
PS > git push -f <remote-name> <remote-branch>
接着将当前分支的提交记录与上游进行同步,即点击 "Sync fork" 按钮。
