如何使用git的命名空间来隐藏分支
如何使用git的命名空间来隐藏分支
背景
我正在与一个大团队一起使用git进行版本控制。正常的流程是:
- 从“待办队列”中选择一个工单。
- 通过本地分支处理问题(例如git checkout -b my_feature_branch)。
- 随着工作的进行,进行多次提交(例如git commit)。
- 将本地更改推送到远程分支,以便在多台计算机上备份工作,以防笔记本电脑损坏或被盗(例如git push -u origin my_feature_branch)。
- 最终在我们的私有github页面上创建一个代码审查,并将特性分支合并到主分支上(squashed merge)。
除了员工根据需要创建的远程特性分支外,我们还有几十个用于创建我们向客户交付的“金版构建”的发布分支,例如1.00、1.01、2.00、2.01、2.02等。
问题
一些开发人员开始抱怨分支太多,我也倾向于同意。一些开发人员没有在不再需要时及时清理旧分支(尽管github提供了一键删除功能,用于在代码审查完成后删除分支)。
问题
有没有办法配置我们公司的github部署,使得当人们使用CLI的git branch命令时:
- 只会显示我们的“重要/发布/金版”分支。
- 一次性开发(临时)分支只会通过git branch -a命令显示?
这样做的主要目标是减少混乱。
编辑:我找到了一个类似的问题,但唯一的答案根本不适用(不要使用远程分支),这违反了我允许人们将代码推送到远程分支作为数据备份的关键约束。正如@Mort所暗示的,私有命名空间的概念似乎正是我所寻找的。现在,我该如何实现呢?
如何使用git命名空间隐藏分支
有时候我们希望在一个Git仓库中隐藏一些分支,只对特定的用户或团队可见。Git的命名空间(namespace)功能可以帮助我们实现这个目标,它允许我们将一个仓库的引用(refs)划分为多个命名空间,每个命名空间都有自己的分支、标签和HEAD。命名空间可以将每个命名空间作为独立的仓库来进行拉取和推送操作,同时共享对象存储。
为了激活一个命名空间,我们可以使用以下命令:
export GIT_NAMESPACE=foo
或者
git --namespace=foo clone/pull/push
当命名空间被激活时,通过使用`git remote show origin`命令,我们只能看到当前命名空间中创建的远程分支。如果我们取消激活命名空间(`unset GIT_NAMESPACE`),我们将再次看到主要的远程分支。
在这种情况下,一个可能的工作流程是:
创建一个功能分支并在其上工作
export GIT_NAMESPACE=foo git checkout -b feature_branch # ... 在该分支上进行工作 ... git commit -a -m "Fixed my ticket from backlog" git push origin feature_branch #(将分支推送到命名空间中)
合并上游分支
unset GIT_NAMESPACE git checkout master git pull(为了获取最新的版本) git merge --squash --allow-unrelated-histories feature_branch git commit -a -m "Merged feature from backlog" git push #(将分支推送到主要的引用中)
命名空间提供了分支的完全隔离,但是你需要每次激活和取消激活命名空间。
需要注意的是,当进行推送操作时要小心。Git将在当前命名空间中进行推送。如果你在功能分支上工作,但忘记激活命名空间,那么在推送时,你将在主要引用中创建该功能分支。
使用git命名空间来隐藏分支的原因是为了减少仓库中的分支数量,使仓库更加整洁。解决方法可以通过以下两种方式实现:
1. 开发人员使用自己的仓库分支进行推送,而不是推送到共享仓库。这样,他们的远程特性分支对其他人是不可见的,所以他们看到的任何“杂乱”都完全是他们自己的责任。
2. 如果所有内容都存储在单个仓库中,可以设置一个简单的Web服务,该服务可以接收来自GitHub的通知,当你关闭一个pull request时会收到通知(响应PullRequest事件)。然后,可以让该服务删除与pull request对应的源分支。
第二种方法相对于第一种方法更复杂,因为它涉及到编写代码和运行一个持久的服务,并且该服务需要对远程仓库具有适当的权限。
实际上,并没有规定你必须在任何地方都推送所有内容,或者从任何地方都获取所有内容。如果你只想要一个仅包含当前重要引用的仓库,可以创建一个。如果没有全局的仅包含重要部分的仓库,可以通过配置fetch命令只获取你关心的内容来在本地创建一个。
在使用Git进行团队开发时,有时会遇到需要隐藏分支的情况,本文将介绍隐藏分支的原因及解决方法。
在团队开发中,如果可以使用fork仓库并使用pull请求或者只保留分支给自己使用,那么这是最好的解决方案。但是,有些情况下我们可能会遇到无法fork仓库或者需要在多台工作站上工作的情况,这时就需要隐藏分支了。
隐藏分支的方法是在分支名前面加上特定的前缀,例如wip/myuser/
,然后通过自定义refspec来进行fetch和push操作,例如refs/x-wip/myuser/*
。
首先,我们需要在克隆仓库后进行标准的远程配置,如下所示:
[remote "origin"]
url = file:///c/temp/remote.git
fetch = +refs/heads/*:refs/remotes/origin/*
为了将以wip/myuser/
开头的分支推送到refs/x-wip/myuser/
,我们需要添加以下配置:
push = refs/heads/wip/myuser/*:refs/x-wip/myuser/*
然而,这样会覆盖默认的分支推送规则。为了恢复默认规则,我们需要添加以下配置:
push = refs/heads/*:refs/heads/*
最后,为了获取现在位于非传统refs/heads/*
refspec之外的WIP分支,我们需要添加以下配置:
fetch = +refs/x-wip/myuser/*:refs/remotes/origin/wip/myuser/*
最终,我们的远程配置如下所示:
[remote "origin"]
url = file:///c/temp/remote.git
fetch = +refs/x-wip/myuser/*:refs/remotes/origin/wip/myuser/*
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/wip/myuser/*:refs/x-wip/myuser/*
push = refs/heads/*:refs/heads/*
需要注意的是,Git会按照从上到下的顺序评估fetch和push规则,并且一旦匹配成功就会停止。因此,我们应该按照从最具体到最不具体的规则进行排序。
使用标准远程配置的人只会从refs/heads/*
获取分支,而使用第二个配置的人则会从refs/heads/*
和refs/x-wip/myuser/*
获取分支。
当你的分支准备好"公开"时,只需移除wip/myuser/
前缀即可。
需要注意的是,一旦在远程配置中设置了push规则,运行git push
命令时不再只推送当前分支,也不再使用push.default
配置定义的策略,而是根据远程push规则推送所有内容。
因此,你需要始终指定要推送的远程和分支,或者根据这个答案中建议的方法使用别名来简化操作。