merge-recursive: When we detect we can skip an update, actually skip it
authorElijah Newren <newren@gmail.com>
Tue, 1 Mar 2011 01:08:52 +0000 (18:08 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 Mar 2011 19:55:06 +0000 (11:55 -0800)
In 882fd11 (merge-recursive: Delay content merging for renames 2010-09-20),
there was code that checked for whether we could skip updating a file in
the working directory, based on whether the merged version matched the
current working copy.  Due to the desire to handle directory/file conflicts
that were resolvable, that commit deferred content merging by first
updating the index with the unmerged entries and then moving the actual
merging (along with the skip-the-content-update check) to another function
that ran later in the merge process.  As part moving the content merging
code, a bug was introduced such that although the message about skipping
the update would be printed (whenever GIT_MERGE_VERBOSITY was sufficiently
high), the file would be unconditionally updated in the working copy
anyway.

When we detect that the file does not need to be updated in the working
copy, update the index appropriately and then return early before updating
the working copy.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
merge-recursive.c
t/t6022-merge-rename.sh

index 231e5cbd7f87c95f909709cc649bfb202a4ece87..847bc8494ff1e7610b6dbb76c9c368efdf903ccd 100644 (file)
@@ -354,10 +354,11 @@ static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
         * make room for the corresponding directory.  Such paths will
         * later be processed in process_df_entry() at the end.  If
         * the corresponding directory ends up being removed by the
-        * merge, then the file will be reinstated at that time;
-        * otherwise, if the file is not supposed to be removed by the
-        * merge, the contents of the file will be placed in another
-        * unique filename.
+        * merge, then the file will be reinstated at that time
+        * (albeit with a different timestamp!); otherwise, if the
+        * file is not supposed to be removed by the merge, the
+        * contents of the file will be placed in another unique
+        * filename.
         *
         * NOTE: This function relies on the fact that entries for a
         * D/F conflict will appear adjacent in the index, with the
@@ -1272,9 +1273,13 @@ static int merge_content(struct merge_options *o,
        }
 
        if (mfi.clean && !df_conflict_remains &&
-           sha_eq(mfi.sha, a_sha) && mfi.mode == a.mode)
+           sha_eq(mfi.sha, a_sha) && mfi.mode == a.mode &&
+           lstat(path, &st) == 0) {
                output(o, 3, "Skipped %s (merged same as existing)", path);
-       else
+               add_cacheinfo(mfi.mode, mfi.sha, path,
+                             0 /*stage*/, 1 /*refresh*/, 0 /*options*/);
+               return mfi.clean;
+       } else
                output(o, 2, "Auto-merging %s", path);
 
        if (!mfi.clean) {
index 6b3e8b8d4bfb8676bef52ace744f59c681120f01..7d955c1e12289dc22f594f97ab04b5d8bb2a0d9e 100755 (executable)
@@ -728,7 +728,7 @@ test_expect_success 'setup avoid unnecessary update, normal rename' '
        git commit -m "Random, unrelated changes"
 '
 
-test_expect_failure 'avoid unnecessary update, normal rename' '
+test_expect_success 'avoid unnecessary update, normal rename' '
        git checkout -q avoid-unnecessary-update-1^0 &&
        test-chmtime =1000000000 rename &&
        test-chmtime -v +0 rename >expect &&