diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py
--- a/mercurial/mdiff.py
+++ b/mercurial/mdiff.py
@@ -180,8 +180,14 @@ def _unidiff(t1, t2, l1, l2, opts=defaul
             # the file more than once.
             lastfunc[0] = astart
 
-        yield "@@ -%d,%d +%d,%d @@%s\n" % (astart + 1, alen,
-                                           bstart + 1, blen, func)
+        # zero-length hunk ranges report their start line as one less
+        if alen:
+            astart += 1
+        if blen:
+            bstart += 1
+
+        yield "@@ -%d,%d +%d,%d @@%s\n" % (astart, alen,
+                                           bstart, blen, func)
         for x in delta:
             yield x
         for x in xrange(a2, aend):
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -723,11 +723,10 @@ class patchfile(object):
 
         # fast case first, no offsets, no fuzz
         old = h.old()
-        # patch starts counting at 1 unless we are adding the file
-        if h.starta == 0:
-            start = 0
-        else:
-            start = h.starta + self.offset - 1
+        start = h.starta + self.offset
+        # zero length hunk ranges already have their start decremented
+        if h.lena:
+            start -= 1
         orig_start = start
         # if there's skew we want to emit the "(offset %d lines)" even
         # when the hunk cleanly applies at start + skew, so skip the
diff --git a/tests/test-diff-unified.t b/tests/test-diff-unified.t
--- a/tests/test-diff-unified.t
+++ b/tests/test-diff-unified.t
@@ -89,23 +89,65 @@ invalid diff.unified
   abort: diff context lines count must be an integer, not 'foo'
   [255]
 
-test off-by-one error with diff -p
+0 lines of context hunk header matches gnu diff hunk header
+
+  $ hg init diffzero
+  $ cd diffzero
+  $ cat > f1 << EOF
+  > c2
+  > c4
+  > c5
+  > EOF
+  $ hg commit -Am0
+  adding f1
+
+  $ cat > f2 << EOF
+  > c1
+  > c2
+  > c3
+  > c4
+  > EOF
+  $ diff -U0 f1 f2
+  --- f1	* (glob)
+  +++ f2	* (glob)
+  @@ -0,0 +1 @@
+  +c1
+  @@ -1,0 +3 @@
+  +c3
+  @@ -3 +4,0 @@
+  -c5
+  [1]
 
-  $ hg init diffp
-  $ cd diffp
-  $ echo a > a
-  $ hg ci -Ama
-  adding a
-  $ rm a
-  $ echo b > a
-  $ echo a >> a
-  $ echo c >> a
-  $ hg diff -U0 -p --nodates
-  diff -r cb9a9f314b8b a
-  --- a/a
-  +++ b/a
-  @@ -1,0 +1,1 @@
-  +b
-  @@ -2,0 +3,1 @@ a
-  +c
+  $ mv f2 f1
+  $ hg diff -U0 --nodates
+  diff -r 55d8ff78db23 f1
+  --- a/f1
+  +++ b/f1
+  @@ -0,0 +1,1 @@
+  +c1
+  @@ -1,0 +3,1 @@
+  +c3
+  @@ -3,1 +4,0 @@
+  -c5
 
+  $ hg diff -U0 --nodates --git
+  diff --git a/f1 b/f1
+  --- a/f1
+  +++ b/f1
+  @@ -0,0 +1,1 @@
+  +c1
+  @@ -1,0 +3,1 @@
+  +c3
+  @@ -3,1 +4,0 @@
+  -c5
+
+  $ hg diff -U0 --nodates -p
+  diff -r 55d8ff78db23 f1
+  --- a/f1
+  +++ b/f1
+  @@ -0,0 +1,1 @@
+  +c1
+  @@ -1,0 +3,1 @@ c2
+  +c3
+  @@ -3,1 +4,0 @@ c4
+  -c5
diff --git a/tests/test-import.t b/tests/test-import.t
--- a/tests/test-import.t
+++ b/tests/test-import.t
@@ -958,3 +958,39 @@ diff lines looking like headers
   $ diff want have
   $ cd ..
 
+import a unified diff with no lines of context (diff -U0)
+
+  $ hg init diffzero
+  $ cd diffzero
+  $ cat > f << EOF
+  > c2
+  > c4
+  > c5
+  > EOF
+  $ hg commit -Am0
+  adding f
+
+  $ hg import --no-commit - << EOF
+  > # HG changeset patch
+  > # User test
+  > # Date 0 0
+  > # Node ID f4974ab632f3dee767567b0576c0ec9a4508575c
+  > # Parent  8679a12a975b819fae5f7ad3853a2886d143d794
+  > 1
+  > diff -r 8679a12a975b -r f4974ab632f3 f
+  > --- a/f	Thu Jan 01 00:00:00 1970 +0000
+  > +++ b/f	Thu Jan 01 00:00:00 1970 +0000
+  > @@ -0,0 +1,1 @@
+  > +c1
+  > @@ -1,0 +3,1 @@
+  > +c3
+  > @@ -3,1 +4,0 @@
+  > -c5
+  > EOF
+  applying patch from stdin
+
+  $ cat f
+  c1
+  c2
+  c3
+  c4