diff --git a/models/db/search.go b/models/db/search.go
index 26e082756..105cb64c4 100644
--- a/models/db/search.go
+++ b/models/db/search.go
@@ -31,5 +31,5 @@ const (
 const (
 	// Which means a condition to filter the records which don't match any id.
 	// It's different from zero which means the condition could be ignored.
-	NoneID = -1
+	NoConditionID = -1
 )
diff --git a/models/issues/issue.go b/models/issues/issue.go
index c8d148dd8..2dae8848c 100644
--- a/models/issues/issue.go
+++ b/models/issues/issue.go
@@ -1266,7 +1266,9 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) {
 		applySubscribedCondition(sess, opts.SubscriberID)
 	}
 
-	if len(opts.MilestoneIDs) > 0 {
+	if len(opts.MilestoneIDs) == 1 && opts.MilestoneIDs[0] == db.NoConditionID {
+		sess.And("issue.milestone_id = 0")
+	} else if len(opts.MilestoneIDs) > 0 {
 		sess.In("issue.milestone_id", opts.MilestoneIDs)
 	}
 
@@ -1280,7 +1282,7 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) {
 	if opts.ProjectID > 0 {
 		sess.Join("INNER", "project_issue", "issue.id = project_issue.issue_id").
 			And("project_issue.project_id=?", opts.ProjectID)
-	} else if opts.ProjectID == db.NoneID { // show those that are in no project
+	} else if opts.ProjectID == db.NoConditionID { // show those that are in no project
 		sess.And(builder.NotIn("issue.id", builder.Select("issue_id").From("project_issue")))
 	}
 
@@ -1680,6 +1682,8 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats,
 
 		if opts.MilestoneID > 0 {
 			sess.And("issue.milestone_id = ?", opts.MilestoneID)
+		} else if opts.MilestoneID == db.NoConditionID {
+			sess.And("issue.milestone_id = 0")
 		}
 
 		if opts.ProjectID > 0 {
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 5154aadb6..8169cba10 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -1310,7 +1310,10 @@ issues.filter_label = Label
 issues.filter_label_exclude = `Use alt + click/enter to exclude labels`
 issues.filter_label_no_select = All labels
 issues.filter_milestone = Milestone
-issues.filter_milestone_no_select = All milestones
+issues.filter_milestone_all = All milestones
+issues.filter_milestone_none = No milestones
+issues.filter_milestone_open = Open milestones
+issues.filter_milestone_closed = Closed milestones
 issues.filter_project = Project
 issues.filter_project_all = All projects
 issues.filter_project_none = No project
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index 3868e895f..4f370c610 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -237,7 +237,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
 	pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
 
 	var mileIDs []int64
-	if milestoneID > 0 {
+	if milestoneID > 0 || milestoneID == db.NoConditionID { // -1 to get those issues which have no any milestone assigned
 		mileIDs = []int64{milestoneID}
 	}
 
@@ -438,14 +438,8 @@ func Issues(ctx *context.Context) {
 		return
 	}
 
-	var err error
-	// Get milestones
-	ctx.Data["Milestones"], _, err = issues_model.GetMilestones(issues_model.GetMilestonesOption{
-		RepoID: ctx.Repo.Repository.ID,
-		State:  api.StateType(ctx.FormString("state")),
-	})
-	if err != nil {
-		ctx.ServerError("GetAllRepoMilestones", err)
+	renderMilestones(ctx)
+	if ctx.Written() {
 		return
 	}
 
@@ -454,6 +448,29 @@ func Issues(ctx *context.Context) {
 	ctx.HTML(http.StatusOK, tplIssues)
 }
 
+func renderMilestones(ctx *context.Context) {
+	// Get milestones
+	milestones, _, err := issues_model.GetMilestones(issues_model.GetMilestonesOption{
+		RepoID: ctx.Repo.Repository.ID,
+		State:  api.StateAll,
+	})
+	if err != nil {
+		ctx.ServerError("GetAllRepoMilestones", err)
+		return
+	}
+
+	openMilestones, closedMilestones := issues_model.MilestoneList{}, issues_model.MilestoneList{}
+	for _, milestone := range milestones {
+		if milestone.IsClosed {
+			closedMilestones = append(closedMilestones, milestone)
+		} else {
+			openMilestones = append(openMilestones, milestone)
+		}
+	}
+	ctx.Data["OpenMilestones"] = openMilestones
+	ctx.Data["ClosedMilestones"] = closedMilestones
+}
+
 // RetrieveRepoMilestonesAndAssignees find all the milestones and assignees of a repository
 func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.Repository) {
 	var err error
diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl
index ddc197a88..a59480109 100644
--- a/templates/repo/issue/list.tmpl
+++ b/templates/repo/issue/list.tmpl
@@ -63,7 +63,7 @@
 					
 
 					
-