checkout -m: attempt merge when deletion of path was staged
twoway_merge() is missing an o->gently check in the case where a file that needs to be modified is missing from the index but present in the old and new trees. As a result, in this case 'git checkout -m' errors out instead of trying to perform a merge. Fix it by checking o->gently. While at it, inline the o->gently check into reject_merge to prevent future call sites from making the same mistake. Noticed by code inspection. The test for the motivating case was added by JC. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									6c1db1b388
								
							
						
					
					
						commit
						6a143aa2b2
					
				|  | @ -223,6 +223,23 @@ test_expect_success 'checkout --merge --conflict=diff3 <branch>' ' | ||||||
| 	test_cmp two expect | 	test_cmp two expect | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | test_expect_success 'switch to another branch while carrying a deletion' ' | ||||||
|  |  | ||||||
|  | 	git checkout -f master && git reset --hard && git clean -f && | ||||||
|  | 	git rm two && | ||||||
|  |  | ||||||
|  | 	test_must_fail git checkout simple 2>errs && | ||||||
|  | 	test_i18ngrep overwritten errs && | ||||||
|  |  | ||||||
|  | 	git checkout --merge simple 2>errs && | ||||||
|  | 	test_i18ngrep ! overwritten errs && | ||||||
|  | 	git ls-files -u && | ||||||
|  | 	test_must_fail git cat-file -t :0:two && | ||||||
|  | 	test "$(git cat-file -t :1:two)" = blob && | ||||||
|  | 	test "$(git cat-file -t :2:two)" = blob && | ||||||
|  | 	test_must_fail git cat-file -t :3:two | ||||||
|  | ' | ||||||
|  |  | ||||||
| test_expect_success 'checkout to detach HEAD (with advice declined)' ' | test_expect_success 'checkout to detach HEAD (with advice declined)' ' | ||||||
|  |  | ||||||
| 	git config advice.detachedHead false && | 	git config advice.detachedHead false && | ||||||
|  |  | ||||||
|  | @ -1178,7 +1178,8 @@ return_failed: | ||||||
| static int reject_merge(const struct cache_entry *ce, | static int reject_merge(const struct cache_entry *ce, | ||||||
| 			struct unpack_trees_options *o) | 			struct unpack_trees_options *o) | ||||||
| { | { | ||||||
| 	return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name); | 	return o->gently ? -1 : | ||||||
|  | 		add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int same(const struct cache_entry *a, const struct cache_entry *b) | static int same(const struct cache_entry *a, const struct cache_entry *b) | ||||||
|  | @ -1633,7 +1634,7 @@ int threeway_merge(const struct cache_entry * const *stages, | ||||||
| 	/* #14, #14ALT, #2ALT */ | 	/* #14, #14ALT, #2ALT */ | ||||||
| 	if (remote && !df_conflict_head && head_match && !remote_match) { | 	if (remote && !df_conflict_head && head_match && !remote_match) { | ||||||
| 		if (index && !same(index, remote) && !same(index, head)) | 		if (index && !same(index, remote) && !same(index, head)) | ||||||
| 			return o->gently ? -1 : reject_merge(index, o); | 			return reject_merge(index, o); | ||||||
| 		return merged_entry(remote, index, o); | 		return merged_entry(remote, index, o); | ||||||
| 	} | 	} | ||||||
| 	/* | 	/* | ||||||
|  | @ -1641,7 +1642,7 @@ int threeway_merge(const struct cache_entry * const *stages, | ||||||
| 	 * make sure that it matches head. | 	 * make sure that it matches head. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (index && !same(index, head)) | 	if (index && !same(index, head)) | ||||||
| 		return o->gently ? -1 : reject_merge(index, o); | 		return reject_merge(index, o); | ||||||
|  |  | ||||||
| 	if (head) { | 	if (head) { | ||||||
| 		/* #5ALT, #15 */ | 		/* #5ALT, #15 */ | ||||||
|  | @ -1770,7 +1771,7 @@ int twoway_merge(const struct cache_entry * const *src, | ||||||
| 				else | 				else | ||||||
| 					return merged_entry(newtree, current, o); | 					return merged_entry(newtree, current, o); | ||||||
| 			} | 			} | ||||||
| 			return o->gently ? -1 : reject_merge(current, o); | 			return reject_merge(current, o); | ||||||
| 		} else if ((!oldtree && !newtree) || /* 4 and 5 */ | 		} else if ((!oldtree && !newtree) || /* 4 and 5 */ | ||||||
| 			 (!oldtree && newtree && | 			 (!oldtree && newtree && | ||||||
| 			  same(current, newtree)) || /* 6 and 7 */ | 			  same(current, newtree)) || /* 6 and 7 */ | ||||||
|  | @ -1788,7 +1789,7 @@ int twoway_merge(const struct cache_entry * const *src, | ||||||
| 			/* 20 or 21 */ | 			/* 20 or 21 */ | ||||||
| 			return merged_entry(newtree, current, o); | 			return merged_entry(newtree, current, o); | ||||||
| 		} else | 		} else | ||||||
| 			return o->gently ? -1 : reject_merge(current, o); | 			return reject_merge(current, o); | ||||||
| 	} | 	} | ||||||
| 	else if (newtree) { | 	else if (newtree) { | ||||||
| 		if (oldtree && !o->initial_checkout) { | 		if (oldtree && !o->initial_checkout) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Jonathan Nieder
						Jonathan Nieder