diff --git a/addon/merge/merge.css b/addon/merge/merge.css
index 5d24b9bb7fc68d62df4bdae65b07468d03a8f4dd..a6a80e43e075a5e98d4171350e1b3973c53b0a65 100644
--- a/addon/merge/merge.css
+++ b/addon/merge/merge.css
@@ -96,3 +96,17 @@
 .CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
 .CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
 .CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
+
+.CodeMirror-merge-collapsed-widget:before {
+  content: "(...)";
+}
+.CodeMirror-merge-collapsed-widget {
+  cursor: pointer;
+  color: #88b;
+  background: #eef;
+  border: 1px solid #ddf;
+  font-size: 90%;
+  padding: 0 3px;
+  border-radius: 4px;
+}
+.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
diff --git a/addon/merge/merge.js b/addon/merge/merge.js
index 14d06903fe61164f017ec39ecd72837c5cdbde8f..ed22b60024a6988125cab5761a2353d7b5a0fbc6 100644
--- a/addon/merge/merge.js
+++ b/addon/merge/merge.js
@@ -368,8 +368,12 @@
 
     this.options = options;
     var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
-    if (origLeft && origRight && options.connect == "align")
-      throw new Error("connect: \"align\" is not supported for three-way merge views");
+    if (origLeft && origRight) {
+      if (options.connect == "align")
+        throw new Error("connect: \"align\" is not supported for three-way merge views");
+      if (options.collapseIdentical)
+        throw new Error("collapseIdentical option is not supported for three-way merge views");
+    }
 
     var hasLeft = origLeft != null, hasRight = origRight != null;
     var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
@@ -402,6 +406,9 @@
     if (left) left.init(leftPane, origLeft, options);
     if (right) right.init(rightPane, origRight, options);
 
+    if (options.collapseIdentical)
+      collapseIdenticalStretches(left || right, options.collapseIdentical);
+
     var onResize = function() {
       if (left) makeConnections(left);
       if (right) makeConnections(right);
@@ -549,6 +556,46 @@
     return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
   }
 
+  function collapseSingle(cm, from, to) {
+    cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
+    var widget = document.createElement("span");
+    widget.className = "CodeMirror-merge-collapsed-widget";
+    widget.title = "Identical text collapsed. Click to expand.";
+    var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
+      inclusiveLeft: true,
+      inclusiveRight: true,
+      replacedWith: widget,
+      clearOnEnter: true
+    });
+    function clear() {
+      mark.clear();
+      cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
+    }
+    widget.addEventListener("click", clear);
+    return {mark: mark, clear: clear};
+  }
+
+  function collapseStretch(dv, origStart, editStart, size) {
+    var mOrig = collapseSingle(dv.orig, origStart, origStart + size);
+    var mEdit = collapseSingle(dv.edit, editStart, editStart + size);
+    mOrig.mark.on("clear", function() { mEdit.clear(); });
+    mEdit.mark.on("clear", function() { mOrig.clear(); });
+  }
+
+  function collapseIdenticalStretches(dv, margin) {
+    if (typeof margin != "number") margin = 2;
+    var lastOrig = dv.orig.firstLine(), lastEdit = dv.edit.firstLine();
+    iterateChunks(dv.diff, function(topOrig, botOrig, _topEdit, botEdit) {
+      var identicalSize = topOrig - margin - lastOrig;
+      if (identicalSize > margin)
+        collapseStretch(dv, lastOrig, lastEdit, identicalSize);
+      lastOrig = botOrig + margin; lastEdit = botEdit + margin;
+    });
+    var bottomSize = dv.orig.lastLine() + 1 - lastOrig;
+    if (bottomSize > margin)
+      collapseStretch(dv, lastOrig, lastEdit, bottomSize);
+  }
+
   // General utilities
 
   function elt(tag, content, className, style) {