作者:jicanmeng
时间:2014年08月29日
Git的远程操作命令大概有这么几个:
git clone
命令用于把远程版本库(remote repository)克隆一份到本地,克隆的这一份版本库就称为本地版本库(local repository)。比如,要克隆Ruby语言的Git代码仓库Grit,可以用下面的命令:
[jicanmeng@andy tmp]$ git clone git://github.com/schacon/grit.git
Cloning into 'grit'...
remote: Counting objects: 4051, done.
remote: Compressing objects: 100% (2824/2824), done.
remote: Total 4051 (delta 1170), reused 4051 (delta 1170)Receiving objects: 99%
(4029/4051), 2.10 MiB |
Receiving objects: 100% (4051/4051), 2.10 MiB | 17 KiB/s, done.
Resolving deltas: 100% (1170/1170), done.
Checking out files: 100% (1384/1384), done.
这条命令会在当前目录下创建一个名为grit的目录,其中包含一个.git的目录,用于保存下载下来的所有版本记录,然后从中取出最新版本的文件拷贝,放到工作区。如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:
[jicanmeng@andy tmp]$ git clone git://github.com/schacon/grit.git mygrit
唯一的差别就是,现在新建的目录成了 mygrit,其他的都和上边的一样。
为了便于管理,Git要求每个远程版本库都必须指定一个名称。git remote
命令就用于查看和配置远程版本库的名称。
git remote
命令列出所有的远程版本库的名称;
git remote -v
命令会列出远程版本库的名称和对应的URL;
git remote show
命令用于列出远程版本库的详细信息。
[jicanmeng@andy tmp]$ git remote
origin
[jicanmeng@andy tmp]$ git remote -v
origin git://github.com/schacon/grit.git (fetch)
origin git://github.com/schacon/grit.git (push)
[jicanmeng@andy tmp]$ git remote show origin
* remote origin
Fetch URL: git://github.com/schacon/grit.git
Push URL: git://github.com/schacon/grit.git
HEAD branch: master
Remote branches:
gh-pages tracked
integration tracked
master 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)
我们在使用git clone
命令克隆版本库的时候,所使用的远程版本库默认情况下会被Git命名为origin。如果想用其他的名称,需要用git clone
命令的-o选项指定。
[jicanmeng@andy tmp]$ git clone -o gritProject git://github.com/schacon/grit.git
[jicanmeng@andy tmp]$ git remote
gritProject
[jicanmeng@andy tmp]$
git remote add NameOne git://github.com/schacon/grit.git
命令用于添加一个URL为git://github.com/schacon/grit.git的远程版本库,名称为NameOne。
git remote rm NameOne
命令用于删除名称为NameOne的远程版本库。
git remote rename NameOne NameTwo
用于将名称为NaneOne的远程版本库的名称修改为NameTwo。
git remote
命令所进行的操作实际上是对.git/config文件进行读和写。我们可以看一看.git/config文件的内容:
[jicanmeng@andy grit]$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "origin"]
url = git://github.com/schacon/grit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[jicanmeng@andy grit]$ git config remote.origin.url
git://github.com/schacon/grit.git
[jicanmeng@andy grit]$ git config branch.master.remote
origin
[jicanmeng@andy grit]$
可以看到,当前的配置文件中保存了一个远程版本库的名称:origin。我们使用git config命令可以查看名称为origin的远程版本库的URL。如果使用git remote add
命令,就会增加一个remote小节。如果使用git remote rm
命令,就会删除对应的remote小节。
git push
命令用于将本地版本库的更新,推送到远程版本库。这条命令的格式如下:
[jicanmeng@andy grit]$ git push [<远程版本库名称> [<本地分支名称>:<远程分支名称>]]
"[]"表示可选,即我们可以执行git push
,可以执行git push <远程版本库>
,可以执行git push <远程版本库名称> <本地分支名称>:<本地分支名称>
,但不能执行git push <本地分支名称:远程分支名称>
.
如果省略了远程版本库名称,分两种情况:1. 如果为当前分支设置了<remote>,即在.git/config文件中由branch.<branch>.remote给出了远程版本库的名称,那么不带参数执行git push
就相当于执行了git push <remote>
; 2. 如果没有为当前分支设置<remote>,那么不带参数执行git push
就相当于执行git push origin
。要推送的远程版本库的URL地址由remote.<remote>.pushurl给出,如果没有这一项配置,那么就使用remote.<remote>.url给出的地址;
如果命令中包含了远程版本库名称,分下面三种情况:
1. 如果省略了本地分支名和远程分支名,分两种情况:1. 如果为注册的远程版本库设置了push参数,即通过remote.<remote>.push配置了一个引用表达式,那么使用该引用表达式进行推送。2. 如果没有设置push参数,那么就使用":"作为引用表达式。该表达式的含义是同名分支推送,即对所有在远程版本库中有同名分支的本地分支执行推送。
2. 如果只省略远程分支名,则表示将本地分支推送到同名的远程分支,如果该远程分支不存在,则会被新建。例如:git push origin master
命令表示,将本地的master分支推送到名称为origin远程版本库的master分支。如果后者不存在,则会被新建。
3. 如果只省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。例如:git push origin :master
命令等同于git push origin --delete master
这条命令,表示删除名称为origin的远程版本库的master分支。
[jicanmeng@andy grit]$ git fetch [<远程版本库名称> [<远程分支名称>:<本地跟踪分支>]]
"[]"表示可选,即我们可以执行git fetch
,也可以执行git fetch <远程版本库名称>
,也可以执行git fetch <远程版本库名称> <远程分支名>
,但不能执行git fetch <远程分支名称>
.
如果省略了远程版本库名称,分两种情况:1. 如果为当前分支设置了<remote>,即在.git/config文件中由branch.<branch>.remote给出了远程版本库的名称,那么不带参数执行git fetch
就相当于执行了git fetch <remote>
; 2. 如果没有为当前分支设置<remote>,那么不带参数执行git fetch
就相当于执行git fetch origin
。远程版本库的URL地址由remote.<remote>.url给出。
如果命令中包含了远程版本库名称,分下面两种情况:
1. 如果省略了远程分支名和本地跟踪分支名,分两种情况:1. 如果为注册的远程版本库设置了fetch参数,即通过remote.<remote>.fetch配置了一个引用表达式,则使用该引用表达式执行获取操作;2. 如果没有配置fetch参数,那么git fetch
取回所有分支(branch)的更新。
2. 如果指定远程分支名,那么应该同时指定本地跟踪分支名,此时只取回这个远程分支的更新。
$ git fetch origin master:refs/remote/origin/master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From C:/Program Files/Git/path/to/repos/user5
* [new branch] master -> origin/master
$
可以使用三幅图来形象地说明一下git fetch
命令的作用:
1. 我的本地版本库和远程版本库保持一致,有两个分支:master和branch01。两个本地跟踪分支分别是refs/remotes/origin/master和refs/remote/origin/branch01。
2. 有其他人往远程版本库上面进行了新的提交,其中master提交两次,branch01分支提交一次。同时我的本地版本库上面master分支上面有一次新的提交。
3. 执行git fetch
命令后,从远程版本库获取了master分支的两次commit和branch01分支的一次commit。然后两个本地跟踪分支分别指向对应的最新的commit。至于本地分支master和branch01的指向都不改变。
从图中可以看出,git fetch
命令只有两个作用:1. 将远程版本库的最新的commit获取到本地版本库;2. 将本地跟踪分支的指向进行修改。
[jicanmeng@andy grit]$ git pull [<远程版本库名称> [<远程分支名称>:<本地分支>]]
实际上拉回操作(git pull)是由两个步骤组成的:一个是获取操作(git fetch),另一个是合并操作(git merge),即
git pull
= git fetch
+ git merge
前面已经详细描述了git fetch
命令,这里只需要再理解git merge
命令的意思就行了。接着上面的图,如果我们在master分支上面执行git merge origin/master
命令,那么结果如下图:
由上图可以看出,在master分支下执行git merge origin/master
,会将master分支指向的提交和origin/master指向的提交进行合并,生成一个新的提交。
工作中常遇到的一个问题是:git push
命令不能执行成功,执行git pull
也会提示冲突。所以一定要学会这两条命令的用法。