diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 19d688c4bb89e29769b9a93add88ad9dba24eaec..add0fef512e672a2c8db04cbf948a69f906e7501 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -7,7 +7,7 @@ module LabelsHelper
     label_color = label.color || Label::DEFAULT_COLOR
     text_color = text_color_for_bg(label_color)
 
-    content_tag :span, class: 'label color-label', style: "background:#{label_color};color:#{text_color}" do
+    content_tag :span, class: 'label color-label', style: "background-color:#{label_color};color:#{text_color}" do
       label.name
     end
   end
diff --git a/app/models/note.rb b/app/models/note.rb
index 39fe421fd7a761202f02c8c0eb62ba2e6c13b1d9..ccd9783e7d4dc7efafc1d8e8b7e5322fb9acb665 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -121,6 +121,36 @@ class Note < ActiveRecord::Base
       })
     end
 
+    def create_labels_change_note(noteable, project, author, added_labels, removed_labels)
+      labels_count = added_labels.count + removed_labels.count
+      added_labels = added_labels.map{ |label| "~#{label.id}" }.join(' ')
+      removed_labels = removed_labels.map{ |label| "~#{label.id}" }.join(' ')
+      message = ''
+
+      if added_labels.present?
+        message << "added #{added_labels}"
+      end
+
+      if added_labels.present? && removed_labels.present?
+        message << ' and '
+      end
+
+      if removed_labels.present?
+        message << "removed #{removed_labels}"
+      end
+
+      message << ' ' << 'label'.pluralize(labels_count)
+      body = "_#{message.capitalize}_"
+
+      create(
+        noteable: noteable,
+        project: project,
+        author: author,
+        note: body,
+        system: true
+      )
+    end
+
     def create_new_commits_note(noteable, project, author, commits)
       commits_text = ActionController::Base.helpers.pluralize(commits.size, 'new commit')
       body = "Added #{commits_text}:\n\n"
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index e3371ec3c1b7c60bd11970052cd627e8021bbbc7..5e1906ad2aec637beca13b6a00b794fd2d7c7eaf 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -10,4 +10,9 @@ class IssuableBaseService < BaseService
     Note.create_milestone_change_note(
       issuable, issuable.project, current_user, issuable.milestone)
   end
+
+  def create_labels_note(issuable, added_labels, removed_labels)
+    Note.create_labels_change_note(
+      issuable, issuable.project, current_user, added_labels, removed_labels)
+  end
 end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 83e413d72480ba2636c4ac1d795fe2e8bd98f42f..c61d67a789354908e601da38cfa8ef489e4f4497 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -14,10 +14,17 @@ module Issues
         issue.update_nth_task(params[:task_num].to_i, false)
       end
 
+      old_labels = issue.labels.to_a
+
       if params.present? && issue.update_attributes(params.except(:state_event,
                                                                   :task_num))
         issue.reset_events_cache
 
+        if issue.labels != old_labels
+          create_labels_note(
+            issue, issue.labels - old_labels, old_labels - issue.labels)
+        end
+
         if issue.previous_changes.include?('milestone_id')
           create_milestone_note(issue)
         end
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 10c401756ebbd5dfe482f24e858c02b627d641a8..870b50bb60dac9262dcae81cb33a98c9e0e8df6c 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -23,11 +23,21 @@ module MergeRequests
         merge_request.update_nth_task(params[:task_num].to_i, false)
       end
 
+      old_labels = merge_request.labels.to_a
+
       if params.present? && merge_request.update_attributes(
         params.except(:state_event, :task_num)
       )
         merge_request.reset_events_cache
 
+        if merge_request.labels != old_labels
+          create_labels_note(
+            merge_request,
+            merge_request.labels - old_labels,
+            old_labels - merge_request.labels
+          )
+        end
+
         if merge_request.previous_changes.include?('milestone_id')
           create_milestone_note(merge_request)
         end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 78627f413c2971a0ab604c823535552452973678..fb0218a2778b069c256ae6fefd1ca17f62cbd0dc 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -92,7 +92,7 @@ module Gitlab
       allowed_tags = ActionView::Base.sanitized_allowed_tags
 
       sanitize text.html_safe,
-               attributes: allowed_attributes + %w(id class),
+               attributes: allowed_attributes + %w(id class style),
                tags: allowed_tags + %w(table tr td th)
     end
 
@@ -128,6 +128,7 @@ module Gitlab
       (?<prefix>\W)?                         # Prefix
       (                                      # Reference
          @(?<user>#{NAME_STR})               # User name
+        |~(?<label>\d+)                      # Label ID
         |(?<issue>([A-Z\-]+-)\d+)            # JIRA Issue ID
         |#{PROJ_STR}?\#(?<issue>([a-zA-Z\-]+-)?\d+) # Issue ID
         |#{PROJ_STR}?!(?<merge_request>\d+)  # MR ID
@@ -138,7 +139,7 @@ module Gitlab
       (?<suffix>\W)?                         # Suffix
     }x.freeze
 
-    TYPES = [:user, :issue, :merge_request, :snippet, :commit].freeze
+    TYPES = [:user, :issue, :label, :merge_request, :snippet, :commit].freeze
 
     def parse_references(text, project = @project)
       # parse reference links
@@ -214,6 +215,19 @@ module Gitlab
       end
     end
 
+    def reference_label(identifier, project = @project, _ = nil)
+      if label = project.labels.find_by(id: identifier)
+        options = html_options.merge(
+          class: "gfm gfm-label #{html_options[:class]}"
+        )
+        link_to(
+          render_colored_label(label),
+          project_issues_path(project, label_name: label.name),
+          options
+        )
+      end
+    end
+
     def reference_issue(identifier, project = @project, prefix_text = nil)
       if project.default_issues_tracker?
         if project.issue_exists? identifier
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 99165950aef447e8cca812727513ae7a653c6928..0b9177afa4ff9ca4570e53f3de7eb7bcc7b5f925 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -1,12 +1,13 @@
 module Gitlab
   # Extract possible GFM references from an arbitrary String for further processing.
   class ReferenceExtractor
-    attr_accessor :users, :issues, :merge_requests, :snippets, :commits
+    attr_accessor :users, :labels, :issues, :merge_requests, :snippets, :commits
 
     include Markdown
 
     def initialize
-      @users, @issues, @merge_requests, @snippets, @commits = [], [], [], [], []
+      @users, @labels, @issues, @merge_requests, @snippets, @commits =
+        [], [], [], [], [], []
     end
 
     def analyze(string, project)
@@ -22,6 +23,12 @@ module Gitlab
       end.reject(&:nil?)
     end
 
+    def labels_for(project = nil)
+      labels.map do |entry|
+        project.labels.where(id: entry[:id]).first
+      end.reject(&:nil?)
+    end
+
     def issues_for(project = nil)
       issues.map do |entry|
         if should_lookup?(project, entry[:project])
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 360305778359862714faee41eeac2dbbfcc9ce49..964b3a707e4e026a836be38a53805df76d87a140 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -5,6 +5,7 @@ describe Issues::UpdateService do
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let(:issue) { create(:issue) }
+  let(:label) { create(:label) }
 
   before do
     project.team << [user, :master]
@@ -18,7 +19,8 @@ describe Issues::UpdateService do
           title: 'New title',
           description: 'Also please fix',
           assignee_id: user2.id,
-          state_event: 'close'
+          state_event: 'close',
+          label_ids: [label.id]
         }
 
         @issue = Issues::UpdateService.new(project, user, opts).execute(issue)
@@ -29,6 +31,8 @@ describe Issues::UpdateService do
       it { @issue.title.should == 'New title' }
       it { @issue.assignee.should == user2 }
       it { @issue.should be_closed }
+      it { @issue.labels.count.should == 1 }
+      it { @issue.labels.first.title.should == 'Bug' }
 
       it 'should send email to user2 about assign of new issue' do
         email = ActionMailer::Base.deliveries.last
@@ -40,6 +44,11 @@ describe Issues::UpdateService do
         note = @issue.notes.last
         note.note.should include "Reassigned to \@#{user2.username}"
       end
+
+      it 'should create system note about issue label edit' do
+        note = @issue.notes[1]
+        note.note.should include "Added ~#{label.id} label"
+      end
     end
   end
 end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 0e60baae2c431f473792e5832d1b2a242d946528..b27acb4771183a6d69258704f4d075bd0f18514f 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -5,6 +5,7 @@ describe MergeRequests::UpdateService do
   let(:user2) { create(:user) }
   let(:merge_request) { create(:merge_request, :simple) }
   let(:project) { merge_request.project }
+  let(:label) { create(:label) }
 
   before do
     project.team << [user, :master]
@@ -18,7 +19,8 @@ describe MergeRequests::UpdateService do
           title: 'New title',
           description: 'Also please fix',
           assignee_id: user2.id,
-          state_event: 'close'
+          state_event: 'close',
+          label_ids: [label.id]
         }
       end
 
@@ -35,6 +37,8 @@ describe MergeRequests::UpdateService do
       it { @merge_request.title.should == 'New title' }
       it { @merge_request.assignee.should == user2 }
       it { @merge_request.should be_closed }
+      it { @merge_request.labels.count.should == 1 }
+      it { @merge_request.labels.first.title.should == 'Bug' }
 
       it 'should execute hooks with update action' do
         expect(service).to have_received(:execute_hooks).
@@ -51,6 +55,11 @@ describe MergeRequests::UpdateService do
         note = @merge_request.notes.last
         note.note.should include "Reassigned to \@#{user2.username}"
       end
+
+      it 'should create system note about merge_request label edit' do
+        note = @merge_request.notes[1]
+        note.note.should include "Added ~#{label.id} label"
+      end
     end
   end
 end