# 远程仓库的使用

为了能在任意 Git 项目上协作,你需要知道如何管理自己的远程仓库。 远程仓库是指托管在因特网或其他网络中的你的项目的版本库。 你可以有好几个远程仓库,通常有些仓库对你只读,有些则可以读写。 与他人协作涉及管理远程仓库以及根据需要推送或拉取数据。 管理远程仓库包括了解如何添加远程仓库、移除无效的远程仓库、管理不同的远程分支并定义它们是否被跟踪等等。 在本节中,我们将介绍一部分远程管理的技能。

TIP

特别注意一个概念:大部分的配置都是针对你项目目录下的 ./git/config 文件进行操作,并不是根据字面意思上的在操作远程服务器上的资源

# 查看远程仓库 remote

如果想 查看你已经配置的远程仓库服务器,可以运行 git remote 命令。 它会列出你指定的每一个远程服务器的简写。 如果你已经克隆了自己的仓库,那么至少应该能看到 origin :这是 Git 给你克隆的 仓库服务器的默认名字

$ git clone https://github.com/schacon/ticgit
Cloning into 'ticgit'...
remote: Reusing existing pack: 1857, done.
remote: Total 1857 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1857/1857), 374.35 KiB | 268.00 KiB/s, done.
Resolving deltas: 100% (772/772), done.
Checking connectivity... done.
$ cd ticgit
$ git remote
origin
1
2
3
4
5
6
7
8
9
10

你也可以指定选项 -v,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。

$ git remote -v
origin	https://github.com/schacon/ticgit (fetch)
origin	https://github.com/schacon/ticgit (push)
1
2
3

如果你的远程仓库不止一个,该命令会将它们全部列出。 例如,与几个协作者合作的,拥有多个远程仓库的仓库看起来像下面这样:

$ cd grit
$ git remote -v
bakkdoor  https://github.com/bakkdoor/grit (fetch)
bakkdoor  https://github.com/bakkdoor/grit (push)
cho45     https://github.com/cho45/grit (fetch)
cho45     https://github.com/cho45/grit (push)
defunkt   https://github.com/defunkt/grit (fetch)
defunkt   https://github.com/defunkt/grit (push)
koke      git://github.com/koke/grit.git (fetch)
koke      git://github.com/koke/grit.git (push)
origin    git@github.com:mojombo/grit.git (fetch)
origin    git@github.com:mojombo/grit.git (push)
1
2
3
4
5
6
7
8
9
10
11
12

这样我们可以轻松拉取其中任何一个用户的贡献。 此外,我们大概还会有某些远程仓库的推送权限,虽然我们目前还不会在此介绍。

注意这些远程仓库使用了不同的协议;我们将会在 在服务器上搭建 Git 中了解关于它们的更多信息。

# 添加远程仓库 remote add

我在之前的章节中已经提到并展示了如何添加远程仓库的示例,不过这里将告诉你如何明确地做到这一点。 运行 git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个你可以轻松引用的简写:

$ git remote
origin
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote -v
origin	https://github.com/schacon/ticgit (fetch)
origin	https://github.com/schacon/ticgit (push)
pb	https://github.com/paulboone/ticgit (fetch)
pb	https://github.com/paulboone/ticgit (push)
1
2
3
4
5
6
7
8

现在你可以在命令行中使用字符串 pb 来 代替整个 URL。 例如,如果你想拉取 Paul 的仓库中有但你没有的信息,可以运行 git fetch pb:

$ git fetch pb
remote: Counting objects: 43, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 43 (delta 10), reused 31 (delta 5)
Unpacking objects: 100% (43/43), done.
From https://github.com/paulboone/ticgit
 * [new branch]      master     -> pb/master
 * [new branch]      ticgit     -> pb/ticgit
1
2
3
4
5
6
7
8

现在 Paul 的 master 分支可以在本地通过 pb/master 访问到 – 你可以将它合并到自己的某个分支中,或者如果你想要查看它的话,可以检出一个指向该点的本地分支。 (我们将会在 Git 分支 中详细介绍什么是分支以及如何使用分支。)

# 从远程仓库中抓取(pull)与拉取(fetch)

就如刚才所见,从远程仓库中获得数据,可以执行:

$ git fetch [remote-name]
1

这个命令会访问远程仓库,从中 拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。

如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。 所以,git fetch origin 会抓取克隆(或上一次抓取)后 新推送的所有工作。 必须注意 git fetch 命令会将数据拉取到你的本地仓库 – 它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。

如果你有一个分支设置为跟踪一个远程分支(阅读下一节与 Git 分支 了解更多信息),可以使用 git pull 命令来 自动的抓取然后合并远程分支到当前分支。 这对你来说可能是一个更简单或更舒服的工作流程;默认情况下,git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或不管是什么名字的默认分支)。 运行 git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。

# 推送到远程仓库(push)

当你想分享你的项目时,必须将其推送到上游。 这个命令很简单:

git push [remote-name] [branch-name]

# remote-name:远程服务器别名
# branch-name:推送到哪一个分支
1
2
3
4

当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字),那么运行这个命令就可以将你所做的备份到服务器:

$ git push origin master
1

只有当你有所克隆服务器的 写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送。 阅读 Git 分支 (opens new window) 了解如何推送到远程仓库服务器的详细信息。

# 查看远程仓库(remote show)

如果想要查看某一个远程仓库的更多信息,可以使用

git remote show [remote-name]
1

命令。 如果想以一个特定的缩写名运行这个命令,例如 origin,会得到像下面类似的信息:

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/schacon/ticgit
  Push  URL: https://github.com/schacon/ticgit
  HEAD branch: master
  Remote branches:
    master                               tracked
    dev-branch                           tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)
1
2
3
4
5
6
7
8
9
10
11
12

它同样会列出远程仓库的 URL 与跟踪分支的信息。 这些信息非常有用,它告诉你正处于 master 分支,并且如果运行 git pull,就会抓取所有的远程引用,然后将远程 master 分支合并到本地 master 分支。 它也会列出拉取到的所有远程引用。

这是一个经常遇到的简单例子。 如果你是 Git 的重度使用者(你的分支很多的话),那么还可以看到更多的信息。

$ git remote show origin
* remote origin
  URL: https://github.com/my-org/complex-project
  Fetch URL: https://github.com/my-org/complex-project
  Push  URL: https://github.com/my-org/complex-project
  HEAD branch: master
  Remote branches:
    master                           tracked
    dev-branch                       tracked
    markdown-strip                   tracked  # 这个应该
    issue-43                         new (next fetch will store in remotes/origin)
    issue-45                         new (next fetch will store in remotes/origin)
    refs/remotes/origin/issue-11     stale (use 'git remote prune' to remove)
  Local branches configured for 'git pull':  # 使用 pull 时本地分支与远程分支自动合并配置
    dev-branch merges with remote dev-branch
    master     merges with remote master
  Local refs configured for 'git push':   # 使用 push 时,本地分支与远程分支的引用
    dev-branch                     pushes to dev-branch                     (up to date)
    markdown-strip                 pushes to markdown-strip                 (up to date)
    master                         pushes to master                         (up to date)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

这个命令列出了当你在特定的分支上执行 git push 会自动地推送到哪一个远程分支。 它也同样地 列出了哪些远程分支不在你的本地哪些远程分支已经从服务器上移除了,还有当你执行 git pull 时哪些分支会自动合并。

# 远程仓库的移除与重命名(remote rename)

如果想要 重命名引用的名字 可以运行 git remote rename 去修改一个远程仓库的简写名。 例如,想要将 pb 重命名为 paul,可以用 git remote rename 这样做:

$ git remote rename pb paul
$ git remote
origin
paul
1
2
3
4

值得注意的是这 同样也会修改你的远程分支名字。 那些过去引用 pb/master 的现在会引用 paul/master。如果因为一些原因想要移除一个远程仓库 – 你已经从服务器上搬走了或不再想使用某一个特定的镜像了,又或者某一个贡献者不再贡献了 – 可以使用 git remote rm :

$ git remote rm paul
$ git remote
origin
1
2
3

# 迁移代码到新的服务器

当你想把一个仓库的代码完全迁移到新的 Git 服务器时,可以用如下的命令,完整的迁移(代码,分支,提交记录)

git clone --mirror <URL to my OLD repo location>
cd <New directory where your OLD repo was cloned>
git remote set-url origin <URL to my NEW repo location>
git push -f origin
1
2
3
4

这个原理也很好解读:

  1. 下载原始仓库
  2. 更改远程仓库地址到新的仓库地址
  3. 强制推送上去

附上一个小脚本

#!/bin/sh

export PROJECT=项目1.git
echo '正在处理 '${PROJECT}
git clone --mirror  git@旧仓库:组/${PROJECT}
cd ${PROJECT}
git remote set-url origin git@新仓库:组/${PROJECT}
git push -f origin
cd ../
1
2
3
4
5
6
7
8
9

另外当你项目很多的时候,要挨个的换掉本地项目的 git 地址(注意,手动更改配置文件是有问题的,需要使用命令更改地址),可以使用如下的小脚本

#!/bin/sh
# 这里的项目名不带 git,是因为默认 clone 下来的仓库所在目录是没有 git 后缀的
export PROJECT=项目1
echo '正在处理 '${PROJECT}
if [ ! -d "$PROJECT" ]; then
  echo 'file is not exist'
else
  cd ./${PROJECT}
  git remote set-url origin git@新仓库地址:组/${PROJECT}.git
  cd ../
fi
1
2
3
4
5
6
7
8
9
10
11