327

Suppose we have an application that's stable.

Tomorrow, someone reports a big ol' bug that we decide to hotfix right away. So we create a branch for that hotfix off of "master", we name it "2011_Hotfix", and we push it up so that all of the developers can collaborate on fixing it.

We fix the bug, and merge "2011_Hotfix" into "master" as well as into the current development branch. And push "master."

What do we do with "2011_Hotfix" now? Should it just sit out there as a branch forever until the end of time or should we now delete it, since it has served its purpose? It seems unclean to just leave branches lying around everywhere, as the list of branches will likely become very long, most of which aren't even necessary anymore.

In the event that it should be deleted, what will happen to its history? Will that be maintained, even though the actual branch is no longer available? Also, how would I remove a remote branch?

Anthony Compton
  • 5,271
  • 3
  • 29
  • 38
  • 40
    It often helps to think of branches as ideas. A fairly good rule of thumb is that if you're done working on the ideas that the branch represents - including done testing and incorporating those changes (merging them into master) - you're done with the branch itself. – Cascabel Mar 17 '11 at 04:30
  • 3
    What I'd like to know: if the remote hotfix is being removed, will it be removed locally for all the developers that collaborated? If not; how to accomplish this? I'd think one person migrates the hotfix to master, but after that it should be cleaned for all collaborators as well, to prevent them to add commits to that branch. – rolandow Dec 22 '15 at 10:17
  • 1
    You cannot affect the local repositories of your co-workers computers. You either have to tell him to delete the branch locally or you can also enforce this server side with git hooks/branch security to prevent pushes from your branch which you want to keep deleted – srz2 Feb 12 '16 at 15:10

8 Answers8

207

You can safely remove a branch with git branch -d yourbranch. If it contains unmerged changes (ie, you would lose commits by deleting the branch), git will tell you and won't delete it.

So, deleting a merged branch is cheap and won't make you lose any history.

To delete a remote branch, use git push origin :mybranch, assuming your remote name is origin and the remote branch you want do delete is named mybranch.

Artefact2
  • 7,516
  • 3
  • 30
  • 38
  • 44
    "deleting a merged branch is cheap" but so is keeping it around. There is no significant performance hit in terms of the time or space git uses, if you keep it around. That said, I would delete the branch because all the commits are already there in the history of `master`, so it does make things much cleaner. – Tyler Mar 17 '11 at 03:37
  • 26
    One of my reasons to wanting to delete branches is:We do a lot of changes in branches (actually, all changes) so eventually you get a long list when using the command 'git branch'. For the overview, I want to shorten that list. So old branches will be deleted. Reale releases are tagged, so are not in this disussion for me. – michel.iamit May 21 '14 at 06:59
  • 10
    While I agree with deleting branches which have already been merged, if you want to see a list of branches which haven't been merged into your current branch you can use: git branch --no-merged – lsklyut Sep 29 '14 at 13:54
  • 70
    @MatrixFrog It's cheap to keep around in terms of git, however in the human cost can become expensive. I just entered a project with about 40 branches, all with numeric branch names. I have no idea what is what, and almost every one of those branches is stale. The overhead of searching through those branches and figuring out what is what is tiring and takes time. So yeah, technically it's cheap, but it's really not. I like to keep my git repo ship shape. If it's not in active dev and has been merged in, delete it. But that's just my MO and I respect that others might do something different. – dudewad Feb 02 '15 at 19:55
  • 1
    What is the command to make `--no-merged` the default? I tried `git config --global --add branch.noMerged true` and it was added but it didn't make any difference. – Craig Silver Nov 13 '16 at 19:01
  • 1
    @CraigSilver one option: `git config --global alias.unmerged 'branch --no-merged'` – user151841 May 17 '17 at 19:55
64

What you need to do is tag anything that you release. Keep branches around for when you are actively developing.

Delete old branches with

git branch -d branch_name

Delete them from the server with

git push origin --delete branch_name

or the old syntax

git push origin :branch_name

which reads as "push nothing into branch_name at origin".

That said, as long as the DAG (directed acyclic graph) can point to it, the commits will be there in history.

Google "git-flow" and that may give some more insight on release management, branching and tagging.

Adam Dymitruk
  • 124,556
  • 26
  • 146
  • 141
34

Since the question has the "github" tag, I'd also add this: specifically in Github, if you pull-request a branch and it gets merged (either via the UI or by merging the pull request's branch), you won't lose the pull request data (including comments), even if you remove the branch.

A consequence of this: If you incorporate pull requests as a part of your workflow (which blends sweetly with code reviews), you can safely delete branches as soon as they get merged. This is so commonplace that recently Github added a (sweet) feature that pops a "delete branch" button right after you merge a pull request.

But it is worth noticing that each group should adopt the workflow that suits it best (and it may or may not lead to deleting such branches). My current work team, for example, prunes all branches that are not master or deployment-related (e.g., production, staging, etc.) as soon as their pull requests gets merged, and we still have full tracking of how the related commits formed each incremental improvement of each product.

Of course no history management (pull requests or otherwise) replaces proper tagging of versions (which you preferably automate with the same tool/script that deploys/packages a version), so you can always fast-switch to whatever your users happen to be on at a given moment. Tagging is also the key to solve your original problem: if you establish that any branch merged to the "work" branches can and should be deleted, and that any one that is merged to a version tag, "production", etc. should not, you'll always have the hotfixes alive until they are integrated in a future version.

MrIsaacs
  • 87
  • 5
chesterbr
  • 2,940
  • 3
  • 29
  • 26
  • 2
    Thanks for explaining why Github was showing me a "Delete branch" button. – Todd Owen Jun 15 '14 at 02:56
  • We're using sourcetree and it gives option of keeping local hotfix branch and remote hotfix branch open. **I thought that closing a hotfix branch meant deleting it and you can't re-use it.** e.g. We need to push hot fixes everyday for the next 5 days. Then we close it. But let's say on 6th day, we need another hotfix. Do we create a new hotfix branch ? – Danger14 Jul 01 '15 at 16:43
  • It's what people usually do. If individually naming them is unfeasible, you could name them based on the day, or on the reference for the ticket system that manages them (if any). Of course, git workflows are supposed to be applied on a "whatever works best for your team" basis, so don't worry if you decide to work differently. – chesterbr Jul 04 '15 at 04:33
8

I would add that the disadvantage of deleting branches is that you will break any hyperlinks to those branches on GitHub (this question is tagged github). You'll get a 404 Not Found error for those links. This is why I change my links to point to a commit or tag after I delete a branch on GitHub.

Because some links can't be changed, such as in email, I now avoid hyperlinking to GitHub branches entirely and link to a commit or tag from day one.

I prefer to delete branches after they're merged in. This prevents the visual clutter of a long list of branches in your repository. These branches also get propagated to all of the repository's forks.

First I delete my local branch. This prevents it from being accidentally pushed later.

git branch -d branchName

Then I delete the remote tracking branch

git branch -dr remoteName\branchName

Then I delete the branch on GitHub. I use the web interface, but the equivalent command is below.

git push remoteName :branchName

Even if the branch is never merged, typically I would still like to keep the commits around for posterity. However I still like to delete the branch. To spread the commits around and to keep them from being eaten by the garbage collector, I make an annotated tag pointing to the same commit as the deleted branch.

git tag -a tagName commitOrBranchName

Then I push the tag to github

git push remoteName tagName
Mark F Guerra
  • 892
  • 10
  • 13
  • When does the garbage collector eat the branch's commits? Do you need to tag and push the tag before deleting the branch? – Jared Thirsk Dec 10 '18 at 23:05
  • 1
    @JaredThirsk see: [When exactly does git prune objects: why is “git gc” not removing commits?](https://stackoverflow.com/q/37733131/3258851) – Marc.2377 Nov 05 '19 at 10:17
4

It seems that you want to delete the 2011_Hotfix branch without losing its history. I will discuss deletion first and history second.

The usual git branch deletion methods have already been described above, and they work as expected. git does not have a one or two word command that means, "Hey git, delete both the local and remote branch." But this behavior can be mimicked via shell script. For example, take Zach Holman's shell script 'git-nuke'. It is very simple:

#!/bin/sh
git branch -D $1
git push origin :$1

Put this in an executable file (e.g., git-nuke) in one of your $PATH directories. If you're not on the 2011_Hotfix branch, you simply running git-nuke 2011_Hotfix will delete both the local and remote branches. This is much faster & simpler--though perhaps more dangerous--than the standard git commands.

Your concern about preserving history is a good one. In this case, you needn't be worried. Once you merge 2011_Hotfix onto master, all commits from 2011_Hotfix will be added to master's commit history. In short, you will not lose history from a simple merge.

I have one more word to add that is perhaps beyond the scope of your question, but is relevant nonetheless. Let's imagine that there are 20 tiny, "work-in-progress" commits on 2011_Hotfix; however, you want only one complete commit for 2011_Hotfix to be added to master's history. How do you combine all 20 small commits into one big commit? Fortunately, git allows you to consolidate multiple commits into one commit by using git-rebase. I won't explain here how that works; though, if you're interested, the documentation for git-rebase is excellent. Do note that git rebase rewrites history, so it should be used judiciously, especially if you are new to it. Finally, your 2011_Hotfix scenario is about a dev team, not a solo dev. If project team members use git rebase, it is wise for the team to have explicit guidelines on the use of git rebase in order that some cowboy dev on the team doesn't unwittingly damage a project's git's history.

tulians
  • 439
  • 5
  • 23
jfmercer
  • 3,641
  • 3
  • 29
  • 35
3

If it's been successfully merged back and maybe even tagged then I would say it has no use anymore. So you can safely do git branch -d branchname.

2

If you want to prune local branches that have been removed from origin, you can also prune, while using git fetch

git fetch --prune
huch
  • 675
  • 8
  • 13
0

You can delete branches in all major web UIs such as github, BitBucket. After deleting the branch online, you can delete the local branch using

git remote prune origin
tkruse
  • 10,222
  • 7
  • 53
  • 80