【发布时间】:2011-11-08 15:16:03
【问题描述】:
我有一个“主”裸存储库和一个“个人”裸存储库。我想将更改从“主要”更新为“个人”,所以我运行:
$ git pull
fatal: /home/gimenero/applib/git/libexec/git-core/git-pull cannot be used without a working tree.
如何拉动推送到“main”的更改?
【问题讨论】:
标签: git
我有一个“主”裸存储库和一个“个人”裸存储库。我想将更改从“主要”更新为“个人”,所以我运行:
$ git pull
fatal: /home/gimenero/applib/git/libexec/git-core/git-pull cannot be used without a working tree.
如何拉动推送到“main”的更改?
【问题讨论】:
标签: git
git pull 执行 fetch 后跟 merge,如果没有工作树,您将无法合并。 (如果出现合并冲突,将无处可解决。)
相反,您可以直接获取。假设您的主存储库在您的个人存储库中配置为远程调用源:
$ git fetch origin master:master
请注意,只有当您的个人存储库的主分支镜像主存储库的主分支时,这才会成功。否则,Git 将拒绝非快进获取。
【讨论】:
git fetch --all 会起作用,但它没有给出预期的结果(即,如果你在裸“个人”存储库中执行git fetch --all,那么 cd 进入非裸“个人”存储库并执行git pull 没有从主仓库中提取任何更改)
更新:
$ git fetch origin +refs/heads/*:refs/heads/* --prune
先说一句:当我们谈到一个名为“xyz”的分支时,git 实际上将其称为refs/heads/xyz。但是你可以输入“xyz”的缩写,否则会很疯狂。 (顺便提一下,标签是refs/tags/xyz。)普通的xyz 是模棱两可的,因为它可能是一个分支、一个标签或一个提交哈希的前N 个字母。而refs/heads/xyz 则明确表示一个分支。
因此,即使您可以键入 git fetch origin foo:bar 来获取存储库中名为 bar 的 foo 分支,您也可以更明确地键入 git fetch origin refs/heads/foo:refs/heads/bar 来执行相同的操作。 (虽然如果foo 实际上是一个标签而不是一个分支,后者将失败,因为它们的refs/heads/foo 不存在。明确性ftw。)
git fetch origin refs/heads/*:refs/heads/* 表示他们所有的分支都属于我们。该命令的运行就像* 部分被替换为其每个分支的分支名称一样。即git fetch origin refs/heads/abc:refs/heads/abc refs/heads/def:refs/heads/def ...(假设他们有名为abc和def的分支)。
--prune 选项意味着我们存储库中与refs/heads/* 匹配但在其存储库中不存在的任何分支都将被删除。
最后,+ 前缀是允许非快进提取。没有它,任何需要 force-updates 的分支更新都会被拒绝。
总而言之,最终结果是您的存储库中的分支最终看起来与他们的完全相同。
- [deleted] (none) -> bar
* [new branch] foo -> foo
4812558a5f..a6aeec6517 abc -> abc
+ a1b2c3d4e5...1a2b3c4d5e def -> def (forced update)
foo、abc、def,而我们有(有)一个额外的:bar
bar 被--prune 删除,def 被+ 前缀允许强制更新。如果不使用 + 和 --prune,会发生以下情况:
* [new branch] foo -> foo
4812558a5f..a6aeec6517 abc -> abc
! [rejected] def -> def (non-fast-forward)
将顶部的命令与以下命令进行比较:
$ git fetch origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/* [--prune]
这基本上就是我们输入git fetch origin [--prune]时发生的事情!
【讨论】:
push --mirror 的反面,这是危险的(即使在发生冲突的情况下也会替换,在目标上删除任何不在发件人端的东西)。