-
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 命令
3.5 Git 分支 - 远程分支
远程分支
远程引用是指你的远程仓库中的引用(指针),包括分支、标签等等。你可以通过 git ls-remote <remote> 命令明确地获取远程引用的完整列表,或者使用 git remote show <remote> 来查看远程分支以及更多信息。尽管如此,更常见的方式是利用远程跟踪分支。
远程跟踪分支是对远程分支状态的引用。它们是本地引用,你无法移动它们;当你进行任何网络通信时,Git 会为你移动它们,以确保它们准确地反映远程仓库的状态。你可以将它们视为书签,用于提醒你在上次连接远程仓库时,远程仓库中的分支所在的位置。
远程跟踪分支的命名格式为 <remote>/<branch>。例如,如果你想查看 origin 远程上的 master 分支在你上次与它通信时的状态,你应该查看 origin/master 分支。如果你正在与伙伴合作处理某个问题,他们推送了一个 iss53 分支,你可能有一个本地的 iss53 分支,但服务器上的分支将由远程跟踪分支 origin/iss53 来表示。
这可能会有点令人困惑,所以让我们看一个例子。假设你在网络上有一个 Git 服务器,地址是 git.ourcompany.com。如果你从这里克隆,Git 的 clone 命令会自动将它命名为 origin,下载所有数据,创建一个指向其 master 分支的本地指针,并将其命名为 origin/master。Git 还会创建一个与 origin 的 master 分支相同的本地 master 分支,这样你就有了可以开始工作的内容。
|
注意
|
“origin” 并非特殊
就像 Git 中“master”分支名没有特殊含义一样,“origin”也没有。虽然“master”是运行 |
如果你在本地的 master 分支上进行了一些工作,而与此同时,其他人推送到了 git.ourcompany.com 并更新了它的 master 分支,那么你的提交历史就会向前发展得不一样。另外,只要你与 origin 服务器没有通信,你的 origin/master 指针就不会移动。
要同步你与某个远程仓库的工作,你需要运行 git fetch <remote> 命令(在我们的例子中是 git fetch origin)。这个命令会查找“origin”是哪个服务器(在这个例子中是 git.ourcompany.com),从它那里获取你还没有的数据,并更新你的本地数据库,将你的 origin/master 指针移动到它新的、更更新的位置。
git fetch 更新你的远程跟踪分支为了演示拥有多个远程服务器以及这些远程项目的远程分支是什么样的,让我们假设你还有一个内部 Git 服务器,它只供一个冲刺团队用于开发。这个服务器的地址是 git.team1.ourcompany.com。你可以通过运行 git remote add 命令将其添加为当前项目中新的远程引用,这在我们之前 Git 基础 中已经讲过了。将此远程命名为 teamone,这将是该完整 URL 的简写名称。
现在,你可以运行 git fetch teamone 来获取 teamone 远程服务器上所有你还没有的内容。因为该服务器目前拥有的数据是你的 origin 服务器数据的一个子集,Git 不会获取任何数据,但会设置一个名为 teamone/master 的远程跟踪分支,指向 teamone 的 master 分支提交。
teamone/master 的远程跟踪分支推送
当你想要与他人共享一个分支时,你需要将其推送到你有写入权限的远程仓库。你的本地分支不会自动同步到你写入的远程仓库——你必须显式地推送你想要共享的分支。这样,你就可以使用私有分支进行不希望共享的工作,只推送你想要协作的话题分支。
如果你有一个名为 serverfix 的分支,你想与他人一起工作,你可以以推送第一个分支的方式推送它。运行 git push <remote> <branch>
$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
* [new branch] serverfix -> serverfix
这是一种快捷方式。Git 会自动将 serverfix 分支名展开为 refs/heads/serverfix:refs/heads/serverfix,意思是“将我的 serverfix 本地分支推送到远程并更新远程的 serverfix 分支”。我们将在 Git 内部原理 中详细介绍 refs/heads/ 部分,但通常你可以省略它。你也可以执行 git push origin serverfix:serverfix,这会做同样的事情——它表示“将我的 serverfix 推送到远程并使其成为远程的 serverfix”。你可以使用此格式将本地分支推送到命名不同的远程分支。如果你不希望它在远程被命名为 serverfix,你可以改为运行 git push origin serverfix:awesomebranch,将你的本地 serverfix 分支推送到远程项目中的 awesomebranch 分支。
|
注意
|
不要每次都输入密码
如果你使用 HTTPS URL 进行推送,Git 服务器会要求你输入用户名和密码进行身份验证。默认情况下,它会在终端提示你输入这些信息,以便服务器可以判断你是否有权限推送。 如果你不想每次推送时都输入密码,可以设置一个“凭据缓存”。最简单的方法是将其保存在内存中几分钟,你可以通过运行 有关各种可用凭据缓存选项的更多信息,请参阅 凭据存储。 |
下一次你的协作者从服务器拉取时,他们将在远程分支 origin/serverfix 下获得指向服务器 serverfix 版本位置的引用。
$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
* [new branch] serverfix -> origin/serverfix
需要注意的是,当你执行一个获取(fetch)操作并下载了新的远程跟踪分支时,你并不会自动获得可编辑的本地副本。换句话说,在这种情况下,你并没有一个新的 serverfix 分支——你只有一个无法修改的 origin/serverfix 指针。
要将此工作合并到你当前的工作分支,你可以运行 git merge origin/serverfix。如果你想拥有自己的 serverfix 分支以便进行工作,你可以基于你的远程跟踪分支来创建它
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
这会创建一个本地分支,你可以对其进行工作,它从 origin/serverfix 的位置开始。
跟踪分支
从远程跟踪分支检出一个本地分支会自动创建一个所谓的“跟踪分支”(而它跟踪的分支称为“上游分支”)。跟踪分支是与远程分支有直接关系的本地分支。如果你在跟踪分支上并键入 git pull,Git 会自动知道从哪个服务器拉取以及合并哪个分支。
当你克隆一个仓库时,通常会自动创建一个 master 分支来跟踪 origin/master。但是,如果你愿意,你也可以设置其他跟踪分支——跟踪其他远程仓库上的分支,或者不跟踪 master 分支。最简单的情况就是你刚才看到的例子,运行 git checkout -b <branch> <remote>/<branch>。这是一个足够常见的操作,以至于 Git 提供了 --track 简写。
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
事实上,这已经非常普遍了,甚至还有一个针对这个简写的简写。如果你的目标检出(checkout)的分支名(a)不存在,并且(b)只在一个远程仓库中与一个分支名完全匹配,Git 会为你创建一个跟踪分支。
$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
要设置一个与远程分支名称不同的本地分支,你可以轻松地使用第一个版本,并指定不同的本地分支名称。
$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'
现在,你的本地分支 sf 将会自动从 origin/serverfix 拉取。
如果你已经有一个本地分支,并希望将其设置为你刚刚拉下来的某个远程分支,或者想更改你要跟踪的上游分支,你可以随时使用 git branch 的 -u 或 --set-upstream-to 选项来显式设置。
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
|
注意
|
上游简写
当你设置了一个跟踪分支后,你可以使用 |
如果你想查看你设置了哪些跟踪分支,可以使用 git branch -vv 选项。这将列出你的本地分支以及更多信息,包括每个分支正在跟踪什么,以及你的本地分支是超前、落后还是两者兼有。
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] Add forgotten brackets
master 1ae2a45 [origin/master] Deploy index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it
testing 5ea463a Try something new
所以在这里我们可以看到,我们的 iss53 分支正在跟踪 origin/iss53,并且“超前”了两次,这意味着我们本地有两个提交尚未推送到服务器。我们还可以看到,我们的 master 分支正在跟踪 origin/master,并且是最新的。接下来,我们看到我们的 serverfix 分支正在跟踪我们 teamone 服务器上的 server-fix-good 分支,并且超前了三次,落后了一次,这意味着服务器上有一个我们尚未合并的提交,以及三个我们尚未推送的本地提交。最后,我们可以看到我们的 testing 分支没有跟踪任何远程分支。
需要注意的是,这些数字仅表示自上次你从每个服务器获取以来(的状态)。此命令不会连接到服务器,它告诉你的是本地缓存的这些服务器的信息。如果你想获得完全最新的超前和落后数字,你需要在运行此命令之前从所有远程仓库进行获取。你可以这样做:
$ git fetch --all; git branch -vv
拉取
虽然 git fetch 命令会获取服务器上所有你还没有的更改,但它不会修改你的工作目录。它只会获取数据,让你自己进行合并。但是,有一个名为 git pull 的命令,在大多数情况下,它实际上是 git fetch 后面紧接着一个 git merge。如果你设置了一个跟踪分支(如上一节所示),无论是通过显式设置还是通过 clone 或 checkout 命令为你创建的,git pull 都会查找你当前分支正在跟踪的服务器和分支,从该服务器获取,然后尝试合并该远程分支。
删除远程分支
假设你已经完成了某个远程分支的工作——比如你和你的协作者已经完成了某个功能,并将其合并到了你远程仓库的 master 分支(或者你稳定代码行的任何分支)。你可以使用 git push 的 --delete 选项来删除远程分支。如果你想从服务器上删除你的 serverfix 分支,可以运行以下命令:
$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
- [deleted] serverfix
基本上,这只是从服务器上移除了指针。Git 服务器通常会暂时保留这些数据,直到垃圾回收运行,所以如果它被意外删除,通常很容易恢复。