Hacker News new | past | comments | ask | show | jobs | submit login
Git Branch Naming Conventions (deepsource.io)
84 points by sanketsaurav on May 1, 2020 | hide | past | favorite | 81 comments

I've seen projects outlive multiple issue-tracking systems.

Nothing inherently wrong with having the number in the branch or commit-message, but please make sure the rest of the name/message stands on its own.

If you are lucky you can import old issues with the same IDs. If not then

This is why I generally prefer using the full issue URL in comments, but that is unwieldy for branch names.

Sure, but sometimes the old issues and the old server just gets lost in the transition. I'm not sure full URLs really help because it's unlikely to have both issue trackers continuing to run. I think the parent's point to add some detail is valuable.

"Fix for PJ-1029: Screen flicker on GTX1070 while jumping off cliff"

Not everything needs to be future proof, being useful right in the moment is good enough.

I disagree with naming conventions for branches. Just give it a name, I like to have have a bit of fun sometimes. For example: 'org-mode', 'more-org-mode' and 'org-mode-3-still-org-moding' are 3 real branches I recently shipped. All the naming convention does is make another pointless argument. As long as the name is more descriptive than 'my-branch' I'm fine with it. Argue over something less pointless.

Agreed. Branches should be short-lived, anyway. If you need a long-lived pointer to a commit, use a tag.

I love the "naming branches for modern git workflows" in the subtitle...

You wouldn't want to be the odd developer out naming their branches like in those un-modern git workflows, would you? Well then, you should buy my e-book and Egghead course, subscribe to my tinypost, and follow me on Twitter.

The principles of marketing don't change, folks.

Can I see a live stream before I buy your e-book?

I fall somewhere in between. I don't mind if the names are random and fun. But I do like: - avoiding the use of slashes (because with enough folks working on the same repo, you can get some crazy conflicts) - prefixing with some sort of "handle" (e.g. your initials) to help avoid branch name conflicts

I made it a policy to only use a-z, 0-9, and _ in any branch, file, folder, or any other 'names' in the cli. Basically anything I'd type in the cli as an identifier/name. I find it prevents weird issues with characters when scripting and such, since the rest of the shiftable symbols on the 1-0 row (*, &, etc.) tend to cause issues when used too much in names because they're also used as operators and stuff. I think I started doing that with Windows filenames, since it has so many limits, and it crossed over into my Linux cli workflow.

Yea, the slashes in branch names grates on me because '/' is a character that means too many things and the name winds up in URLs on Github.

I had similar thoughts: https://blog.kowsheek.com/git-branch-naming-conventions-for-...

The purpose of feature branches is agility and shouldnt be used to create more process.

Yeah, I don't think you need to be over perspective over branch names. With the caveat that I like two guidelines: beginning branch names with the users name for a short user-specific feature. And something reasonably descriptive of what the branch is especially for non user specific ones.

Agreed. Branch names are temporary and ideally not persisted. Same with commit messages in many workflows. If your branch names are ever exposed outside your team (like environment per branch or something) then yes, maybe you should be mindful of that.

Just want to throw a small one in there: branch names are all lower case.

Prevents strange issues when you use a case insensitive file system like on OSX or Windows

What kind of issues have you encountered? Since NTFS, HFS+, and APFS are all case-preserving the only thing I've ever run into was a Unix-only project where they files which differed only in case (i.e. Makefile and makefile) and the project team fixed that by recognizing that it was just asking for trouble.

I make a branch named 'feature/ABC-123', do some work, and push to the server. You want to take over my branch so you do a fetch then run the command 'git checkout feature/abc-123'. You will check out my branch, but when you go to push back to the server you're going to be push a new branch with a lower case file name unless you realize what has happened and know that you need to run 'git push origin feature/abc-123:feature/ABC-123' to push your changes to the existing remote branch.

Yep exactly this. We've gotten into messes before when people are working on - or think they are - the same branch. Some os think they are the same, others different.

Also just finished migrating something that ran on IIS to linux, and got the casing pains once again.

If the universe were to be reinvented, I ask please make everything case sensitive by default

Interesting — I've never hit that, presumably because it always works the right way if you use tab-completion or are copying a command from the GitHub/GitLab UI. That's good to know about.

Yeah, it’s not exactly a common problem. I’ve only seen it come up in that scenario when two people with different casing habits try to share a branch.

Save yourself the headache and just make your project directories case sensitive.

fsutil.exe file setCaseSensitiveInfo "C:\path\to\dir" enable

can't do on osx without reformat if i'm recalling correctly

APFS filesystem has volumes that share shape with Macintosh HD. You can create a separate encrypted case sensitive volume called Development

that's like using a nuke to hammer a nail.

It really isn’t. APFS has excellent support for logical volumes, and it’s barely any harder than creating a new folder.

(Each volume can also use an extra encryption layer if you want, which can be super useful.)

I don't recall seeing anything in git that involves putting the branch name on the filesystem. Not even poking around in the .git directory. What are you seeing?

So, every branch is represented by a file in .git/refs; you’ll find, for example, .git/refs/heads/master alongside any other local branches you’ve created.

There’s an analogous tree for remote branches!

Well, hell. I've done surgery on those files before. Not sure how I forgot that.

A handy thing about jira is that the ticket picks up the commit automatically, so anyone viewing that ticket can go straight to the changes if the branch begins with the ticket id.

I don't what the definition of a 'feature' is. Is it a task or something bigger than a task?

I'm not a huge fan of overly verbose commit messages. They can make the job of compiling release notes annoying.

> I'm not a huge fan of overly verbose commit messages. They can make the job of compiling release notes annoying.

Commit messages have little to do with releases or release notes. I'd argue either your commits or your release notes are most likely wrong in some way if you are doing that.

We release our code as a debian package that stored in jfrog and then used to build GCP images for each release.


> A handy thing about jira is that the ticket picks up the commit automatically

It's certainly possible to configure that sort of integration. But it won't just happen out of the box.

I'll add some more I find useful:

1. Use All lower case. It's impossible to be consistent with any other case (except all upper case). This is important. Git does NOT like case insensitive file systems, and people having two branches with a segment with different case causes problems.

2. Use path segments to group branches. Categories can be versions or a specific team or user e.g. version/v1.0 or topic/desktop/123-add-printing-support or /topic/jimbob/123-add-printing-support Many systems will display these segments in a tree structure so you can quickly navigate all branches of a specific kind e.g. all your ongoing work separate from 20 version maintenance branches.

3. When making branches to cherry pick hotfixes to a different branch, include the new target branch in the branch name to avoid confusion. E.g. topic/123-fix-blank-password-always-accepted and topic/blank-passsword-always-accepted-on-version-v1.0

I discourage people from using path parts, because git actually treats it like a path—and I’ve seen some conflicts with this. Better to just use hyphens as separators and forget that you can use slashes at all.

Totally agree on all lower case.

Yeah, I've had problems by using '/' on branch names. When you have something like origin/jira/PROJ1-123/DoThisThing, some commands don't like.

If there's no good reason to do that, just don't.

I'm starting to like slashes in branch names. They are so easy to visually grasp a list of branches.

Do you recall any of the problems you had? I'm frequently using checkout/rebase/merge workflow and never had any problems. But I always felt I am not using all features got had to offer.

I had a recent situation where someone had created a branch called `something/some-reason` and I had a branch called `something` that already existed locally. I was unable to check out `something/some-reason` because `something` already existed as a file.

Slashes in branch names are BAD ideas and should be avoided.

As a side note, I always found it annoying to use “feature/123” instead of “features/123“. Just like in REST APIs, the slash brings to mind a collection or a file system directory, both of which should be pluralized.

I like fix/ refact/ feat/ special/ docs/ as pre-fixes and would not like to pluralise any of them.

Why do you like these prefixes? Honest question.

My thoughts are: They don't really add any value to the branch nor do they inform the developer. Identifying a bug fix, a new feature, or a document branch doesn't change the way you treat the branch in any way, nor would it necessarily prioritize the branch.

If you are drowning branches (like dozens or hundreds) and need to categorize them like this, it's somewhat a "code smell" reflecting the development process. Having too many things open and not closing them is not the greatest strategy.

Anyway, honestly interested in your opinion and why you find those prefixes useful. They seem to me to be some holdout from early blog postings recommending this approach, but turn out to not really add any value.

Agree with you. Branches are branches, they have code. That's it.

We review tickets / pull requests. Tickets should already be prioritized, be tagged as task/improvement/fix, and pull requests are displayed in order of creation. No need to worry about branch names. Just use either the ticket code, or the title (or code-title)

I used to be a big fan of conventional branches and commits (feat, fix, etc.), but realistically after a few years this scheme has never been useful once. It just wastes precious characters in commit messages.

ITYM "doc", since "docs" is already pluralised...

gitlab is already doing this. The default branch name when you click `Create Merge Request` is issue_id-issue_title, like "477-update-readme-md"

There's lots of suggestions floating around that are answered with "Gitlab has been doing this for a while".

Yep, and the default is now to both create a branch and a merge request https://www.dropbox.com/s/hgcwyifxkc6jrxh/Screenshot%202020-...

I like throw an alias and date stamp in their too:

as it makes cleaning up old branches (both local and remote) just a little bit easier. Author left the team? Delete. Untouched from 6 months back? Delete.

> it makes cleaning up old branches (both local and remote) just a little bit easier

Slightly different from what you are referring to, but I have the following aliases that are super useful for cleaning up dead branches locally. They make running `git branch` actually return a reasonable list of branches rather than every branch I ever checked out in the past eight years.

   listdead = "!sh -c \"git branch -vv | grep ': gone]' | awk '{print \\$1}'\""
   prunedead = "!sh -c \"git branch -vv | grep ': gone]' | awk '{print \\$1}' | xargs git branch -D\""

So I will run `git listdead` after I merge something and pull the latest `master`. Then it will usually show the branches that I have merged recently.

Then I run `git prunedead` and it goes through and actually deletes them.

I've never run into a case where branches I didn't want removed were in the dead list, but I usually run `listdead` first just in case.

I think I swiped these from a StackOverflow answer at some point. Don't remember.

My approach:

    refage = ! git for-each-ref --format='%(committerdate:relative),%(authorname),%(refname)' --sort -committerdate | column -t -s ','
This will list all refs (including tags, so you might want to grep the output), their relative ages, and who the last commit author was, and then formats it nicely. This makes it easy to see how many branches there and how old they are, as well as who to contact to request deletion.

The above line is a git alias. I failed to mentioned that.

git-gone does this as well, works cross platform.


Do you need to compile and install it from source? I couldn't find it on homebrew

I am a fan of the alias as well.

I'm not a huge fan of the timestamp as it makes viewing a list of branches a little noisy. I think instead you can use this[0] solution to delete branches older than X days.

[0] https://stackoverflow.com/a/10325758

I find it simpler to always list my branches sorted by last commit date (with `git for-each-ref --count=30 --sort=-committerdate refs/heads/ --format='%(refname:short)'`). You can probably modify it to show the last author / date too.

> cleaning up old branches

For remote, you should just delete when you merge OR, when doing the cleanup, delete the old and merged branches.

For local, just remove branches that are not on remote anymore

Personally I like the `ft/...` format using "/" for divider. However, it does not play with other software especially when the url is involved (e.g. the branch name collides with url path). This issue fits loosely similar problem to file naming to avoid problems (e.g. avoid " " (space), "-" (dash), or use of any weird characters as part of filename. This is the reason why you may find a lot of files named with "_" (underscore), especially in place of a space.

This raises the question of using "-" or "_" for divider. Keep in mind there are words that may have "-" (e.g "self-expression"). And as far as I know there are no words that have "_".

In summary: And so I have decided on using "_" as my divider and plays well with other integrated tooling for future robustness.

A bit late to the party but I'm going to suggest something entirely different.

At my shop we often use a setup comprising simply of a develop branch, a staging (test) branch, and of course master (as the live productive branch), and we have build processes for both staging and master, which may differ slightly based on the test vs. live environment.

We only use separate branches for possible new breaking features that could cause hold ups in this chain. Otherwise, the work flow is develop on develop (obviously :) ), test on staging, and merge to master once all tests pass.

Indeed, we're a small shop, but I can't help but recommend having these three key branches. Even at a larger organization I could see this working, only maybe having more separate feature branches as branched off from the develop branch.

Do you do code reviews on committing to develop? Other companies/organizations generally have develop for work in between releases and merge into develop from feature/bug fix branches (primarily owned by one individual) with pull requests. The PR provides an opportunity for team code review and feedback before merging into the shared develop branch. That also allows developers to commit and push unfinished work to their own branches, so that it is backed up on their remote repository rather than just their own laptop. Otherwise if they pushed straight to develop, they'd constantly be breaking that shared branch with non-functional, partially complete code.

> For example, there could be multiple branches needed to work on one issue, possibly by different people.

I would say that in a case like this, probably you need to break that issue into smaller tasks? Otherwise, how you keep track if the ticket is ready for review, which parts are completed, etc?

I like the <feature/featurename> naming scheme because in some Git software (at least in Visual Studio) all of the branches starting with <feature/> will show up in a collapsable folder named feature in the interface.

My team found slashes to be annoying though, they are illegal in docker tag and DNS names. Tagging images with branch names and creating instances with branch as subdomain is kinda convenient.

I do the same, and this seems to work in a lot of UIs for grouping git branches, with Azure DevOps being another off the top of my head.

I usually use "feat/my-branch" or "fix/my-branch" depending on the purpose of the branch.

That's one of the reasons I like it too. feature/ticketid-short-description makes it super easy to determine what the branch is for and what originated it as well as keeps it organized in most Git GUI clients

underscores or GTFO, so you can double-click to select the full branch name!

we also tend to prepend with our initials just in case someone else also has a branch related to that issue and they give it a similar descriptive slug

I like to separate the issue tracker number from the rest of the branch name using a / where the rest is separated by either a - or _

That allows easy ticket number extract using grep.

Another tip to add to point 2: keep the scope of each branch limited so that the resulting name can be short. E.g. a branch with feature1, feature2, and fix3 should be 3 separate branches. Combining too many things into one branch is a common mistake, and a side-effect is that it's impossible to come up with a short name for the branch.

I use the same convention but whatever you do, be consistent even if you don't intend to push a branch to a remote.

Good advice. I usually like to put the ticket number at the end just because it makes autocomplete a little easier.

Wait, are you telling me that

    git branch -b ohnowhathaveidone
isn't right??

That's correct. It should be

    git checkout -b ohnowhathaveidone

Oh no, right you are.

Describining the likely outcome AS the branch name doesn't really make sense ... particularly considering how often that outcome / branch name happens for some of us.

it's fine for your local development, probably want to rename it or incorporate the changes into it's parent branch that is named more usefully for pushing it somewhere shared

if you need a branch naming scheme, then you probably have too many public branches.

Everyone that uses branches regularly probably has a naming convention they use. This is just an article saying how the author does theirs. It seems reasonable to me.

I usually just do names like `dev/short_description`, but that is still a naming convention.

Sure, I have a branch naming scheme for my repos. But nobody else has to know it because those branches don't leave my system. Branches published waiting for code review are shortlived enough even if someone notices the branch name in the review tool, they're likely not going to use it for anything.

Unless there are many long-lived, public, collaborative branches there's little need for careful and deliberate naming convention across a team. And if you have enough of those kind of branches, I contend that you're not merging enough.

From painful experience, I can say that leaving a branch that lasts longer than a day only on your machine is begging to lose work.

Unless your machine is automatically backed up every hour, in which case ignore me.

That has not been the case in most of my jobs, but pushing my WIP branch to a remote every hour or two achieves that goal in practice (as long as I don't have anything important that's not in a repo).

Branches have names regardless of if they're public or not. Every branch name was determined somehow and having shared conventions for that somehow can enable better tooling, developer interoperation, and even just personal organization.

After say 3 branches ... I would kind of like to know what they do, even just for myself.

If this can make HN, here's my news item:

"Walking conventions:

1. Stand.

2. Move right foot ahead.

3. Move left foot to match.

That's it. You can also do it the other way around, but be consistent."

Applications are open for YC Winter 2022

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact