How to Use Git Namespace to Hide Branches

How to use git namespace to hide branches

Long story short: you can - but it may be a bit tricky.

You should use the namespace concept (give a look here: gitnamespaces)

Quoting from the docs:

Git supports dividing the refs of a single repository into multiple namespaces, each of which has its own branches, tags, and HEAD. Git can expose each namespace as an independent repository to pull from and push to, while sharing the object store

and

Storing multiple repositories as namespaces of a single repository avoids storing duplicate copies of the same objects, such as when storing multiple branches of the same source.


To activate a namespace you can simply:

export GIT_NAMESPACE=foo

or

git --namespace=foo clone/pull/push

When a namespace is active, through git remote show origin you can see only the remote branches created in the current namespace. If you deactivate it (unset GIT_NAMESPACE), you will see again the main remote branches.


A possible workflow in your situation may be:

Create a feature branch and work on it

export GIT_NAMESPACE=foo
git checkout -b feature_branch
# ... do the work ...
git commit -a -m "Fixed my ticket from backlog"
git push origin feature_branch # (will push into the namespace and create the branch there)

Merging upstream

unset GIT_NAMESPACE
git checkout master
git pull (just to have the latest version)
git merge --squash --allow-unrelated-histories feature_branch
git commit -a -m "Merged feature from backlog"
git push # (will push into the main refs)

The tricky part

Namespace provides a complete isolation of branches, but you need to activate and to deactivate namespace each time

Pay attention

Pay attention when pushing. Git will push in the current namespace. If you are working in the feature branch and you forgot to activate the namespace, when pushing, you will create the feature branch in the main refs.

How to config namespace for 'private' branches in git?

Keep your working branches locally and only push the shared branches. Ask others to do the same.

That's assuming you're all sharing a central repository as a remote, rather than pushing/pulling to and from each other's local repositories.

Remove/hide git branches without deleting commit histories

Here's one alternative: use non-branch references to save the branch-tips before deleting the branch names.

Since these are non-branch references, they won't show up in git branch output, nor in stuff shown by git log --branches and gitk --branches, for instance. However, they will show up in --all listings, and will retain repository objects.

To create or update a non-branch reference, use git update-ref. Choose a name-space within refs/ that you think will not collide with some future use (current uses are refs/heads/ for branches, refs/tags/ for tags, refs/remotes/ for remote branches, refs/notes/ for notes, and refs/stash for the stash). [Edit, July 2022: refs/namespaces/ is now reserved as well, and refs/replace/ is used by git replace. refs/bisect/, refs/rewritten/, and refs/worktree/ are reserved; refs/original/ is reserved if you will use git filter-branch. Gerrit, if you use it, has more reserved names. The list never seems to stop growing, so use care here.]

how do i use git namespaces locally?

Git namespaces is only intended to work with remote repos, not locally (https://github.com/git/git/commit/6b01ecfe22f0b6ccb9665cd8d85d78a381fecffc). Most of the operations that work using git namespaces appear to work on operations that go through the git-upload-pack and git-receive-pack functions.
Thats why the documenation suggests if you want to test it locally to fake it into thinking you're pulling from a remote machine eg: git clone ext::'git --namespace=foo %s /tmp/prefixed.git'

so commands like

git --namespace foo add
git --namespace foo commit
git --namespace foo branch

All essentially do nothing. The only operations that appear to have any effect are clone/fetch/pull and push.

In order to leverage namespaces the way you're hoping, you'd have to set up your own git backend that is capable of translating URL arguments into the GIT_NAMESPACE variable and pass it along to git-http-backend or something similar. The documentation recommends the following in your apache configuration:

To serve multiple repositories from different gitnamespaces in a single repository:

SetEnvIf Request_URI "^/git/([^/]*)" GIT_NAMESPACE=$1
ScriptAliasMatch ^/git/[^/]*(.*) /usr/libexec/git-core/git-http-backend/storage.git$1

Also note that what this documentation does not say, is that what is going on here is extracting the GIT_NAMESPACE variable from a URL and setting an environment variable that git-http-backend is expecting. i.e. http://myserver.com/git/namespace/repository.git. The 'storage.git' part is a typo and should not be there. I should submit a documentation patch.

Here's most of the commits that created this feature.
https://github.com/git/git/commits/398dd4bd039680ba98497fbedffa415a43583c16?author=joshtriplett

Using Git namespaces to host multiple repos


I would like to host a single repository containing small Python libraries for my team, with each library having its own set branches/tags

That would be far easier to do using submodules.

Your main repo would reference subrepos with

git submodule add /url/of/lib1
git submodule add /url/of/lib2
git submodule add /url/of/lib3

git push branches in same namespace

Just try

git branch | grep "issues/*" | xargs git push

If you want to abbreviate, you could try to create an alias mypush

git config --global alias.mypush 'git branch | grep "issues/*" | xargs git push'

You might need to play with ' or ".



Related Topics



Leave a reply



Submit