-
1. 起步
-
2. Git 基础
-
3. Git 分支
-
4. 服务器上的 Git
- 4.1 协议
- 4.2 在服务器上部署 Git
- 4.3 生成 SSH 公钥
- 4.4 架设服务器
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方托管服务
- 4.10 小结
-
5. 分布式 Git
-
A1. 附录 A: Git 在其他环境
- A1.1 图形界面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 小结
-
A2. 附录 B: 在应用程序中嵌入 Git
-
A3. 附录 C: Git 命令
10.5 Git 内部原理 - Refspec
Refspec
在本书中,我们使用了远程分支到本地引用的简单映射,但它们可以更复杂。假设你正在跟随前面的章节,并且已经创建了一个小的本地 Git 仓库,现在想给它添加一个*远程*仓库。
$ git remote add origin https://github.com/schacon/simplegit-progit
运行上面的命令会在你的仓库的 .git/config 文件中添加一个部分,指定远程仓库的名称(origin)、远程仓库的 URL 以及用于获取的 *refspec*。
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/*
Refspec 的格式是,首先是一个可选的 +,然后是 <src>:<dst>,其中 <src> 是远程端的引用模式,<dst> 是这些引用将在本地进行跟踪的位置。+ 告诉 Git 即使引用不是快进(fast-forward)的,也要更新该引用。
在 git remote add origin 命令自动写入的默认情况下,Git 会从服务器上的 refs/heads/ 下获取所有引用,并将它们写入本地的 refs/remotes/origin/。因此,如果服务器上有一个 master 分支,你可以通过以下任何一种方式在本地访问该分支的日志:
$ git log origin/master
$ git log remotes/origin/master
$ git log refs/remotes/origin/master
它们都是等效的,因为 Git 会将它们都展开为 refs/remotes/origin/master。
如果你希望 Git 每次只拉取 master 分支,而不是远程服务器上的其他所有分支,你可以将 fetch 行更改为仅引用该分支:
fetch = +refs/heads/master:refs/remotes/origin/master
这只是该远程仓库的 git fetch 的默认 refspec。如果你想只进行一次性 fetch,也可以在命令行上指定特定的 refspec。要将远程的 master 分支拉取到本地的 origin/mymaster,你可以运行:
$ git fetch origin master:refs/remotes/origin/mymaster
你也可以指定多个 refspecs。在命令行上,你可以像这样拉取多个分支:
$ git fetch origin master:refs/remotes/origin/mymaster \
topic:refs/remotes/origin/topic
From git@github.com:schacon/simplegit
! [rejected] master -> origin/mymaster (non fast forward)
* [new branch] topic -> origin/topic
在这种情况下,master 分支的拉取被拒绝了,因为它未被列为快进引用。你可以通过在 refspec 前指定 + 来覆盖它。
你也可以在配置文件中为 fetch 指定多个 refspecs。如果你想始终从 origin 远程仓库获取 master 和 experiment 分支,请添加两条行:
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/experiment:refs/remotes/origin/experiment
自 Git 2.6.0 起,你可以在模式中使用部分 glob 来匹配多个分支,因此这很有效:
fetch = +refs/heads/qa*:refs/remotes/origin/qa*
更好的是,你可以使用命名空间(或目录)来实现相同的功能,并提供更多结构。如果你有一个 QA 团队推送了一系列分支,并且你只想获取 master 分支和 QA 团队的任何分支,但不获取其他任何分支,你可以使用如下的配置部分:
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*
如果你有一个复杂的流程,其中有一个 QA 团队推送分支,开发人员推送分支,集成团队推送并协作远程分支,你可以通过这种方式轻松地为它们添加命名空间。
推送 Refspecs
通过这种方式获取命名空间引用很方便,但 QA 团队如何才能将他们的分支推送到 *qa/* 命名空间中呢?你通过使用 refspecs 来推送实现这一点。
如果 QA 团队想将他们的 master 分支推送到远程服务器上的 qa/master,他们可以运行:
$ git push origin master:refs/heads/qa/master
如果他们希望 Git 在每次运行 git push origin 时自动执行此操作,他们可以在配置文件中添加一个 push 值:
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/heads/qa/master
同样,这会默认导致 git push origin 将本地的 master 分支推送到远程的 qa/master 分支。
|
注意
|
你不能使用 refspec 从一个仓库获取并推送到另一个仓库。有关如何执行此操作的示例,请参阅 保持你的 GitHub 公共仓库最新。 |
删除引用
你也可以使用 refspec 通过运行类似以下命令来从远程服务器删除引用:
$ git push origin :topic
因为 refspec 是 <src>:<dst>,通过省略 <src> 部分,这基本上表示将远程的 topic 分支置为空,从而将其删除。
或者,你可以使用较新的语法(自 Git v1.7.0 起可用):
$ git push origin --delete topic