5

How can I create a branch alias in such a way that it can be pushed and pulled without being treated as a separate branch. Some background:

We have a branch named Production. For various reasons, I can't just rename the branch.

$ git branch --all
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/Production
  remotes/origin/master

Sometimes I will git checkout production by mistake and not notice it's a new branch. There is no remote branch production. There is also no ref origin/production.

$ git checkout production
Branch production set up to track remote branch production from origin.
Switched to a new branch 'production'
$ git status
On branch production
Your branch is up-to-date with 'origin/production'.

nothing to commit, working directory clean
$ git branch --all
  master
* production
  remotes/origin/HEAD -> origin/master
  remotes/origin/Production
  remotes/origin/master

Git created a local branch production and claimed it is tracking the remote branch production. Now if I commit and push or just push git will push a new branch. Not what I want.

$ git push
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:path/repo.git
 * [new branch]      production -> production

Then I have to step back and reverse things

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git branch -d production
warning: deleting branch 'production' that has been merged to
         'refs/remotes/origin/production', but not yet merged to HEAD.
Deleted branch production (was bc6d7a2).
$ git push origin :production
To git@github.com:path/repo.git
 - [deleted]         production
$ git checkout Production
error: pathspec 'Production' did not match any file(s) known to git.

And somehow now I've lost Production until I pull it again. Is git case sensitive or not?

$ git branch --all
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
$ git pull
From github.com:path/repo
 * [new branch]      Production -> origin/Production
Already up-to-date.
$ git checkout Production
Branch Production set up to track remote branch Production from origin.
Switched to a new branch 'Production'
Your branch is up-to-date with 'origin/Production'.

And pushing doesn't push a new branch now. Actually what I want.

$ git push
Everything up-to-date

My first thought is to create an alias of the Production branch that is called production but I want it to be able to be pushed and pulled as though the two were actually the same thing. This is the thing I don't know how to do. All the alias methods in other questions appear to be local aliases only.

If you have a different solution to my problem, I'd like to hear it as well.

As a side note, bonus points if you can tell me why git is sometimes case sensitive and sometimes not.

Nate
  • 12,963
  • 4
  • 59
  • 80

2 Answers2

3

The OP mentions in the comments a branch alias

git symbolic-ref refs/heads/production refs/heads/Production

That does solve the problem locally, and is simpler than the hooks mentioned below.
Those hooks can be there to ensure both branches remain in sync.

In both cases, that involves a local config to be done on all team members, although I mention "templatedir" at the end, to automate the hook propagation.


Using hooks, You could create a post-commit hook which would make sure the the local branch production is set to the same commit as the Production branch. (or, if you committed on the production branch, that the Production is set to the same commit as the production branch)
That way, both branches always refer to the same commit, and you can push from any one of those.

pre-push hook (git 1.8.2+) which can:

  • check which branch is pushed (production or Production)
  • trigger a push for the other branch

That way, even with a git config push.default set to simple (meaning you are only pushing the current branch), even if you are pushing the wrong one (production => origin/production), the pre-push hook can take care of pushing the other one (Production => origin/Production)

Since both branches are pushed, a pull will always update at least one of them.
And the post-commit hook will ensure that the other one will catch up.

The goal is to no longer care on which branch (Production or production) you are working on.


You can add those hooks in a shared template Git repo folder, which would allow any team member to get those hooks in their newly cloned repo, provided their init.templatedir global config reference that shared folder.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thank you. This is a very creative solution. This solves my problem locally, however a [branch alias](http://stackoverflow.com/a/549949/761771) would also solve the problem locally. It looks like git hooks [are not pushed](http://stackoverflow.com/a/12222225/761771) and so it does not solve the problem for the whole team without manual work for each member. – Nate Aug 12 '14 at 15:05
  • In my bounty description I forgot to mention the portability issue and so if I don't get an answer that does before the bounty expires I'll give it to you anyway. – Nate Aug 12 '14 at 15:07
  • The command for a git branch alias in [that answer](http://stackoverflow.com/a/549949/761771) is `git symbolic-ref refs/heads/trunk refs/heads/master` so I'm thinking I could do `git symbolic-ref refs/heads/production refs/heads/Production`. Though, I haven't tried so I am not sure if it'll work better or worse than a hook @VonC. – Nate Aug 12 '14 at 15:09
  • @Nate That looks simpler than the hooks (I have referenced it in the answer). I have edited the answer to propose a way to mutualize the hook definition. – VonC Aug 12 '14 at 15:13
  • It sounds like there is no easy and portable way to make this work the way I want. I think I have my answer. Thanks for the help @VonC. – Nate Aug 12 '14 at 21:49
1

As an alternative for future readers, I considered creating a production orphaned branch and putting a file that makes it obvious when you are on the wrong branch.

git checkout --orphan production
touch wrong-branch

This would be portable but would not make the production branch behave like the Production branch across clones as I really wanted (and seems impossible)

This could cause a live server outage if (for some unknown reason) someone was on the live server and did git checkout production by mistake.

Community
  • 1
  • 1
Nate
  • 12,963
  • 4
  • 59
  • 80