diff --git a/models/repo.go b/models/repo.go
index 7944149a76..860c5c4813 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -146,6 +146,7 @@ const (
 	RepositoryReady           RepositoryStatus = iota // a normal repository
 	RepositoryBeingMigrated                           // repository is migrating
 	RepositoryPendingTransfer                         // repository pending in ownership transfer state
+	RepositoryBroken                                  // repository is in a permanently broken state
 )
 
 // TrustModelType defines the types of trust model for this repository
@@ -289,6 +290,11 @@ func (repo *Repository) IsBeingCreated() bool {
 	return repo.IsBeingMigrated()
 }
 
+// IsBroken indicates that repository is broken
+func (repo *Repository) IsBroken() bool {
+	return repo.Status == RepositoryBroken
+}
+
 // AfterLoad is invoked from XORM after setting the values of all fields of this object.
 func (repo *Repository) AfterLoad() {
 	// FIXME: use models migration to solve all at once.
diff --git a/modules/context/repo.go b/modules/context/repo.go
index c96d34f2fc..1f1a035267 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -522,14 +522,30 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 		}
 	}
 
+	isHomeOrSettings := ctx.Link == ctx.Repo.RepoLink || ctx.Link == ctx.Repo.RepoLink+"/settings" || strings.HasPrefix(ctx.Link, ctx.Repo.RepoLink+"/settings/")
+
 	// Disable everything when the repo is being created
-	if ctx.Repo.Repository.IsBeingCreated() {
+	if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() {
 		ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
+		if !isHomeOrSettings {
+			ctx.Redirect(ctx.Repo.RepoLink)
+		}
 		return
 	}
 
 	gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
 	if err != nil {
+		if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") {
+			log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
+			ctx.Repo.Repository.Status = models.RepositoryBroken
+			ctx.Repo.Repository.IsEmpty = true
+			ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
+			// Only allow access to base of repo or settings
+			if !isHomeOrSettings {
+				ctx.Redirect(ctx.Repo.RepoLink)
+			}
+			return
+		}
 		ctx.ServerError("RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
 		return
 	}
@@ -551,6 +567,17 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 
 	tags, err := ctx.Repo.GitRepo.GetTags(0, 0)
 	if err != nil {
+		if strings.Contains(err.Error(), "fatal: not a git repository ") {
+			log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
+			ctx.Repo.Repository.Status = models.RepositoryBroken
+			ctx.Repo.Repository.IsEmpty = true
+			ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
+			// Only allow access to base of repo or settings
+			if !isHomeOrSettings {
+				ctx.Redirect(ctx.Repo.RepoLink)
+			}
+			return
+		}
 		ctx.ServerError("GetTags", err)
 		return
 	}
@@ -919,6 +946,11 @@ func UnitTypes() func(ctx *Context) {
 // IssueTemplatesFromDefaultBranch checks for issue templates in the repo's default branch
 func (ctx *Context) IssueTemplatesFromDefaultBranch() []api.IssueTemplate {
 	var issueTemplates []api.IssueTemplate
+
+	if ctx.Repo.Repository.IsEmpty {
+		return issueTemplates
+	}
+
 	if ctx.Repo.Commit == nil {
 		var err error
 		ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 6e39b4b03d..ca6cd66625 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -946,6 +946,7 @@ clone_this_repo = Clone this repository
 create_new_repo_command = Creating a new repository on the command line
 push_exist_repo = Pushing an existing repository from the command line
 empty_message = This repository does not contain any content.
+broken_message = The git data underlying this repository cannot be read. Contact the administrator of this instance or delete this repository.
 
 code = Code
 code.desc = Access source code, files, commits and branches.
diff --git a/routers/private/serv.go b/routers/private/serv.go
index a7ef980d2d..329d80476a 100644
--- a/routers/private/serv.go
+++ b/routers/private/serv.go
@@ -162,6 +162,14 @@ func ServCommand(ctx *context.PrivateContext) {
 			return
 		}
 
+		if repo.IsBroken() {
+			ctx.JSON(http.StatusInternalServerError, private.ErrServCommand{
+				Results: results,
+				Err:     "Repository is in a broken state",
+			})
+			return
+		}
+
 		// We can shortcut at this point if the repo is a mirror
 		if mode > models.AccessModeRead && repo.IsMirror {
 			ctx.JSON(http.StatusForbidden, private.ErrServCommand{
diff --git a/templates/repo/empty.tmpl b/templates/repo/empty.tmpl
index 20563f59e6..6da9e28e16 100644
--- a/templates/repo/empty.tmpl
+++ b/templates/repo/empty.tmpl
@@ -10,7 +10,11 @@
 						{{.i18n.Tr "repo.archive.title"}}
 					</div>
 				{{end}}
-				{{if .CanWriteCode}}
+				{{if .Repository.IsBroken}}
+						<div class="ui segment center">
+							{{.i18n.Tr "repo.broken_message"}}
+						</div>
+				{{else if .CanWriteCode}}
 					<h4 class="ui top attached header">
 						{{.i18n.Tr "repo.quick_guide"}}
 					</h4>
diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl
index 554456d230..4fb5e1941b 100644
--- a/templates/repo/header.tmpl
+++ b/templates/repo/header.tmpl
@@ -40,7 +40,7 @@
 				{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{.BaseRepo.FullName}}</a></div>{{end}}
 				{{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{.TemplateRepo.FullName}}</a></div>{{end}}
 			</div>
-			{{if not .IsBeingCreated}}
+			{{if not (or .IsBeingCreated .IsBroken)}}
 				<div class="repo-buttons">
 					{{if $.RepoTransfer}}
 						<form method="post" action="{{$.RepoLink}}/action/accept_transfer?redirect_to={{$.RepoLink}}">
@@ -100,7 +100,7 @@
 	</div><!-- end container -->
 {{end}}
 	<div class="ui tabs container">
-		{{if not .Repository.IsBeingCreated}}
+		{{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}}
 			<div class="ui tabular stackable menu navbar">
 				{{if .Permission.CanRead $.UnitTypeCode}}
 				<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}">
@@ -172,6 +172,14 @@
 					</div>
 				{{end}}
 			</div>
+		{{else if .Permission.IsAdmin}}
+			<div class="ui tabular stackable menu navbar">
+				<div class="right menu">
+					<a class="{{if .PageIsSettings}}active{{end}} item" href="{{.RepoLink}}/settings">
+						{{svg "octicon-tools"}} {{.i18n.Tr "repo.settings"}}
+					</a>
+				</div>
+			</div>
 		{{end}}
 	</div>
 	<div class="ui tabs divider"></div>