In Git, how do I configure my local branches to have a prefix when I push them to a remote?

Viewed 247

I work on a team that has a branch naming standard that requires a specific prefix for branches in the central git repository. That prefix is as follows:

dev/<name>/<topic>

Example:

dev/john/my-feature

Locally, for sanity reasons, I don't want to have to deal with the prefix. It's boilerplate that makes typing commands more tedious. Instead, I want my branch locally to just be the <topic>, which in the above example is just my-feature.

I want to see what kind of push & fetch workflow I can build to make this prefixing as transparent as possible. First, let me share some interesting configuration options I currently have set in my global .gitconfig:

[push]
    default = current
[remote]
    pushDefault = fork

The remote-specific settings may not matter here, but I have included it for completeness. There are three distinct use cases I want to support:

  1. When I fetch remote branches that contain the dev/john prefix, I want them to appear locally under refs/remotes/origin/<topic>. For example, remote branch refs/heads/dev/john/my-feature should get fetched locally to refs/remotes/origin/my-feature.
  2. When I push the local branch refs/heads/my-feature to remote origin, it should map to refs/heads/dev/john/my-feature on the remote.
  3. When I push refs/heads/master, it should still go to refs/heads/master on the remote. The master branch should completely ignore the prefixing.

Here is the remote configuration for origin in my repo's .git/config that I have so far. Note that I've only been testing git push for now, I realize that the fetch refspec doesn't support the first use case above.

[remote "origin"]
    url = git@mydomain:myrepo
    fetch = +refs/heads/dev/john/*:refs/remotes/origin/*
    fetch = +refs/heads/*:refs/remotes/origin/*
    push = refs/heads/master:refs/heads/master
    push = refs/heads/*:refs/heads/dev/john/*

Here is what I've observed so far:

  1. git fetch origin so far works in all cases: Branches under refs/heads/dev/john/ get mapped to refs/heads/origin/. And everything else is the normal direct mapping we're all used to.
  2. Doing a git push -n origin master yielded expected results.
  3. Doing a git push -n origin my-feature yielded expected results. Specifically:

    • [new branch] my-feature -> dev/john/my-feature
  4. With a local branch named my-feature checked out, the command git push -n origin push did not respect push.default, and instead pushed all local branches. My expectation is that push.default is still used in cases where the remote.origin.push setting includes a wildcard in the refspec. Without a source branch specified, I want it to still assume I'm pushing the current branch, but just map it to a different remote ref.

The documentation does not support the behavior I'm asserting for the git push -n origin case, from what I read. Specifically the [git-push] docs say (emphasis mine):

When the command line does not specify what to push with <refspec>... arguments or --all, --mirror, --tags options, the command finds the default <refspec> by consulting remote.*.push configuration, and if it is not found, honors push.default configuration to decide what to push.

So all of this, I suppose, is a long way of ultimately asking: How do I make git push -n origin give me the same behavior of git push -n origin my-feature with the given configuration (noting that a change in configuration itself is acceptable)?

0 Answers
Related