首先要明确一点,对 Git 的操作是围绕 3 个大的步骤来展开的(其实几乎所有的 SCM 都是这样)
- 从 git 取数据(
git clone
) - 改动代码
- 将改动传回 git(
git push
)
这 3 个步骤又涉及到两个 repository,一个是 remote repository,在远程服务器上,一个是 local repository,在自己工作区上。其中 1, 3 两个步骤涉及到 remote server/remote repository/remote branch,2 涉及到 local repository/local branch。git clone
会根据你指定的 remote server/repository/branch,拷贝一个副本到你本地,在 git push
之前,你对所有文件的改动都是在你自己本地的 local repository 来做的,你的改动 local branch 和 remote branch 是独立(并行)的。Gitk 显示的就是 local repository。
在 clone 完成之后,Git 会自动为你将此远程仓库命名为 origin(origin 只相当于一个别名,运行 git remote –v
或者查看 .git/config 可以看到 origin 的含义),并下载其中所有的数据,建立一个指向它的 master 分支的指针,我们用 (远程仓库名)/(分支名) 这样的形式表示远程分支,所以 origin/master 指向的是一个 remote branch(从那个 branch 我们 clone 数据到本地),但你无法在本地更改其数据。
同时,Git 会建立一个属于你自己的本地 master 分支,它指向的是你刚刚从 remote server 传到你本地的副本。随着你不断的改动文件,git add
, git commit
,master 的指向会自动移动,你也可以通过merge(fast forward)来移动 master 的指向。
查看所有分支:
$ git branch -a (to show all the branches git knows about) * master remotes/origin/HEAD -> origin/master remotes/origin/master
查看远程分支:
$ git branch -r (to show remote branches git knows about) origin/HEAD -> origin/master origin/master
可以发现,master 就是 local branch,origin/master 是 remote branch(master is a branch in the local repository. remotes/origin/master is a branch named master on the remote named origin)。
$ git diff origin/master master
=> show me the changes between the remote master branch and my master branch
需要注意的是,remotes/origin/master 和 origin/master 的指向是相同的,可以运行以下命令看效果:
$ git diff origin/master remotes/origin/master
$ git push origin master
origin 指定了你要 push 到哪个 remote。
master 其实是一个“refspec”,正常的“refspec”的形式为“+<src>:<dst>”,冒号前表示 local branch 的名字,冒号后表示 remote repository 下 branch 的名字。注意,如果你省略了<dst>,git就认为你想 push 到 remote repository 下和 local branch 相同名字的 branch。听起来有点拗口,再解释下,push 是怎么个 push 法,就是把本地 branch 指向的 commit push 到 remote repository 下的 branch,比如:
$ git push origin master:master
=> 在 local repository 中找到名字为 master 的 branch,使用它去更新 remote repository 下名字为 master 的 branch,如果 remote repository 下不存在名字是 master 的 branch,那么新建一个。
$ git push origin master
=> 省略了<dst>,等价于“git push origin master:master”。
$ git push origin master:refs/for/mybranch
=> 在 local repository 中找到名字为 master 的 branch,用它去更新 remote repository 下面名字为 mybranch 的 branch。
$ git push origin HEAD:refs/for/mybranch
=> HEAD 指向当前工作的 branch,master 不一定指向当前工作的 branch,所以我觉得用 HEAD 还比 master 好些。
$ git push origin :mybranch
=> 在 origin repository 里面查找 mybranch,删除它。用一个空的去更新它,就相当于删除了。