参考链接:https://blog.csdn.net/longintchar/article/details/84480862
本文想讨论 fetch 、merge 以及 push 命令的细节。
假设我们用命令添加了一个远程版本库:
$ git remote add origin [email protected]:schacon/simplegit-progit.git
上述命令会在 .git/config
文件中添加几行,并在其中指定远程版本库名称( origin
)、URL 和一个用于获取(fetch)操作的引用规格(refspec):
[remote "origin"]
url = [email protected]:schacon/simplegit-progit.git
fetch = +refs/heads/*:refs/remotes/origin/*
第1行:表示远程仓库的简称是 origin
;
第2行:指明远程仓库的 URL;
第3行:引用规格的格式由一个可选的 +
号和紧随其后的
组成。其中
是一个模式(pattern),代表远程版本库中的引用;
是远程版本库的引用在本地所对应的位置;+
号是可选的,告诉 Git 即使在不能快进的情况下也要(强制)更新引用。一般情况下都是加上+
号的,先把文件拉取到本地,不是Fast Forward
方式就手动合并;默认情况下,引用规格由 git remote add
命令自动生成, Git 会获取服务器中 refs/heads/
下面的 所有引用,并将它写入到本地的 refs/remotes/origin/
中。
如果运行 git fetch
命令,示意图如下(命令中的灰色部分是默认参数):
所以,如果服务器上有一个 master
分支,我们可以在本地通过下面这种方式来访问该分支上的提交记录:
$ git log origin/master
$ git log remotes/origin/master
$ git log refs/remotes/origin/master
上面的三个命令作用相同,因为 Git 会把它们都扩展成 refs/remotes/origin/master
。
如果想让 Git 每次只拉取远程的 master
分支,而不是所有分支,可以把上文引用规格的第 3 行修改为:
fetch = +refs/heads/master:refs/remotes/origin/master
这也是针对远程版本库 origin
的 git fetch
操作的 默认引用规格。
对于那些只执行一次的 fetch 操作,我们可以在命令行指定引用规格。 比如,只想将远程的 master
分支抓取到本地的 origin/master
分支,可以运行:
$ git fetch origin master:refs/remotes/origin/master
也可以在命令行中按照如下的方式抓取多个分支:
$ git fetch origin master:refs/remotes/origin/master \
topic:refs/remotes/origin/topic
From [email protected]:schacon/simplegit
! [rejected] master -> origin/master (non fast forward)
* [new branch] topic -> origin/topic
在这个例子中,对 master
分支的抓取操作被拒绝,因为它不是一个可快进的引用。 可以在引用规格之前指定 +
号来强制抓取。例如:
$ git fetch origin +master:refs/remotes/origin/master \
topic:refs/remotes/origin/topic
上面的命令表示,对于远程仓库的 master 分支,会强制抓取到本地,但是对于 topic 分支仅允许快进式抓取。
你也可以在配置文件中指定多个用于 fetch 操作的引用规格refspec。 如果想在每次抓取时都包括 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/config
文件中可以看到跟踪的远程分支:
[branch "master"]
remote = origin
merge = refs/heads/master #这里指远端服务器上的refs/heads/master
merge是由所在branch定义的,[branch “master”]的配置指定当前master
分支的merge策略是使用 服务器端的refs/heads/master
来合并到当前分支。这样就可以顺利的git pull origin
了。
当前已有跟踪分支,开始推送代码
$ git push origin
上面过程的本质是提交当前分支头指针到origin,相当于拷贝本地refs/head/xxx
到远程引用refs/remotes/master/
下并提交。git push origin
会被展开成git push origin
$ git push origin master
$ git push origin master:master
$ git push origin master:refs/heads/master
$ git push origin refs/heads/master:refs/heads/master
上面的命令作用相同,因为 Git 会把它们都扩展成 refs/heads/master
。
注意,区分本地的 refs/heads/master
和远程仓库的 refs/heads/master
拓展
refs/remotes/xxx/
)refs/remotes/xxx
->refs/heads
)refs/heads
)refs/remotes/xxx
)refs/heads/
下的一个头指针refs/remotes/xxx
)refs/remotes/
下的指针拷贝到了refs/heads
下