diff --git a/add-patch.c b/add-patch.c
index 457b8c550e..867720a7c6 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -451,7 +451,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 	pend = p + plain->len;
 	while (p != pend) {
 		char *eol = memchr(p, '\n', pend - p);
-		const char *deleted = NULL, *added = NULL, *mode_change = NULL;
+		const char *deleted = NULL, *mode_change = NULL;
 
 		if (!eol)
 			eol = pend;
@@ -468,12 +468,11 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 		} else if (p == plain->buf)
 			BUG("diff starts with unexpected line:\n"
 			    "%.*s\n", (int)(eol - p), p);
-		else if (file_diff->deleted || file_diff->added)
+		else if (file_diff->deleted)
 			; /* keep the rest of the file in a single "hunk" */
 		else if (starts_with(p, "@@ ") ||
 			 (hunk == &file_diff->head &&
-			  (skip_prefix(p, "deleted file", &deleted) ||
-			   skip_prefix(p, "new file", &added)))) {
+			  (skip_prefix(p, "deleted file", &deleted)))) {
 			if (marker == '-' || marker == '+')
 				/*
 				 * Should not happen; previous hunk did not end
@@ -491,8 +490,6 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 
 			if (deleted)
 				file_diff->deleted = 1;
-			else if (added)
-				file_diff->added = 1;
 			else if (parse_hunk_header(s, hunk) < 0)
 				return -1;
 
@@ -501,6 +498,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 			 * split
 			 */
 			marker = *p;
+		} else if (hunk == &file_diff->head &&
+			   starts_with(p, "new file")) {
+			file_diff->added = 1;
 		} else if (hunk == &file_diff->head &&
 			   skip_prefix(p, "old mode ", &mode_change) &&
 			   is_octal(mode_change, eol - mode_change)) {
@@ -1362,7 +1362,8 @@ static int patch_update_file(struct add_p_state *s,
 		ALLOW_EDIT = 1 << 6
 	} permitted = 0;
 
-	if (!file_diff->hunk_nr)
+	/* Empty added files have no hunks */
+	if (!file_diff->hunk_nr && !file_diff->added)
 		return 0;
 
 	strbuf_reset(&s->buf);
@@ -1371,21 +1372,25 @@ static int patch_update_file(struct add_p_state *s,
 	for (;;) {
 		if (hunk_index >= file_diff->hunk_nr)
 			hunk_index = 0;
-		hunk = file_diff->hunk + hunk_index;
-
+		hunk = file_diff->hunk_nr
+				? file_diff->hunk + hunk_index
+				: &file_diff->head;
 		undecided_previous = -1;
-		for (i = hunk_index - 1; i >= 0; i--)
-			if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
-				undecided_previous = i;
-				break;
-			}
-
 		undecided_next = -1;
-		for (i = hunk_index + 1; i < file_diff->hunk_nr; i++)
-			if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
-				undecided_next = i;
-				break;
-			}
+
+		if (file_diff->hunk_nr) {
+			for (i = hunk_index - 1; i >= 0; i--)
+				if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
+					undecided_previous = i;
+					break;
+				}
+
+			for (i = hunk_index + 1; i < file_diff->hunk_nr; i++)
+				if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
+					undecided_next = i;
+					break;
+				}
+		}
 
 		/* Everything decided? */
 		if (undecided_previous < 0 && undecided_next < 0 &&
@@ -1393,38 +1398,40 @@ static int patch_update_file(struct add_p_state *s,
 			break;
 
 		strbuf_reset(&s->buf);
-		render_hunk(s, hunk, 0, colored, &s->buf);
-		fputs(s->buf.buf, stdout);
+		if (file_diff->hunk_nr) {
+			render_hunk(s, hunk, 0, colored, &s->buf);
+			fputs(s->buf.buf, stdout);
 
-		strbuf_reset(&s->buf);
-		if (undecided_previous >= 0) {
-			permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK;
-			strbuf_addstr(&s->buf, ",k");
-		}
-		if (hunk_index) {
-			permitted |= ALLOW_GOTO_PREVIOUS_HUNK;
-			strbuf_addstr(&s->buf, ",K");
-		}
-		if (undecided_next >= 0) {
-			permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK;
-			strbuf_addstr(&s->buf, ",j");
-		}
-		if (hunk_index + 1 < file_diff->hunk_nr) {
-			permitted |= ALLOW_GOTO_NEXT_HUNK;
-			strbuf_addstr(&s->buf, ",J");
-		}
-		if (file_diff->hunk_nr > 1) {
-			permitted |= ALLOW_SEARCH_AND_GOTO;
-			strbuf_addstr(&s->buf, ",g,/");
-		}
-		if (hunk->splittable_into > 1) {
-			permitted |= ALLOW_SPLIT;
-			strbuf_addstr(&s->buf, ",s");
-		}
-		if (hunk_index + 1 > file_diff->mode_change &&
-		    !file_diff->deleted) {
-			permitted |= ALLOW_EDIT;
-			strbuf_addstr(&s->buf, ",e");
+			strbuf_reset(&s->buf);
+			if (undecided_previous >= 0) {
+				permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK;
+				strbuf_addstr(&s->buf, ",k");
+			}
+			if (hunk_index) {
+				permitted |= ALLOW_GOTO_PREVIOUS_HUNK;
+				strbuf_addstr(&s->buf, ",K");
+			}
+			if (undecided_next >= 0) {
+				permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK;
+				strbuf_addstr(&s->buf, ",j");
+			}
+			if (hunk_index + 1 < file_diff->hunk_nr) {
+				permitted |= ALLOW_GOTO_NEXT_HUNK;
+				strbuf_addstr(&s->buf, ",J");
+			}
+			if (file_diff->hunk_nr > 1) {
+				permitted |= ALLOW_SEARCH_AND_GOTO;
+				strbuf_addstr(&s->buf, ",g,/");
+			}
+			if (hunk->splittable_into > 1) {
+				permitted |= ALLOW_SPLIT;
+				strbuf_addstr(&s->buf, ",s");
+			}
+			if (hunk_index + 1 > file_diff->mode_change &&
+			    !file_diff->deleted) {
+				permitted |= ALLOW_EDIT;
+				strbuf_addstr(&s->buf, ",e");
+			}
 		}
 		if (file_diff->deleted)
 			prompt_mode_type = PROMPT_DELETION;
@@ -1438,7 +1445,9 @@ static int patch_update_file(struct add_p_state *s,
 		color_fprintf(stdout, s->s.prompt_color,
 			      "(%"PRIuMAX"/%"PRIuMAX") ",
 			      (uintmax_t)hunk_index + 1,
-			      (uintmax_t)file_diff->hunk_nr);
+			      (uintmax_t)(file_diff->hunk_nr
+						? file_diff->hunk_nr
+						: 1));
 		color_fprintf(stdout, s->s.prompt_color,
 			      _(s->mode->prompt_mode[prompt_mode_type]),
 			      s->buf.buf);
@@ -1458,16 +1467,24 @@ static int patch_update_file(struct add_p_state *s,
 			hunk->use = SKIP_HUNK;
 			goto soft_increment;
 		} else if (ch == 'a') {
-			for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
-				hunk = file_diff->hunk + hunk_index;
-				if (hunk->use == UNDECIDED_HUNK)
-					hunk->use = USE_HUNK;
+			if (file_diff->hunk_nr) {
+				for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
+					hunk = file_diff->hunk + hunk_index;
+					if (hunk->use == UNDECIDED_HUNK)
+						hunk->use = USE_HUNK;
+				}
+			} else if (hunk->use == UNDECIDED_HUNK) {
+				hunk->use = USE_HUNK;
 			}
 		} else if (ch == 'd' || ch == 'q') {
-			for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
-				hunk = file_diff->hunk + hunk_index;
-				if (hunk->use == UNDECIDED_HUNK)
-					hunk->use = SKIP_HUNK;
+			if (file_diff->hunk_nr) {
+				for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
+					hunk = file_diff->hunk + hunk_index;
+					if (hunk->use == UNDECIDED_HUNK)
+						hunk->use = SKIP_HUNK;
+				}
+			} else if (hunk->use == UNDECIDED_HUNK) {
+				hunk->use = SKIP_HUNK;
 			}
 			if (ch == 'q') {
 				quit = 1;
@@ -1625,7 +1642,8 @@ static int patch_update_file(struct add_p_state *s,
 		if (file_diff->hunk[i].use == USE_HUNK)
 			break;
 
-	if (i < file_diff->hunk_nr) {
+	if (i < file_diff->hunk_nr ||
+	    (!file_diff->hunk_nr && file_diff->head.use == USE_HUNK)) {
 		/* At least one hunk selected: apply */
 		strbuf_reset(&s->buf);
 		reassemble_patch(s, file_diff, 0, &s->buf);
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index f36c0078ac..6771c0a026 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -754,13 +754,16 @@ sub parse_diff_header {
 	my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
 	my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
 	my $deletion = { TEXT => [], DISPLAY => [], TYPE => 'deletion' };
-	my $addition = { TEXT => [], DISPLAY => [], TYPE => 'addition' };
+	my $addition;
 
 	for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
+		if ($src->{TEXT}->[$i] =~ /^new file/) {
+			$addition = 1;
+			$head->{TYPE} = 'addition';
+		}
 		my $dest =
 		   $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? $mode :
 		   $src->{TEXT}->[$i] =~ /^deleted file/ ? $deletion :
-		   $src->{TEXT}->[$i] =~ /^new file/ ? $addition :
 		   $head;
 		push @{$dest->{TEXT}}, $src->{TEXT}->[$i];
 		push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i];
@@ -1501,12 +1504,6 @@ sub patch_update_file {
 			push @{$deletion->{DISPLAY}}, @{$hunk->{DISPLAY}};
 		}
 		@hunk = ($deletion);
-	} elsif (@{$addition->{TEXT}}) {
-		foreach my $hunk (@hunk) {
-			push @{$addition->{TEXT}}, @{$hunk->{TEXT}};
-			push @{$addition->{DISPLAY}}, @{$hunk->{DISPLAY}};
-		}
-		@hunk = ($addition);
 	}
 
 	$num = scalar @hunk;
@@ -1516,6 +1513,7 @@ sub patch_update_file {
 		my ($prev, $next, $other, $undecided, $i);
 		$other = '';
 
+		last if ($ix and !$num);
 		if ($num <= $ix) {
 			$ix = 0;
 		}
@@ -1548,35 +1546,51 @@ sub patch_update_file {
 				last;
 			}
 		}
-		last if (!$undecided);
+		last if (!$undecided && ($num || !$addition));
 
-		if ($hunk[$ix]{TYPE} eq 'hunk' &&
-		    hunk_splittable($hunk[$ix]{TEXT})) {
-			$other .= ',s';
-		}
-		if ($hunk[$ix]{TYPE} eq 'hunk') {
-			$other .= ',e';
-		}
-		for (@{$hunk[$ix]{DISPLAY}}) {
-			print;
+		if ($num) {
+			if ($hunk[$ix]{TYPE} eq 'hunk' &&
+			    hunk_splittable($hunk[$ix]{TEXT})) {
+				$other .= ',s';
+			}
+			if ($hunk[$ix]{TYPE} eq 'hunk') {
+				$other .= ',e';
+			}
+			for (@{$hunk[$ix]{DISPLAY}}) {
+				print;
+			}
 		}
-		print colored $prompt_color, "(", ($ix+1), "/$num) ",
-			sprintf(__($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}), $other);
+		my $type = $num ? $hunk[$ix]{TYPE} : $head->{TYPE};
+		print colored $prompt_color, "(", ($ix+1), "/", ($num ? $num : 1), ") ",
+			sprintf(__($patch_update_prompt_modes{$patch_mode}{$type}), $other);
 
 		my $line = prompt_single_character;
 		last unless defined $line;
 		if ($line) {
 			if ($line =~ /^y/i) {
-				$hunk[$ix]{USE} = 1;
+				if ($num) {
+					$hunk[$ix]{USE} = 1;
+				} else {
+					$head->{USE} = 1;
+				}
 			}
 			elsif ($line =~ /^n/i) {
-				$hunk[$ix]{USE} = 0;
+				if ($num) {
+					$hunk[$ix]{USE} = 0;
+				} else {
+					$head->{USE} = 0;
+				}
 			}
 			elsif ($line =~ /^a/i) {
-				while ($ix < $num) {
-					if (!defined $hunk[$ix]{USE}) {
-						$hunk[$ix]{USE} = 1;
+				if ($num) {
+					while ($ix < $num) {
+						if (!defined $hunk[$ix]{USE}) {
+							$hunk[$ix]{USE} = 1;
+						}
+						$ix++;
 					}
+				} else {
+					$head->{USE} = 1;
 					$ix++;
 				}
 				next;
@@ -1613,19 +1627,28 @@ sub patch_update_file {
 				next;
 			}
 			elsif ($line =~ /^d/i) {
-				while ($ix < $num) {
-					if (!defined $hunk[$ix]{USE}) {
-						$hunk[$ix]{USE} = 0;
+				if ($num) {
+					while ($ix < $num) {
+						if (!defined $hunk[$ix]{USE}) {
+							$hunk[$ix]{USE} = 0;
+						}
+						$ix++;
 					}
+				} else {
+					$head->{USE} = 0;
 					$ix++;
 				}
 				next;
 			}
 			elsif ($line =~ /^q/i) {
-				for ($i = 0; $i < $num; $i++) {
-					if (!defined $hunk[$i]{USE}) {
-						$hunk[$i]{USE} = 0;
+				if ($num) {
+					for ($i = 0; $i < $num; $i++) {
+						if (!defined $hunk[$i]{USE}) {
+							$hunk[$i]{USE} = 0;
+						}
 					}
+				} elsif (!defined $head->{USE}) {
+					$head->{USE} = 0;
 				}
 				$quit = 1;
 				last;
@@ -1743,7 +1766,7 @@ sub patch_update_file {
 		}
 	}
 
-	@hunk = coalesce_overlapping_hunks(@hunk);
+	@hunk = coalesce_overlapping_hunks(@hunk) if ($num);
 
 	my $n_lofs = 0;
 	my @result = ();
@@ -1753,7 +1776,7 @@ sub patch_update_file {
 		}
 	}
 
-	if (@result) {
+	if (@result or $head->{USE}) {
 		my @patch = reassemble_patch($head->{TEXT}, @result);
 		my $apply_routine = $patch_mode_flavour{APPLY};
 		&$apply_routine(@patch);
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index fb73a847cb..ebe84a6353 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -814,6 +814,44 @@ test_expect_success 'checkout -p works with pathological context lines' '
 	test_cmp expect a
 '
 
+# This should be called from a subshell as it sets a temporary editor
+setup_new_file() {
+	write_script new-file-editor.sh <<-\EOF &&
+	sed /^#/d "$1" >patch &&
+	sed /^+c/d patch >"$1"
+	EOF
+	test_set_editor "$(pwd)/new-file-editor.sh" &&
+	test_write_lines a b c d e f >new-file &&
+	test_write_lines a b d e f >new-file-expect &&
+	test_write_lines "@@ -0,0 +1,6 @@" +a +b +c +d +e +f >patch-expect
+}
+
+test_expect_success 'add -N followed by add -p patch editing' '
+	git reset --hard &&
+	(
+		setup_new_file &&
+		git add -N new-file &&
+		test_write_lines e n q | git add -p &&
+		git cat-file blob :new-file >actual &&
+		test_cmp new-file-expect actual &&
+		test_cmp patch-expect patch
+	)
+'
+
+test_expect_success 'checkout -p patch editing of added file' '
+	git reset --hard &&
+	(
+		setup_new_file &&
+		git add new-file &&
+		git commit -m "add new file" &&
+		git rm new-file &&
+		git commit -m "remove new file" &&
+		test_write_lines e n q | git checkout -p HEAD^ &&
+		test_cmp new-file-expect new-file &&
+		test_cmp patch-expect patch
+	)
+'
+
 test_expect_success 'show help from add--helper' '
 	git reset --hard &&
 	cat >expect <<-EOF &&
