 						change.op.p += op_length
 						moved_changes.push change
 					else if op_start == change_start
-						# If the insert matches the start of the delete, just remove it from the delete instead
-						if change.op.d.length >= op.i.length and change.op.d.slice(0, op.i.length) == op.i
+						# If we are undoing, then we want to cancel any existing delete ranges if we can.
+						# Check if the insert matches the start of the delete, and just remove it from the delete instead if so.
+						if undoing and change.op.d.length >= op.i.length and change.op.d.slice(0, op.i.length) == op.i
 							change.op.d = change.op.d.slice(op.i.length)
 							change.op.p += op.i.length
 							if change.op.d == ""

					@_removeChange change
					moved_changes = moved_changes.filter (c) -> c != change
			
			if moved_changes.length > 0
				@emit "changes:moved", moved_changes

		_addOp: (op, metadata) ->
			change = {

					t: op.t
				metadata
			}
			@_markAsDirty comment, "comment", "added"
			return comment
		
		applyInsertToComments: (op) ->
			for comment in @comments
				if op.p <= comment.op.p
					comment.op.p += op.i.length
					@_markAsDirty comment, "comment", "moved"
				else if op.p < comment.op.p + comment.op.c.length
					offset = op.p - comment.op.p
					comment.op.c = comment.op.c[0..(offset-1)] + op.i + comment.op.c[offset...]
					@_markAsDirty comment, "comment", "moved"

		applyDeleteToComments: (op) ->
			op_start = op.p
