Git:在裸仓库中更改活动分支的正确方法?

239
我有一个裸仓库,用作我的项目的中央存储库。 所有开发人员都使用 git clone <repo>来共享它。 当他们克隆时,他们会得到主分支的检出(除非他们使用 git clone -n),因为repo.git/HEAD包含ref: refs/heads/master,使这个分支成为活动分支
问题是,如何正确更改活动分支? 我可以直接修改repo.git/HEAD文件,但那看起来很恶劣,而且有点像破解。
我尝试在仓库.git目录中执行git checkout <otherbranch>,但失败了,因为我不在工作树中。
我尝试过 git update-ref HEAD refs/heads/otherbranch,但那只是将refs/heads/master更新为与refs/heads/otherbranch相同(好吧,我在一个虚拟仓库中做了那个操作,而不是在生产仓库中!)
我尝试过git update-ref --no-deref HEAD refs/heads/otherbranch,几乎成功了。 它更新了HEAD文件,但将其设置为由refs/heads/otherbranch指向的提交的SHA1值。
我正在使用git版本1.7.0.2.msysgit.0进行测试。
我猜想不可能通过git push来完成此操作,因为允许所有人更改默认分支似乎有点不安全!但是在仓库.git目录中有更好的方法来完成这个操作,而不是直接修改HEAD文件。

在我看来,你正在从根本上尝试做错误的事情。如果你想让默认分支不是主干,那么该分支需要成为主干。或者,使用两个不同的存储库。 - Nicholas Knight
13
这里的基本原则是什么?裸仓库支持多个分支。我将裸仓库用作本地仓库的备份,并镜像了这些分支,使两者都有主分支和开发分支。如果我想在裸仓库中查看开发分支的日志,则必须修改文件,似乎 Git 在裸仓库支持方面存在根本性的错误。 - Cthutu
18
在我看来,你在这里基本上是错的。 “master”作为分支名称并没有什么特别之处,它只是一个默认值。在我们维护的存储库中,我们没有“master”分支,因为“master”对公司而言没有意义。每当我们发布一个新版本时,我们会创建一个新的维护分支,并将其分配为活动分支。 - Spacemoose
@NicholasKnight,虽然我理解你的想法,但这是第一个告诉我如何切换到主分支的SO Q/A!当我在功能分支上创建我的初始repo并进行裸克隆时,从该裸repo进行的后续克隆默认使用该分支而不是主分支。 - Warbo
1
哇 - 这个问题一直在运行和运行 - 这是我的第一大声望积分赚取者!关于“主”这个词,它只是一个名称,如果对于您的组织、团队、项目、阶段等没有意义,那么选择适合的名称,这样当您的协作者克隆您的存储库时,他们会立即切换到您作为配置管理器想要他们使用的分支。我曾经使用过ClearCase(呕吐!),所以你的选择是“main”,“main”或“main”。噫。 - kbro
这个回答解决了你的问题吗?将Git远程HEAD指向除master以外的其他内容 - A.L
7个回答

350

如果您可以访问远程裸仓库,则该文章建议

git symbolic-ref HEAD refs/heads/mybranch

这将更新您的存储库中的 HEAD 文件,使其包含:

ref: refs/heads/mybranch

git-symbolic-ref所述:


如果您无法访问远程 repo,请参见我的先前回答


请记住,像git remote set-head这样的命令:

  • 不会更改远程repo的默认分支。
    它只会更改存储在本地 repo 中的一个远程跟踪分支,作为 refs/remotes/<name>/HEAD

  • 不会更改HEAD本身(再次是refs/remotes/<name>/HEAD),因此需要使用git symbolic-ref

因此,在此处git remote set-head 不是答案。
如果您可以直接访问远程 repo,则可使用git symbolic-ref HEAD


3
谢谢!我可以直接访问远程bare repo,所以git-symbolic-ref就可以完成任务。但是,我也喜欢另一个帖子中提到的no-common-ancestor trick技巧——这一定是需要牢记的。我花了很长时间在谷歌上搜索,但找不到你之前的答案,然而"git remote head master"却在第二高排名,紧随git-remote(1)之后。真奇怪,这表明如果不知道确切的信息,要想找到某些东西是多么困难。 - kbro
git symbolic-ref HEAD refs/heads/mybranch 对我来说完全没问题!谢谢!;) - vinzenzweber
1
我非常感激这个问题,因为我不小心检出了一个与主分支不同的分支,现在我必须修复它。 - Jonny
1
这个答案对我很有帮助,但是有一件事情不太清楚:使用 git symbolic-ref 改变了裸远程仓库的 HEAD 后,如何更新克隆库以反映裸远程仓库的新 HEAD?如果我创建一个裸远程仓库的新克隆,它的默认检出和历史记录正确反映了新的 HEAD。但是现有克隆的 git log 输出仍然显示远程旧 HEAD,即使尝试了各种 git fetchgit pull - Nick Williams
@NickWilliams 很好的问题,我不太确定,除了在本地更改 origin/HEAD之外。 - VonC
显示剩余3条评论

9
要更改分支,您需要将HEAD引用更改为要使用的分支。
首先,通过执行以下操作列出裸仓库中的所有引用:
$find ref

首先找到与你的分支相关的引用,格式如下:refs/heads/<my_branch>。接下来的步骤是检查当前引用,只需输入以下命令:

$git symbolic-ref HEAD

所以您需要知道哪个是当前分支,然后根据需要更新它。

$git symbolic-ref HEAD refs/heads/<my_branch>

就是这样,享受吧。


4
如何正确更改活动分支?
状态: 在repo.git目录中运行git checkout命令会返回fatal: This operation must be run in a work tree。
提示: 只需添加--work-tree参数。
详细示例: 假设: 远程服务器上有裸的git:~/bare_git_repository.git 分离的工作树:/var/www/myappremote 在本地服务器上创建版本为1.7的分支(otherbranch): git branch version.1.7 git push origin version.1.7
在具有裸的git repo的远程服务器上: $ cd ~/bare_git_repository.git $ git branch master version.1.7
如上所述,以下命令: git checkout version.1.7 返回: fatal: This operation must be run in a work tree 使用以下命令成功更改活动分支: git --work-tree=/var/www/myappremote checkout version.1.7
检查结果: $ git branch master version.1.7
使用以下命令检查结果: ll /var/www/myappremote 希望这能帮到您。

1
这个非常简单的解决方案对我很有用,谢谢!需要注意的是,我不得不手动创建一个空的工作树目录,才能成功执行命令。 - Joël Esponde

1

至少在v.2.35.3版本中,git symbolic-ref HEAD refs/heads/otherbranch不再生成文件refs/heads/otherbranch。相反,它会静默地添加到.packed-refs文件中,并且如果没有提交,则添加到HEAD中。git symbolic-ref HEAD将从所有位置静默报告。

请参见git help pack-refs


-1
此外,如果您无法访问裸仓库,则可通过执行git remote set-head来完成。
请参阅之前的response

-3

我在我们的服务器上也有一个裸仓库,并且成功地使用以下命令检索文件

git clone //server/repo/directory -b branch_name

即使manpage上说这仅适用于非裸库,也可以将其导入新的本地存储库。


1
虽然你说的是对的,但是你使用-b来选择特定的分支,这破坏了我的问题背景,因为我想知道如何设置默认分支。 - kbro

-3

我在执行以下命令前后比较了两个目录:

git symbolic-ref HEAD refs/heads/mybranch

看起来只有repo.git/HEAD文件发生了变化,所以很可能可以安全地“黑客”这个文件。


2
直接编辑Git引用文件可能会引入微妙的破坏问题,我强烈建议不要这样做。管道命令比直接编辑引用更容易且更安全。 - Alain O'Dea
2
这个@boryn有什么优势? - Alex Chamberlain
2
Git在后台跟踪许多东西,例如引用历史记录。如果您手动更改文件,则不会被记录。虽然这可能并不重要,但是如果您追踪某些提交并想要找到它们,如果您没有只是“黑客”文件,那么您会更加高兴。 - qwerty9967
1
我使用了这个命令。但是这个答案对于理解它的工作原理非常有帮助,特别是理解refs/heads是一些内部的东西,我不应该改变它,只能改变“路径”的最后一部分。因此,我投了赞成票,因为我认为这是非常有价值的信息。 - Mike Keskinov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接