merge-recursive: do not clobber untracked working tree garbage
When merge-recursive wanted to create a new file in the work tree (either as the final result, or a hint for reference purposes while delete/modify conflicts), it unconditionally overwrote an untracked file in the working tree. Be careful not to lose whatever the user has that is not tracked. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Dec 14, 2008 at 19:40 UTC
c5ab03f26c992e30f355fba129f70db0f290fcd7
2 files changed
+33
-1
builtin-merge-recursive.c
+32
@@ -471,6 +471,30 @@ static void flush_buffer(int fd, const char *buf, unsigned long size)
471
}
472
}
473
474
+static int would_lose_untracked(const char *path)
475
+{
476
+ int pos = cache_name_pos(path, strlen(path));
477
+
478
+ if (pos < 0)
479
+ pos = -1 - pos;
480
+ while (pos < active_nr &&
481
+ !strcmp(path, active_cache[pos]->name)) {
482
+ /*
483
+ * If stage #0, it is definitely tracked.
484
+ * If it has stage #2 then it was tracked
485
+ * before this merge started. All other
486
+ * cases the path was not tracked.
487
+ */
488
+ switch (ce_stage(active_cache[pos])) {
489
+ case 0:
490
+ case 2:
491
+ return 0;
492
+ }
493
+ pos++;
494
+ }
495
+ return file_exists(path);
496
+}
497
+
498
static int make_room_for_path(const char *path)
499
{
500
int status;
@@ -486,6 +510,14 @@ static int make_room_for_path(const char *path)
510
die(msg, path, "");
511
}
512
513
+ /*
514
+ * Do not unlink a file in the work tree if we are not
515
+ * tracking it.
516
+ */
517
+ if (would_lose_untracked(path))
518
+ return error("refusing to lose untracked file at '%s'",
519
+ path);
520
+
521
/* Successful unlink is good.. */
522
if (!unlink(path))
523
return 0;
t/t7607-merge-overwrite.sh
+1
-1
@@ -53,7 +53,7 @@ test_expect_success 'will not overwrite staged changes' '
53
test_cmp important c2.c
54
'
55
56
-test_expect_failure 'will not overwrite removed file' '
56
+test_expect_success 'will not overwrite removed file' '
57
git reset --hard c1 &&
58
git rm c1.c &&
59
git commit -m "rm c1.c" &&