@@ -2879,4 +2879,371 @@ test_expect_failure '9g-check: Renamed directory that only contained immediate s
2879
2879
# side of history for any implicit directory renames.
2880
2880
# ##########################################################################
2881
2881
2882
+ # ##########################################################################
2883
+ # SECTION 10: Handling untracked files
2884
+ #
2885
+ # unpack_trees(), upon which the recursive merge algorithm is based, aborts
2886
+ # the operation if untracked or dirty files would be deleted or overwritten
2887
+ # by the merge. Unfortunately, unpack_trees() does not understand renames,
2888
+ # and if it doesn't abort, then it muddies up the working directory before
2889
+ # we even get to the point of detecting renames, so we need some special
2890
+ # handling, at least in the case of directory renames.
2891
+ # ##########################################################################
2892
+
2893
+ # Testcase 10a, Overwrite untracked: normal rename/delete
2894
+ # Commit O: z/{b,c_1}
2895
+ # Commit A: z/b + untracked z/c + untracked z/d
2896
+ # Commit B: z/{b,d_1}
2897
+ # Expected: Aborted Merge +
2898
+ # ERROR_MSG(untracked working tree files would be overwritten by merge)
2899
+
2900
+ test_expect_success ' 10a-setup: Overwrite untracked with normal rename/delete' '
2901
+ test_create_repo 10a &&
2902
+ (
2903
+ cd 10a &&
2904
+
2905
+ mkdir z &&
2906
+ echo b >z/b &&
2907
+ echo c >z/c &&
2908
+ git add z &&
2909
+ test_tick &&
2910
+ git commit -m "O" &&
2911
+
2912
+ git branch O &&
2913
+ git branch A &&
2914
+ git branch B &&
2915
+
2916
+ git checkout A &&
2917
+ git rm z/c &&
2918
+ test_tick &&
2919
+ git commit -m "A" &&
2920
+
2921
+ git checkout B &&
2922
+ git mv z/c z/d &&
2923
+ test_tick &&
2924
+ git commit -m "B"
2925
+ )
2926
+ '
2927
+
2928
+ test_expect_success ' 10a-check: Overwrite untracked with normal rename/delete' '
2929
+ (
2930
+ cd 10a &&
2931
+
2932
+ git checkout A^0 &&
2933
+ echo very >z/c &&
2934
+ echo important >z/d &&
2935
+
2936
+ test_must_fail git merge -s recursive B^0 >out 2>err &&
2937
+ test_i18ngrep "The following untracked working tree files would be overwritten by merge" err &&
2938
+
2939
+ git ls-files -s >out &&
2940
+ test_line_count = 1 out &&
2941
+ git ls-files -o >out &&
2942
+ test_line_count = 4 out &&
2943
+
2944
+ echo very >expect &&
2945
+ test_cmp expect z/c &&
2946
+
2947
+ echo important >expect &&
2948
+ test_cmp expect z/d &&
2949
+
2950
+ git rev-parse HEAD:z/b >actual &&
2951
+ git rev-parse O:z/b >expect &&
2952
+ test_cmp expect actual
2953
+ )
2954
+ '
2955
+
2956
+ # Testcase 10b, Overwrite untracked: dir rename + delete
2957
+ # Commit O: z/{b,c_1}
2958
+ # Commit A: y/b + untracked y/{c,d,e}
2959
+ # Commit B: z/{b,d_1,e}
2960
+ # Expected: Failed Merge; y/b + untracked y/c + untracked y/d on disk +
2961
+ # z/c_1 -> z/d_1 rename recorded at stage 3 for y/d +
2962
+ # ERROR_MSG(refusing to lose untracked file at 'y/d')
2963
+
2964
+ test_expect_success ' 10b-setup: Overwrite untracked with dir rename + delete' '
2965
+ test_create_repo 10b &&
2966
+ (
2967
+ cd 10b &&
2968
+
2969
+ mkdir z &&
2970
+ echo b >z/b &&
2971
+ echo c >z/c &&
2972
+ git add z &&
2973
+ test_tick &&
2974
+ git commit -m "O" &&
2975
+
2976
+ git branch O &&
2977
+ git branch A &&
2978
+ git branch B &&
2979
+
2980
+ git checkout A &&
2981
+ git rm z/c &&
2982
+ git mv z/ y/ &&
2983
+ test_tick &&
2984
+ git commit -m "A" &&
2985
+
2986
+ git checkout B &&
2987
+ git mv z/c z/d &&
2988
+ echo e >z/e &&
2989
+ git add z/e &&
2990
+ test_tick &&
2991
+ git commit -m "B"
2992
+ )
2993
+ '
2994
+
2995
+ test_expect_failure ' 10b-check: Overwrite untracked with dir rename + delete' '
2996
+ (
2997
+ cd 10b &&
2998
+
2999
+ git checkout A^0 &&
3000
+ echo very >y/c &&
3001
+ echo important >y/d &&
3002
+ echo contents >y/e &&
3003
+
3004
+ test_must_fail git merge -s recursive B^0 >out 2>err &&
3005
+ test_i18ngrep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out &&
3006
+ test_i18ngrep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out &&
3007
+
3008
+ git ls-files -s >out &&
3009
+ test_line_count = 3 out &&
3010
+ git ls-files -u >out &&
3011
+ test_line_count = 2 out &&
3012
+ git ls-files -o >out &&
3013
+ test_line_count = 5 out &&
3014
+
3015
+ git rev-parse >actual \
3016
+ :0:y/b :3:y/d :3:y/e &&
3017
+ git rev-parse >expect \
3018
+ O:z/b O:z/c B:z/e &&
3019
+ test_cmp expect actual &&
3020
+
3021
+ echo very >expect &&
3022
+ test_cmp expect y/c &&
3023
+
3024
+ echo important >expect &&
3025
+ test_cmp expect y/d &&
3026
+
3027
+ echo contents >expect &&
3028
+ test_cmp expect y/e
3029
+ )
3030
+ '
3031
+
3032
+ # Testcase 10c, Overwrite untracked: dir rename/rename(1to2)
3033
+ # Commit O: z/{a,b}, x/{c,d}
3034
+ # Commit A: y/{a,b}, w/c, x/d + different untracked y/c
3035
+ # Commit B: z/{a,b,c}, x/d
3036
+ # Expected: Failed Merge; y/{a,b} + x/d + untracked y/c +
3037
+ # CONFLICT(rename/rename) x/c -> w/c vs y/c +
3038
+ # y/c~B^0 +
3039
+ # ERROR_MSG(Refusing to lose untracked file at y/c)
3040
+
3041
+ test_expect_success ' 10c-setup: Overwrite untracked with dir rename/rename(1to2)' '
3042
+ test_create_repo 10c &&
3043
+ (
3044
+ cd 10c &&
3045
+
3046
+ mkdir z x &&
3047
+ echo a >z/a &&
3048
+ echo b >z/b &&
3049
+ echo c >x/c &&
3050
+ echo d >x/d &&
3051
+ git add z x &&
3052
+ test_tick &&
3053
+ git commit -m "O" &&
3054
+
3055
+ git branch O &&
3056
+ git branch A &&
3057
+ git branch B &&
3058
+
3059
+ git checkout A &&
3060
+ mkdir w &&
3061
+ git mv x/c w/c &&
3062
+ git mv z/ y/ &&
3063
+ test_tick &&
3064
+ git commit -m "A" &&
3065
+
3066
+ git checkout B &&
3067
+ git mv x/c z/ &&
3068
+ test_tick &&
3069
+ git commit -m "B"
3070
+ )
3071
+ '
3072
+
3073
+ test_expect_failure ' 10c-check: Overwrite untracked with dir rename/rename(1to2)' '
3074
+ (
3075
+ cd 10c &&
3076
+
3077
+ git checkout A^0 &&
3078
+ echo important >y/c &&
3079
+
3080
+ test_must_fail git merge -s recursive B^0 >out 2>err &&
3081
+ test_i18ngrep "CONFLICT (rename/rename)" out &&
3082
+ test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out &&
3083
+
3084
+ git ls-files -s >out &&
3085
+ test_line_count = 6 out &&
3086
+ git ls-files -u >out &&
3087
+ test_line_count = 3 out &&
3088
+ git ls-files -o >out &&
3089
+ test_line_count = 3 out &&
3090
+
3091
+ git rev-parse >actual \
3092
+ :0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :3:y/c &&
3093
+ git rev-parse >expect \
3094
+ O:z/a O:z/b O:x/d O:x/c O:x/c O:x/c &&
3095
+ test_cmp expect actual &&
3096
+
3097
+ git hash-object y/c~B^0 >actual &&
3098
+ git rev-parse O:x/c >expect &&
3099
+ test_cmp expect actual &&
3100
+
3101
+ echo important >expect &&
3102
+ test_cmp expect y/c
3103
+ )
3104
+ '
3105
+
3106
+ # Testcase 10d, Delete untracked w/ dir rename/rename(2to1)
3107
+ # Commit O: z/{a,b,c_1}, x/{d,e,f_2}
3108
+ # Commit A: y/{a,b}, x/{d,e,f_2,wham_1} + untracked y/wham
3109
+ # Commit B: z/{a,b,c_1,wham_2}, y/{d,e}
3110
+ # Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~B^0,wham~HEAD}+
3111
+ # CONFLICT(rename/rename) z/c_1 vs x/f_2 -> y/wham
3112
+ # ERROR_MSG(Refusing to lose untracked file at y/wham)
3113
+
3114
+ test_expect_success ' 10d-setup: Delete untracked with dir rename/rename(2to1)' '
3115
+ test_create_repo 10d &&
3116
+ (
3117
+ cd 10d &&
3118
+
3119
+ mkdir z x &&
3120
+ echo a >z/a &&
3121
+ echo b >z/b &&
3122
+ echo c >z/c &&
3123
+ echo d >x/d &&
3124
+ echo e >x/e &&
3125
+ echo f >x/f &&
3126
+ git add z x &&
3127
+ test_tick &&
3128
+ git commit -m "O" &&
3129
+
3130
+ git branch O &&
3131
+ git branch A &&
3132
+ git branch B &&
3133
+
3134
+ git checkout A &&
3135
+ git mv z/c x/wham &&
3136
+ git mv z/ y/ &&
3137
+ test_tick &&
3138
+ git commit -m "A" &&
3139
+
3140
+ git checkout B &&
3141
+ git mv x/f z/wham &&
3142
+ git mv x/ y/ &&
3143
+ test_tick &&
3144
+ git commit -m "B"
3145
+ )
3146
+ '
3147
+
3148
+ test_expect_failure ' 10d-check: Delete untracked with dir rename/rename(2to1)' '
3149
+ (
3150
+ cd 10d &&
3151
+
3152
+ git checkout A^0 &&
3153
+ echo important >y/wham &&
3154
+
3155
+ test_must_fail git merge -s recursive B^0 >out 2>err &&
3156
+ test_i18ngrep "CONFLICT (rename/rename)" out &&
3157
+ test_i18ngrep "Refusing to lose untracked file at y/wham" out &&
3158
+
3159
+ git ls-files -s >out &&
3160
+ test_line_count = 6 out &&
3161
+ git ls-files -u >out &&
3162
+ test_line_count = 2 out &&
3163
+ git ls-files -o >out &&
3164
+ test_line_count = 4 out &&
3165
+
3166
+ git rev-parse >actual \
3167
+ :0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham &&
3168
+ git rev-parse >expect \
3169
+ O:z/a O:z/b O:x/d O:x/e O:z/c O:x/f &&
3170
+ test_cmp expect actual &&
3171
+
3172
+ test_must_fail git rev-parse :1:y/wham &&
3173
+
3174
+ echo important >expect &&
3175
+ test_cmp expect y/wham &&
3176
+
3177
+ git hash-object >actual \
3178
+ y/wham~B^0 y/wham~HEAD &&
3179
+ git rev-parse >expect \
3180
+ O:x/f O:z/c &&
3181
+ test_cmp expect actual
3182
+ )
3183
+ '
3184
+
3185
+ # Testcase 10e, Does git complain about untracked file that's not in the way?
3186
+ # Commit O: z/{a,b}
3187
+ # Commit A: y/{a,b} + untracked z/c
3188
+ # Commit B: z/{a,b,c}
3189
+ # Expected: y/{a,b,c} + untracked z/c
3190
+
3191
+ test_expect_success ' 10e-setup: Does git complain about untracked file that is not really in the way?' '
3192
+ test_create_repo 10e &&
3193
+ (
3194
+ cd 10e &&
3195
+
3196
+ mkdir z &&
3197
+ echo a >z/a &&
3198
+ echo b >z/b &&
3199
+ git add z &&
3200
+ test_tick &&
3201
+ git commit -m "O" &&
3202
+
3203
+ git branch O &&
3204
+ git branch A &&
3205
+ git branch B &&
3206
+
3207
+ git checkout A &&
3208
+ git mv z/ y/ &&
3209
+ test_tick &&
3210
+ git commit -m "A" &&
3211
+
3212
+ git checkout B &&
3213
+ echo c >z/c &&
3214
+ git add z/c &&
3215
+ test_tick &&
3216
+ git commit -m "B"
3217
+ )
3218
+ '
3219
+
3220
+ test_expect_failure ' 10e-check: Does git complain about untracked file that is not really in the way?' '
3221
+ (
3222
+ cd 10e &&
3223
+
3224
+ git checkout A^0 &&
3225
+ mkdir z &&
3226
+ echo random >z/c &&
3227
+
3228
+ git merge -s recursive B^0 >out 2>err &&
3229
+ test_i18ngrep ! "following untracked working tree files would be overwritten by merge" err &&
3230
+
3231
+ git ls-files -s >out &&
3232
+ test_line_count = 3 out &&
3233
+ git ls-files -u >out &&
3234
+ test_line_count = 0 out &&
3235
+ git ls-files -o >out &&
3236
+ test_line_count = 3 out &&
3237
+
3238
+ git rev-parse >actual \
3239
+ :0:y/a :0:y/b :0:y/c &&
3240
+ git rev-parse >expect \
3241
+ O:z/a O:z/b B:z/c &&
3242
+ test_cmp expect actual &&
3243
+
3244
+ echo random >expect &&
3245
+ test_cmp expect z/c
3246
+ )
3247
+ '
3248
+
2882
3249
test_done
0 commit comments