我使用并喜欢GIT,但我正在努力理解它。
我有点卡在遥控器上,跟踪等等。
我回到主要,我做
git fetch ../second
-> * branch HEAD -> FETCH_HEAD
换句话说,我正在寻找对其克隆一无所知的原始回购。
使用gitk --all,似乎没有添加任何东西。
我的问题:
答案 0 :(得分:2)
注意:使用明确的"远程"是这些日子的方式(见下文为什么)。直接命名URL是一种非常古老(并且已经过时)的方法。
如果您要运行gitk --all FETCH_HEAD
,您会看到不同的内容(尝试并查看)。原因是--all
仅列出refs/
中的所有引用(见下文)。
具体而言,遥控器是git配置文件中的一个条目(通常在repo本身内.git/config
)。或者更确切地说,是remote.name
:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = ssh://some.host.name/path/to/repo.git
或类似的。这一点是记录一些常见项目,这样你就不必一直重复它们。特别是,在此之后不必拼写url(和可选的push-url)。 fetch =
行也很重要,如下所述。 ("镜像"与#34;常规"存储库不同。)
git fetch
如果您执行git fetch ../second
,如上所示,您直接命名存储库,而不是"远程"。因此,您不需要remote "origin"
部分及其所有条目,相反,您可能需要做更多的工作/打字。您可以使用ssh://...
或https://...
等完整网址命名其他存储库;对于已在您自己的计算机上的存储库的特殊情况,您可以使用相对路径名称,如您的示例所示。
我认为最好将refspec视为识别一个"远程存储库",可能在网络上的其他某台机器上。这有助于我清楚地了解谁有权访问什么。一个"远程存储库的特例"在你自己的本地机器上是一个特例。显然,如果它在您的本地计算机上,它可以随时访问。其他遥控器往往不太容易接近。
考虑克隆的情况,例如,从某个网站(kernel.org或其他地方)git自身的源代码到笔记本电脑上。在某些时候,你拔掉笔记本电脑并随身携带 - 也许是在你没有网络访问权限的飞机上。所以"他们"允许您访问其存储库并将其复制到您的存储库中。一旦你拥有了所有东西,你就不需要他们的#34;除了偶尔与他们重新同步。
git fetch
可以使用两个以上的参数如果您运行git fetch repository refspec
,则不仅会更新本地存储库中的对象,还会更新一些" ref-names" (参考文献;见下文)。 fetch
的最后一个参数是" refspec"部分,(忽略一些技术性)基本上是ref-names的对,用冒号分隔。例如,您可以写git fetch ssh://... master:refs/remotes/origin/master
。
您需要指定哪些参考名称(如果有)在您从获取的地方,应该将其对象带过来 - 但同样重要的是,该名称是什么名称( s)那些应该在"你的"库。当然,"他们"有分支master
,还有分支maint
(维护),next
等等。最初,您可以在存储库中为它们提供相同的分支名称 - 但是在您工作之后,添加了内容并重新与它们同步,* master
和您的{{1} } 是不同的。因此,您需要一个不同的名称来放置"他们的分支"当您获取其master
的更新时。
使用远程名称(例如master
)运行git fetch
,通过origin
行为您提供refspec(事实上,可以有多条fetch
行,多个refspecs)。但是当你不使用遥控器时,你必须提供自己的refspecs。你没有,所以你得到了一个默认值(稍后会详细介绍)。
引用包括分支和标记名称之类的内容。但是,他们 更加通用和灵活。实际上,fetch
也是一个参考。参考文献有一个完整的名称空间"正在发生的事情:它们几乎全部拼写为HEAD
,并且特定的种的refs生活在这个空间的不同部分。你将一直使用的四个是refs/
(这是一种特殊的 - 它不是以HEAD
开头而且git一直在内部使用它 - 但它仍然是一个引用) ,分支(本地分支),标记和远程分支。
(事实上,refs/
引用名称是所以特殊,如果你删除它,git决定你不再拥有一个存储库。)
Git通常会自动选择"正确的类型" ref并没有让你把它全部拼出来,但它有助于了解所有这些东西,特别是当git混淆了它的时候,把它搞清楚并做我的意思"代码做了一些你实际上并不是真的意思。
本地分支位于HEAD
,因此您的本地refs/heads/
分支实际上是全名master
。创建新分支时,这只会添加更多refs/heads/master
个名称。 (那些在你本地存储库中的文件中结束。创建一个分支只需要创建一个41字节的小文件。这就是为什么在git中分支是如此快速和简单。)
通常,您不在refs/heads/
部分,只需编写分支名称。 Git知道该怎么做。
标签位于refs/heads/
:标签refs/tags/
只是v1.0
。将refs/tags/v1.0
与--tags
一起使用只是告诉它将git fetch
添加到它将更新的refspec中。 (在某些版本的git中,这是"替换"而不是"添加"。)
通常,您不在refs/tags/*:refs/tags/*
部分,只需编写标签名称即可。由于您正在运行refs/tags/
或git tag
等命令,因此git知道该怎么做。
尽管有名字,"远程分支"实际上是一个本地的东西,保存在"你的"回购。换句话说,当你在飞机上拿笔记本电脑时,它们会随身携带。
远程分支位于git fetch --tags
,然后一个拥有更多名称部分,这只是远程的名称。例如,对于refs/remotes/
遥控器,您可以origin
跟踪远程refs/remotes/origin/master
上master
的内容。如果origin
还有一个名为origin
的分支,您可以跟踪maint
那边的内容"在您自己的本地maint
。
同样,通常你会遗漏refs/remotes/origin/maint
部分 - 但这一次,你保留了远程名称。所以你写的是refs/heads
和origin/master
。
额外名称部分的一个重要原因是您可以拥有多个遥控器。如果您有遥控器origin/maint
和origin
,请在fred
保留master
- 来源的副本,并保留origin/master
的副本 - -fred在master
。额外名称部分的另一个重要原因是,当您编写fred/master
时,git可以告诉您的意思是远程分支origin/master
,而不是您的本地master
}。
这些"远程分支"是master
需要更新的内容。但是,为了自动更新它们,它需要知道远程的名称。这就是为什么git fetch
更好":它只是自动执行所有这些操作。您可以使用git fetch remote
明确地将它们写出来,但确保将其全部保存在git fetch url "+refs/heads/*:refs/remotes/origin/*"
下更好。
很久以前,git没有这些东西。相反,您运行了remote "origin"
,例如git fetch url refname
。
为了完成这项工作,git fetch ssh://... master
不得破坏您的 fetch
。所以它做了 - 并且仍然做 - 是去远程存储库并将所需的所有存储库对象,将它们放入存储库,然后写另一个"特殊的"参考,master
。 (例如FETCH_HEAD
和HEAD
以及一些其他特殊名称,MERGE_HEAD
不属于FETCH_HEAD
空间。)
每次编写refspec并省略冒号时都会发生这种情况。而且,如果你完全忽略了refspec,那么 就像写了refs/
一样。因此:
HEAD
表示git fetch url master
git fetch url master:FETCH_HEAD
表示git fetch url maint
git fetch url maint:FETCH_HEAD
表示git fetch url
请注意,远程存储库是一个git存储库(" well duh" :-))。这意味着它有一个git fetch url HEAD:FETCH_HEAD
。如果它是HEAD
的典型存储库,则其fetch
与其HEAD
相同,因此您获得的默认值是获取master
并写入进入master
。
FETCH_HEAD
Git' git pull
命令基本上只是一种方便的方法。它意味着"与pull
后跟git fetch
(或git merge
,git pull --rebase
后跟git fetch
相同,但请忽略此处)。
git rebase
例如,git pull origin master
做的是调用git pull
"旧方式",以便这会带来git fetch
' s {{1但无法更新origin
。相反,它只是将填充内容的引用放入master
。在那里,它对大多数命令都是不可见的,包括refs/remotes/origin/master
。
但FETCH_HEAD
的下一步是运行(实际上):
gitk --all
这会将更改合并到当前分支中,这使得大多数命令都可以看到它们,包括git pull origin master
。
在这种特殊情况下,您运行git merge FETCH_HEAD
或gitk --all
,或者没有 git pull remote branch
参数的任何一个都无关紧要{ {1}}脚本阻止git pull url branch
更新远程分支名称。
(在git 1.9中,带有远程名称的branch
或没有能够计算远程名称的参数的pull
将运行git fetch
,以便更新远程分支名称。)
答案 1 :(得分:0)
Git fetch不会将任何内容集成到您的存储库中,即它只会将有关更改的信息下载到本地副本,而不是更改本身。 Git拉扯另一方面
在默认模式下,git pull是git fetch的缩写,后跟 git merge FETCH_HEAD。
因此,pull实际上会将来自远程存储库的更改集成到您当前的分支中,而不仅仅是将有关更改的信息提取到存储库索引中。您可能希望这样做,例如在将更改合并到本地副本之前检查对远程进行了哪些更改。 Here's a good article关于此事。
以下内容应说明正在发生的事情
> git init main
> git clone main other
> cd other
> touch file.txt
> git add file.txt
> git commit -m "Added file.txt"
master (root-commit) 027216b] Added file.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file.txt
> cd ../main
> touch a.txt
> git add a.txt
> git commit -m "Added a.txt"
[master (root-commit) 8ac8913] Added a.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a.txt
> git fetch ../other/ master
warning: no common commits
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../other
* branch master -> FETCH_HEAD
> git diff master FETCH_HEAD
diff --git a/a.txt b/a.txt <-- a.txt does not exist in FETCH_HEAD
deleted file mode 100644 <-- a.txt does not exist in FETCH_HEAD
index e69de29..0000000
diff --git a/file.txt b/file.txt <-- file.txt does not exist in master
new file mode 100644 <-- file.txt does not exist in master
index 0000000..e69de29
因此../other
的更改已被提取到FETCH_HEAD
,您可以查看差异并根据需要合并更改,而不是仅仅执行pull
并冒险从远程破坏当前分支中的某些东西。
另一个选择是总是拉到新创建的分支并查看那里的差异,但这有点麻烦。