320 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			320 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/sh
 | 
						|
 | 
						|
test_description='test aborting in-progress merges
 | 
						|
 | 
						|
Set up repo with conflicting and non-conflicting branches:
 | 
						|
 | 
						|
There are three files foo/bar/baz, and the following graph illustrates the
 | 
						|
content of these files in each commit:
 | 
						|
 | 
						|
# foo/bar/baz --- foo/bar/bazz     <-- master
 | 
						|
#             \
 | 
						|
#              --- foo/barf/bazf   <-- conflict_branch
 | 
						|
#               \
 | 
						|
#                --- foo/bart/baz  <-- clean_branch
 | 
						|
 | 
						|
Next, test git merge --abort with the following variables:
 | 
						|
- before/after successful merge (should fail when not in merge context)
 | 
						|
- with/without conflicts
 | 
						|
- clean/dirty index before merge
 | 
						|
- clean/dirty worktree before merge
 | 
						|
- dirty index before merge matches contents on remote branch
 | 
						|
- changed/unchanged worktree after merge
 | 
						|
- changed/unchanged index after merge
 | 
						|
'
 | 
						|
. ./test-lib.sh
 | 
						|
 | 
						|
test_expect_success 'setup' '
 | 
						|
	# Create the above repo
 | 
						|
	echo foo > foo &&
 | 
						|
	echo bar > bar &&
 | 
						|
	echo baz > baz &&
 | 
						|
	git add foo bar baz &&
 | 
						|
	git commit -m initial &&
 | 
						|
	echo bazz > baz &&
 | 
						|
	git commit -a -m "second" &&
 | 
						|
	git checkout -b conflict_branch HEAD^ &&
 | 
						|
	echo barf > bar &&
 | 
						|
	echo bazf > baz &&
 | 
						|
	git commit -a -m "conflict" &&
 | 
						|
	git checkout -b clean_branch HEAD^ &&
 | 
						|
	echo bart > bar &&
 | 
						|
	git commit -a -m "clean" &&
 | 
						|
	git checkout master
 | 
						|
'
 | 
						|
 | 
						|
pre_merge_head="$(git rev-parse HEAD)"
 | 
						|
 | 
						|
test_expect_success 'fails without MERGE_HEAD (unstarted merge)' '
 | 
						|
	test_must_fail git merge --abort 2>output &&
 | 
						|
	test_i18ngrep MERGE_HEAD output
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'fails without MERGE_HEAD (unstarted merge): .git/MERGE_HEAD sanity' '
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'fails without MERGE_HEAD (completed merge)' '
 | 
						|
	git merge clean_branch &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	# Merge successfully completed
 | 
						|
	post_merge_head="$(git rev-parse HEAD)" &&
 | 
						|
	test_must_fail git merge --abort 2>output &&
 | 
						|
	test_i18ngrep MERGE_HEAD output
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'fails without MERGE_HEAD (completed merge): .git/MERGE_HEAD sanity' '
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$post_merge_head" = "$(git rev-parse HEAD)"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Forget previous merge' '
 | 
						|
	git reset --hard "$pre_merge_head"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort after --no-commit' '
 | 
						|
	# Redo merge, but stop before creating merge commit
 | 
						|
	git merge --no-commit clean_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	# Abort non-conflicting merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff)" &&
 | 
						|
	test -z "$(git diff --staged)"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort after conflicts' '
 | 
						|
	# Create conflicting merge
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	# Abort conflicting merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff)" &&
 | 
						|
	test -z "$(git diff --staged)"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Clean merge with dirty index fails' '
 | 
						|
	echo xyzzy >> foo &&
 | 
						|
	git add foo &&
 | 
						|
	git diff --staged > expect &&
 | 
						|
	test_must_fail git merge clean_branch &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff)" &&
 | 
						|
	git diff --staged > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Conflicting merge with dirty index fails' '
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff)" &&
 | 
						|
	git diff --staged > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Reset index (but preserve worktree changes)' '
 | 
						|
	git reset "$pre_merge_head" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort clean merge with non-conflicting dirty worktree' '
 | 
						|
	git merge --no-commit clean_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	# Abort merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff --staged)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort conflicting merge with non-conflicting dirty worktree' '
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	# Abort merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff --staged)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Reset worktree changes' '
 | 
						|
	git reset --hard "$pre_merge_head"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Fail clean merge with conflicting dirty worktree' '
 | 
						|
	echo xyzzy >> bar &&
 | 
						|
	git diff > expect &&
 | 
						|
	test_must_fail git merge --no-commit clean_branch &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff --staged)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Fail conflicting merge with conflicting dirty worktree' '
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff --staged)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Reset worktree changes' '
 | 
						|
	git reset --hard "$pre_merge_head"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Fail clean merge with matching dirty worktree' '
 | 
						|
	echo bart > bar &&
 | 
						|
	git diff > expect &&
 | 
						|
	test_must_fail git merge --no-commit clean_branch &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff --staged)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort clean merge with matching dirty index' '
 | 
						|
	git add bar &&
 | 
						|
	git diff --staged > expect &&
 | 
						|
	git merge --no-commit clean_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	### When aborting the merge, git will discard all staged changes,
 | 
						|
	### including those that were staged pre-merge. In other words,
 | 
						|
	### --abort will LOSE any staged changes (the staged changes that
 | 
						|
	### are lost must match the merge result, or the merge would not
 | 
						|
	### have been allowed to start). Change expectations accordingly:
 | 
						|
	rm expect &&
 | 
						|
	touch expect &&
 | 
						|
	# Abort merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	git diff --staged > actual &&
 | 
						|
	test_cmp expect actual &&
 | 
						|
	test -z "$(git diff)"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Reset worktree changes' '
 | 
						|
	git reset --hard "$pre_merge_head"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Fail conflicting merge with matching dirty worktree' '
 | 
						|
	echo barf > bar &&
 | 
						|
	git diff > expect &&
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	test -z "$(git diff --staged)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort conflicting merge with matching dirty index' '
 | 
						|
	git add bar &&
 | 
						|
	git diff --staged > expect &&
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	### When aborting the merge, git will discard all staged changes,
 | 
						|
	### including those that were staged pre-merge. In other words,
 | 
						|
	### --abort will LOSE any staged changes (the staged changes that
 | 
						|
	### are lost must match the merge result, or the merge would not
 | 
						|
	### have been allowed to start). Change expectations accordingly:
 | 
						|
	rm expect &&
 | 
						|
	touch expect &&
 | 
						|
	# Abort merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	git diff --staged > actual &&
 | 
						|
	test_cmp expect actual &&
 | 
						|
	test -z "$(git diff)"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Reset worktree changes' '
 | 
						|
	git reset --hard "$pre_merge_head"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort merge with pre- and post-merge worktree changes' '
 | 
						|
	# Pre-merge worktree changes
 | 
						|
	echo xyzzy > foo &&
 | 
						|
	echo barf > bar &&
 | 
						|
	git add bar &&
 | 
						|
	git diff > expect &&
 | 
						|
	git diff --staged > expect-staged &&
 | 
						|
	# Perform merge
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	# Post-merge worktree changes
 | 
						|
	echo yzxxz > foo &&
 | 
						|
	echo blech > baz &&
 | 
						|
	### When aborting the merge, git will discard staged changes (bar)
 | 
						|
	### and unmerged changes (baz). Other changes that are neither
 | 
						|
	### staged nor marked as unmerged (foo), will be preserved. For
 | 
						|
	### these changed, git cannot tell pre-merge changes apart from
 | 
						|
	### post-merge changes, so the post-merge changes will be
 | 
						|
	### preserved. Change expectations accordingly:
 | 
						|
	git diff -- foo > expect &&
 | 
						|
	rm expect-staged &&
 | 
						|
	touch expect-staged &&
 | 
						|
	# Abort merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual &&
 | 
						|
	git diff --staged > actual-staged &&
 | 
						|
	test_cmp expect-staged actual-staged
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Reset worktree changes' '
 | 
						|
	git reset --hard "$pre_merge_head"
 | 
						|
'
 | 
						|
 | 
						|
test_expect_success 'Abort merge with pre- and post-merge index changes' '
 | 
						|
	# Pre-merge worktree changes
 | 
						|
	echo xyzzy > foo &&
 | 
						|
	echo barf > bar &&
 | 
						|
	git add bar &&
 | 
						|
	git diff > expect &&
 | 
						|
	git diff --staged > expect-staged &&
 | 
						|
	# Perform merge
 | 
						|
	test_must_fail git merge conflict_branch &&
 | 
						|
	test -f .git/MERGE_HEAD &&
 | 
						|
	# Post-merge worktree changes
 | 
						|
	echo yzxxz > foo &&
 | 
						|
	echo blech > baz &&
 | 
						|
	git add foo bar &&
 | 
						|
	### When aborting the merge, git will discard all staged changes
 | 
						|
	### (foo, bar and baz), and no changes will be preserved. Whether
 | 
						|
	### the changes were staged pre- or post-merge does not matter
 | 
						|
	### (except for not preventing starting the merge).
 | 
						|
	### Change expectations accordingly:
 | 
						|
	rm expect expect-staged &&
 | 
						|
	touch expect &&
 | 
						|
	touch expect-staged &&
 | 
						|
	# Abort merge
 | 
						|
	git merge --abort &&
 | 
						|
	test ! -f .git/MERGE_HEAD &&
 | 
						|
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 | 
						|
	git diff > actual &&
 | 
						|
	test_cmp expect actual &&
 | 
						|
	git diff --staged > actual-staged &&
 | 
						|
	test_cmp expect-staged actual-staged
 | 
						|
'
 | 
						|
 | 
						|
test_done
 |