我在我的教程中学习了git,它最近给出了cat .git / config的输出,用于跟踪远程分支,如下所示。我明白那个分支" master"是主分支,origin是指本地计算机中的远程跟踪分支,但有人可以解释一下获取,合并和远程选项是什么(我理解其余的)?
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = https://github.com/rich44/explore_california.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
答案 0 :(得分:2)
从技术上讲,这些中的每一个都只是一个带变量的部分,因此,例如,[branch "master"]
是主分支,它不是真的,它是' s只有一对设置可以拼写为:
branch.master.remote origin
branch.master.merge refs/heads/master
你的问题有效地解决了一些部分问题,我试图按照合理的顺序进行处理,尽管Git就是这样,有时候订单是不合理的。 : - )
Git喜欢 1 来谈论"部分"在配置中。具体来说,git config
命令包含--rename-section
和--remove-section
。 部分基本上只是方括号内的部分,这是一种最初来自INI file format的语法。
然而,除此之外,Git内部并没有真正关心部分。每个程序只使用固定字符串(例如core.bare
或branch.master.remote
)或使用regular expression或类似内容(例如core\..*
)进行查询,该[core]
匹配.
中的所有内容1}}部分。这里需要反斜杠来保护第一个点.
字符;第二个*
字符表示"匹配任何内容"并且星号core.
- 在信息学理论中称为Kleene star - 意味着"重复它零次或多次"。因此,这匹配任何以git config
开头并继续为零个或多个字符的字符串。 (Git中与部分中的项匹配的大多数C代码比这更粗糙;只有git config
本身和运行[remote "..."]
的各种脚本才真正使用正则表达式的全部功能。)
扫描匹配项的功能允许Git查找所有遥控器,它们只是每个remote "..."
部分中的所有名称。 (这里引用的双引号是因为INI文件语法禁止远程名称和分支名称中允许的某些字符等等。幸运的是,远程和分支名称不能包含双引号:如果可以,我们将不得不想知道这些如何被编码。)
1 我意识到我在这里anthropomorphizing Git。这是一个有用的比喻。但请记住,不要将计算机拟人化:他们讨厌这个!
[remote "origin"]
abracadabra = magic word
hello = kitty
部分因为INI语法非常灵活,所以您可以将任何您喜欢的内容放入此部分。 Git不知道或不关心的事情,Git完全无视。例如,您可以编辑配置以包含:
url
这两个设置将被忽略。因此,找出Git实际上会关注哪些项目会更有趣。 (我们制作的任何列表都必然是不完整的,因为Git会逐渐增加新的"要注意的项目随着时间的推移:Git一度寻找pushurl
而不是pushurl
。很久以前,我在Git脚本中添加了代码以检查pushurl
。然后出现了新版本的Git 1.6.4,它正好使用了url
我使用它的方式相同。[显然我们也有同样的想法。]如果我们选择好新项目,我们可能最终会同意Git人员的意思,就像在这里发生的那样,但它&#39总是有点风险,增加了新的东西。)
尽管如此,这是一个部分列表,主要是从the git config
documentation复制而来:
pushurl
:从中获取的默认位置,通常是推送到。mirror
:如果设置,则为推送的默认位置。--mirror
:如果已设置,默认情况下会推送到此远程用户proxy
。fetch
:为libcurl提供代理设置。git fetch
:为push
提供默认的refspec(可能会重复)。git push
:为prune
提供默认的refspec(可能会重复)。--prune
:如果已设置,请默认从此远程使用fetch
进行提取。您明确询问的git fetch
的{{1}}行供应 refspecs 。有关refspecs的更多信息,请参见下文。
branch "..."
部分同样,Git确实关注的事情可以设置很长的列表。 that same git config
documentation中记录了这些内容,尽管可能从未完全记录下来。
remote
:提取和推送时使用的默认远程。merge
:在远程Git 上看到的分支的名称,用于获取和推送时使用。在复杂的情况下,这会有点复杂:请参阅下面的refspecs说明。rebase
:设置{默认false
,其他选项包括true
和preserve
),了解git pull
下半年的运行情况(请记住{ {1}}基本上是"首先运行git pull
的简写,然后运行另一个,第二个,Git命令")。git fetch
:在description
求职信和拉请求中插入一个简短的描述性字符串。 Git最初有分支和标签。为了使它们分开,Git将format-patch
中的分支和refs/heads/
中的标记存储起来。这些事实上仍然只是refs/tags/
内的目录,尽管今天还有#34;打包引用"存储在.git
中,如果您有数千个很少更新的分支和永不更新的标记,则可以节省时间和磁盘空间。
这意味着,当您看到.git/packed-refs
之类的分支名称时,Git实际上会看到master
。这不仅仅是Git存储分支的哈希ID的地方,它也是Git首先知道它是分支的方式。您输入refs/heads/master
; Git在master
和.git/refs/
中进行搜索,然后提出.git/packed-refs
;并且refs/heads/master
部分告诉Git:啊哈,这是一个分支!
当Git收购远程跟踪分支时,它们很容易添加,因为前面有一点点规划。远程跟踪分支只是存储在refs/heads/
中的名称。对于此前缀,Git会添加遥控器本身的名称,以便refs/remotes/
进入origin/master
。这个全名告诉Git,该名称实际上是一个远程跟踪分支。
要真正了解refspecs,了解一点Git历史记录会有所帮助。回到Dim Time,在Git拥有远程跟踪和远程跟踪分支之前,人们有各种kludges的集合来处理从其他Git存储库推送和拉取更改。那时有一个refs/remotes/origin/master
,但这是一个难以使用的"管道"程序,主要用于脚本使用。它将其结果转储到名为git fetch
的文件中。前端"漂亮"命令是FETCH_HEAD
。这就是为什么Git有git pull
和push
作为明显但错误的!-opposites,以及为什么人们通常会介绍使用pull
和push
来传输数据而不是使用pull
和push
,这实际上是最好的方式。 fetch
的 nice 版本尚未存在。今天fetch
仍将结果转储到git fetch
,但行为也更好。
由于远程跟踪分支不存在,因此refspecs确实不需要存在。如果你是从Bob的存储库中获取的,那么你有一个运行FETCH_HEAD
的更好的前端脚本。以某种方式(通过git fetch
或ssh
或http
或其他任何方式获取到Bob的计算机,就像现在一样)并提取他的分支和标签并将所有内容放入您的https
文件。然后,您的前端脚本会提取任何看起来很有趣的内容,并让您合并,或者改变或者您想要做的任何事情。
请注意,在此过程中,您不必关心Bob如何命名他的分支。您的前端脚本只会查看FETCH_HEAD
。该文件与您的分支完全分开,您或者您的前端脚本 - 一看完就可以丢弃Bob的分支名称。
当然,你的漂亮的前端拉动脚本 需要知道你的分支的Bob的名字。我们假设你打电话给你的分行FETCH_HEAD
,而鲍勃打电话给他paris
。您始终希望将其合并到您的中,因此您只需将asteroid_433
配置为branch.paris.merge
。
整个过程非常混乱。有人出现并发明了远程跟踪分支,这真是一个非常好的主意。而不是必须记住鲍勃称之为asteroid_433
,为什么不从鲍勃那里得到一切?对于您获得的每个名称,如果它是分支 - 如果它以asteroid_433
开头 - 只需将其放在名为refs/heads/
的存储库中即可。现在,您可以随时轻松查看Bob的所有分支。您仍然需要记住映射("我的refs/remotes/Bob/whatever
= Bob'} paris
")但大多数的时间你们俩可能会使用相同的名字。
想象一下,你是发明这个奇妙新功能的人。当然,asteroid_433
脚本已经存在。您无法更改pull
:它仍会说出branch.paris.merge
,这是Bob计算机上的名称。并且,您不确定这是否是您想要这样做的方式。也许您希望refs/heads/asteroid_433
抓住Bob的git fetch
并将重命名为asteroid_433
,以便获得paris
}作为远程跟踪分支。
输入refspec。 2 在这种情况下,refspec只是一个由冒号分隔的名称,并且可选地带有加号前缀。左边的名字是"来源"右边的名字是"目的地"。源是Bob的分支名称,目标是远程跟踪分支,用于名为refs/remotes/Bob/paris
的远程分支。
为了使这项工作更好,你可以进行模式匹配。无论出于何种原因,您都不使用正则表达式,而是使用shell样式glob表达式。 (在2.9以前的Git版本中,这些版本甚至进一步受到限制。虽然它们运行得很好。)左侧仍有名称bob
,右侧名称为refs/heads/*
,但现在左侧refs/remotes/bob/*
表示"匹配任何内容",右侧*
表示"将其替换为您在左侧匹配的内容"。
这将生成您的远程跟踪分支,*
现在更新。要存储新的refspec,您可以将git fetch
个配置条目添加到fetch
部分。
要允许多次重命名,请确保Git读取所有 [remote "bob"]
行,以便有人可以写:
fetch =
等等。但实际上,大多数遥控器只有一条[remote "bob"]
fetch = +refs/heads/asteroid_433:refs/remotes/bob/paris
fetch = +refs/heads/master:refs/remotes/bob/master
线。
(允许多行是很好的预见,因为事实证明,今天我们有时想要添加以fetch
开头的refspecs,以便我们可以带来Git笔记。你还不知道这一点,但显然你很聪明,首先想出了远程跟踪分支机构。:-))
当然,旧的+refs/notes/...
语法必须四处逛逛,因为您无法更改现有的Git用户'配置。所以现在Git必须通过相同的branch.paris.merge
refspec来使用这个merge
值, map 该值,以便找出正确的远程跟踪分支名称。 (旧的脚本没有打扰 - 它只是直接从fetch
获得了值。这个脚本最近被重写为一个C程序,它不再是显而易见的。{{{ 1}}和FETCH_HEAD
命令,当它们独立运行时,实际上必须执行此映射。)
我也应该在这里提到领先merge
。这只是给定refspec的 force 标志。它等同于rebase
:它意味着"与更常见的分支名称更新规则相比,此引用应该更新,无论什么",如果更新,则允许更新添加新提交,但如果更新将丢失"则拒绝现有提交(例如,如果您正在获取某种上游+
)。通常,每个远程的每个git push --force
refspec都有前导git reset
,因为您总是希望所有远程跟踪分支都更新为他们的分支所说的正确的
2 实际上,对于fetch =
目的,它已经存在,因为+
总是需要它。但它有所改进。
答案 1 :(得分:1)
遥控器是您的本地存储库有关的远程存储库,您可以将本地存储库指向多个远程存储库,您可以使用“git remote --help(也可以探索git remote add ...)”来探索更多。 “Origin”是一个远程存储库,默认情况下是在克隆本地存储库时创建的,它指向您克隆本地存储库的存储库(“git remote show origin”提供了更多信息)。
fetch = +refs/heads/*:refs/remotes/origin/*
上面讲述了下次执行“git fetch origin”时你想要获取的名为“origin”的远程分支
[branch "master"]
remote = origin
merge = refs/heads/master
上面告诉“git pull”下次执行“git pull”命令时哪个分支合并。在上面的例子中,它说要从原始存储库中获取内容。如前所述,有关获取内容的信息来自“fetch = + refs / heads / :refs / remotes / origin / ”。 “merge = refs / heads / master”告诉我们在完成提取后将哪些远程分支合并到本地,在上面的示例中,它告诉将远程分支(origin)“master”合并到本地“master”中。