git read-tree -m -u --exclude-per-directory=.gitignore branch-point master side
'
+test_expect_success '3-way not overwriting local changes (setup)' '
+
+ git reset --hard &&
+ git checkout -b side-a branch-point &&
+ echo >>file1 "new line to be kept in the merge result" &&
+ git commit -a -m "side-a changes file1" &&
+ git checkout -b side-b branch-point &&
+ echo >>file2 "new line to be kept in the merge result" &&
+ git commit -a -m "side-b changes file2" &&
+ git checkout side-a
+
+'
+
+test_expect_success '3-way not overwriting local changes (our side)' '
+
+ # At this point, file1 from side-a should be kept as side-b
+ # did not touch it.
+
+ git reset --hard &&
+
+ echo >>file1 "local changes" &&
+ git read-tree -m -u branch-point side-a side-b &&
+ grep "new line to be kept" file1 &&
+ grep "local changes" file1
+
+'
+
+test_expect_success '3-way not overwriting local changes (their side)' '
+
+ # At this point, file2 from side-b should be taken as side-a
+ # did not touch it.
+
+ git reset --hard &&
+
+ echo >>file2 "local changes" &&
+ test_must_fail git read-tree -m -u branch-point side-a side-b &&
+ ! grep "new line to be kept" file2 &&
+ grep "local changes" file2
+
+'
+
test_done
static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
struct unpack_trees_options *o)
{
+ int update = CE_UPDATE;
+
if (old) {
/*
* See if we can re-use the old CE directly?
* That way we get the uptodate stat info.
*
- * This also removes the UPDATE flag on
- * a match.
+ * This also removes the UPDATE flag on a match; otherwise
+ * we will end up overwriting local changes in the work tree.
*/
if (same(old, merge)) {
copy_cache_entry(merge, old);
+ update = 0;
} else {
if (verify_uptodate(old, o))
return -1;
invalidate_ce_path(merge, o);
}
- add_entry(o, merge, CE_UPDATE, CE_STAGEMASK);
+ add_entry(o, merge, update, CE_STAGEMASK);
return 1;
}