试图在git上获得真正的处理:)git是否会进行存储库扩展操作?这意味着,它是否会更新存储库中的本地分支(跟踪远程分支),还是只为当前签出的分支进行获取和合并?
推送是否同样如此?什么 - 所有做推拉操作?
任何帮助都会摇滚!
另外,fetch做了什么?它是否获取特定分支的信息(.git文件夹中的文件)?或者.git文件夹在整个仓库中是否一致?如果我取而不是克隆,那么之后我就无法做任何事情了,取出后该怎么办?
答案 0 :(得分:2)
git pull
只是git fetch
和git merge
的组合。
git fetch
将更新所有远程分支,git merge
将通过合并相应的远程分支来更新当前分支。
普通git push
的确切行为取决于git config push.default
的输出。
最近的git版本将其设置为simple
,它只会推送当前分支。
有关命令行选项的确切含义,请使用git help push
和git help pull
。
git clone
只是git init
,git remote add
,git fetch
和git checkout
的组合。
您的.git
文件夹 是您的本地存储库,其中包含所有文件的完整历史记录。 .git
文件夹外的文件是您的“工作树”。更改文件需要工作树,但git log
等大多数其他git命令不需要。
答案 1 :(得分:1)
答案是"两者都没有",真的。或者"它取决于"。或类似的东西!
首先,需要考虑两个基本操作:fetch
和push
。 (pull
操作只是构建在fetch
之上的shell脚本,因此一旦您知道 如何工作,我们就可以正确解释pull
。)< / p>
fetch
和push
都有访问到整个存储库。但一般来说,它们不能通过线路(或其他通信信道)发送整个存储库。它们基于引用工作。
fetch和push操作通常采用&#34; refspecs&#34 ;,它们是引用对(远程:本地和本地:远程分别)和一个可选的&#34; force&#34;标志前缀+
。但是,它们只能给出一个简单的引用,并且可以使用-f
或--force
指定强制标记。
这两个命令已经存在了很长时间,并积累了许多旧的东西&#34;。 &#34;现代&#34;使用远程存储库的方法是通过名为&#34; remote&#34;的东西,使用git remote add
来创建它们(并且git clone
默认创建一个名为origin
的东西。这些变成了.git/config
文件中的条目:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = ssh://...
url =
行提供了抓取和推送的网址,但如果需要,可以添加额外的pushurl =
行,以便推送到其他位置。 (有#34;老方法&#34;直接运行提取和推送并提供URL,等等,但是让我们忽略所有这些......遥控器要好得多!)这也提供了refspecs -well,一个refspec,在这种情况下为git fetch
。
完成后,让我们完全从另一个命令git ls-remote
开始。这类似于fetch
,但实际上没有取任何东西:
$ git ls-remote origin
676699a0e0cdfd97521f3524c763222f1c30a094 HEAD
222c4dd303570d096f0346c3cd1dff6ea2c84f83 refs/heads/branch
676699a0e0cdfd97521f3524c763222f1c30a094 refs/heads/master
d41117433d7b4431a188c0eddec878646bf399c3 refs/tags/tag-foo
这告诉我们名为origin
的远程名称有三个引用名称。两个是分支,一个是标签。 (特殊HEAD
ref与refs/heads/master
具有相同的SHA-1,因此git会猜测远程在分支master
上的#34;&#34;为{{1}可能会说。远程协议中存在各种错误:git应该能够说&#34; git status
是一个符号引用,指向HEAD
&#34;,所以您的结果不必猜测。这将解决两个分支具有与refs/heads/master
相同的SHA-1的情况。)
当您运行HEAD
时,获取操作会以相同的git fetch origin
开始,或多或少,从而查看所有分支和标记。如果你使用ls-remote
它也会带来所有标签,否则它会带来相当复杂的 1 带来所有分支和一些标签。它也会看到所有其他引用,但默认情况下,它不会带来那些:例如,远程可能有--tags
,refs/notes/commits
使用它,但是那个人没有过来。
但是,当你改变赋予git notes
的refspec时,你会改变被带来的东西。默认值是git fetch
,.git/config
中的默认值。这个refspec说要将所有fetch = +refs/heads/*:refs/remotes/origin/*
个引用 - 所有分支 - 带到本地,并使用与远程分支名称相同的名称将它们存储在refs/heads/*
下。使用refs/remotes/origin/
会添加一个额外的refspec:--tags
。这就是git如何带来所有标签:匹配refs/tags/*:refs/tags/*
的所有标签,都是匹配名称下的本地refs/tags/*
。
(您可以添加更多refs/tags/
行并带来更多内容。有关示例,请参阅this answer&#34;远程标记&#34;。
现在,只要引用引用名称就不会有好处,除非git还带来任何必需的底层对象, 2 由他们的SHA-1识别。我们假设您已经fetch =
,但不是676699a...
。 (您在222c4dd...
上更新了最新信息,但master
上没有更新。也许您甚至还没有拥有分支branch
。)获取操作需要确保带来该提交。该提交可能需要各种文件和先前的提交,等等。所以你的branch
与遥控器上正在查看另一个git存储库的东西进行通信,并且他们进行了一些对话,每个人都告诉对方他们现在拥有什么样的SHA-1,以及哪些是他们仍然需要。如果您需要git fetch
,则会询问另一端&#34;我还需要使用 222c4dd...
&#34;,检查是否有那些,如果没有,将它们添加到列表中,一旦添加就更详细地检查它们,等等。
最终同意交换什么,他们的git会向你发送对象 - 通常是在&#34;薄包&#34;如果可能(详细信息取决于传输) - 并且您的git根据需要解压缩和/或重新打包它们,然后更新您的本地引用以获取任何新分支,标记或其他引用。 (默认情况下,你的git只是将他们的分支存储在你的&#34;远程分支&#34; - 你的副本#34;他们最后一次与他们交谈的内容&#34; - 但是更新你的< / em>标签。也就是说,没有&#34;远程标签&#34;,只是&#34;远程分支&#34;。)
作为一种特殊情况,如果你给222c4dd...
超出遥控器名称的任何参数 - 如:
git fetch
例如 - 这些 refspecs覆盖配置文件中的那些和(在1.8.4之前的git版本中)阻止更新&#34;远程分支&#34 ;。这通常会限制所取得的东西,有时甚至是相当多的。 (在1.8.4及更高版本中,它们仍限制获取,但远程分支无论如何都会更新,这更有意义。)这里,一个缺少冒号的refspec - 就像上面的那个 - 是不是< / em>被视为两面都有相同的名称。相反,&#34;他们的&#34;像往常一样收集分支,但SHA-1和分支名称写入git fetch origin master
。
(这是有充分理由的:如果.git/FETCH_HEAD
更新了git fetch origin master
,您将丢失所有新提交的内容!所以您希望它仅更新master
和/或origin/master
。)
FETCH_HEAD
操作与push
非常相似。但它并不是完全对称的:你不会推到一个远程分支机构,一般情况下,你只需要向右推进一个分支机构&#34;。例如,在推送您的分支fetch
时,您的本地引用为master
,其本地引用也是 refs/heads/master
。它肯定不是refs/heads/master
。所以用于推送的refspec通常要简单得多。
如果您只是运行refs/remotes/yoursystem/master
(或git push
),那么仍然需要提供一些refspec(s)。
git配置文件git push origin
中有一个(某种新的)控制旋钮,允许您配置git推送的引用。在当前版本的git中,默认为push.default
。在git 2.0中,它将被更改为matching
。总共有五种设置:
simple
:产生错误nothing
:将您所在的分支推到同一个名称current
:将您所在的分支推送到其上游名称upstream
:与上游类似,但要求上游名称与本地名称匹配simple
:推送所有具有相同名称的分支其中一些需要进一步解释。 &#34;上游名称&#34;是另一端的分支名称。假设您有一个名为matching
的远程分支,并为此创建了一个本地跟踪分支,但称之为origin/feature
,因为您已经在处理另一个feature2
分支(尚未在feature
上创建)。因此,您的本地origin
上游有feature2
(而您的remote/origin
根本没有上游)。推送到feature
将跟随映射,并将upstream
推送到feature2
。推送feature
将拒绝该尝试。
因此,如果你simple
没有refspec,git会查找默认配置 3 并根据它构建refspec。对于git push
案例,它会推送您和他们都拥有的每个分支(因此,如果您同时拥有matching
和master
,请将branch
推送到master
和你的master
到branch
),但是只有你们中的一个人没有对分支做任何事情。
如果你给出一些明确的refspec,那么所有这些都没有实际意义:push操作会推送你给它的refspec。此外,没有冒号的refspec意味着&#34;在两端使用相同的名称&#34;,因此branch
是编写完整长版本master
的简便方法。
与fetch一样,你的git和他们的git进行通信,以确定需要发送哪些存储库对象(如果有的话)来完成推送。
refs/heads/master:refs/heads/master
操作运行git pull
的四字形式。
它的第一步是找出使用什么遥控器。如果你说出一个名字:
git fetch
它取你给它的名字;否则,它会查看您所在的分支(让我们说git pull origin master
),然后查看master
以查找.git/config
(可能是branch.master.remote
)。
然后,它计算出要使用的分支。如果你命名一个,它会使用它;否则,它使用origin
,这是另一端的分支的名称(通常只是branch.master.merge
)。然后它使用这些参数运行master
。
这意味着获取只会带来有趣的&#34;分支,在本例中为git fetch
,并将SHA-1放在master
中。 (如果你有git 1.8.4或更新版本,它也会更新FETCH_HEAD
。)
最后,origin/master
运行pull
或merge
,这取决于配置条目以及是否使用rebase
运行它。您将合并或重新绑定的提交是其SHA-1现在存储在--rebase
中的提交。
请注意,这只会合并或重新绑定您当前的分支。
1 如手册中所述,fetch默认为&#34;标记&#34;技巧:它查看标签中的SHA-1,并查看它们是否存在于您的存储库中。对于那些曾经或将要成为的人来说,它会带来那个标签。您可以使用FETCH_HEAD
关闭此功能。
2 对象是存储库实际存储的东西:&#34; blobs&#34; (文件),树(充满文件或更多目录的目录),提交和&#34;带注释的标签&#34;。每个都有一个唯一的SHA-1名称。
3 但是,您可以使用每个分支配置--no-tags
和branch.name.pushremote
覆盖此设置。通过转动许多配置旋钮,你可以制作出难以理解的大量效果。