Subject: [PATCH] test case highlighting possible strategy to rebase merge

From: Jacob Keller <[email-masked]>
Date: Tue, 27 Feb 2018 00:10:29 -0800

Add a test case highlighting how the process outlined by Sergey Organov
could be used to re-create merges without losing any context.

The test currently only uses new files, with the exception of one part
involving an evil merge. Unfortunately I'm not sure how to represent
merge conflicts that need to be handled. It looks like it should when
there is enough context that the changes don't have direct textual
conflict, but I was unable to figure out how to produce such a change
directly in the test case.

I think this method shows a lot of promise, and is worth investigating
more to see if we can actually make it work in practice without
requiring separate steps.

Signed-off-by: Jacob Keller <[email-masked]>
---
 t/t7900-rebasing-merge.sh | 178 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 178 insertions(+)
 create mode 100755 t/t7900-rebasing-merge.sh

diff --git a/t/t7900-rebasing-merge.sh b/t/t7900-rebasing-merge.sh
new file mode 100755
index 0000000..7639425
--- /dev/null
+++ b/t/t7900-rebasing-merge.sh
@@ -0,0 +1,178 @@
+#!/bin/sh
+
+test_description='test showcasing safe method to rebase a merge'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo "file1" >a &&
+	echo "file2" >b &&
+	test_tick &&
+	git add a b &&
+	git commit -m "initial" &&
+	git branch initial &&
+	git branch branch1 &&
+	git branch branch2 &&
+	git checkout branch1 &&
+	test_tick &&
+	echo "a change in file1" >>a &&
+	git add a &&
+	git commit -m "commit1" &&
+	test_tick &&
+	echo "another change in file1" >>a &&
+	git add a &&
+	git commit -m "commit2" &&
+	git checkout branch2 &&
+	test_tick &&
+	echo "a change in file2" >>b &&
+	git add b &&
+	git commit -m "commit3" &&
+	git checkout -B simple-merge branch1 &&
+	git merge -m "simple merge branch2 into branch1" branch2 &&
+	cat >expected <<-\EOF &&
+	file1
+	a change in file1
+	another change in file1
+	EOF
+	test_cmp expected a &&
+	cat >expected <<-\EOF &&
+	file2
+	a change in file2
+	EOF
+	test_cmp expected b
+'
+
+test_expect_success 'trivial rebase case' '
+	git checkout -B new-initial initial &&
+	echo "newfile3" >c &&
+	test_tick &&
+	git add c &&
+	git commit -m "a new file" &&
+	git checkout -B new-branch1 branch1 &&
+	test_tick &&
+	git rebase new-initial &&
+	test_tick &&
+	git cherry-pick -m1 --keep-redundant-commits simple-merge &&
+	git checkout -B new-branch2 branch2 &&
+	test_tick &&
+	git rebase new-initial &&
+	test_tick &&
+	git cherry-pick -m2 --keep-redundant-commits simple-merge &&
+	git checkout -B rebased-simple-merge new-branch1 &&
+	git merge --no-ff -m "rebased simple merge new-branch2 into new-branch1" new-branch2 &&
+	git reset --soft HEAD^ &&
+	git update-ref refs/heads/rebased-simple-merge "$(git commit-tree -m "finalized rebased simple merge new-branch2 into new-branch1" "$(git write-tree)" -p "$(git rev-parse new-branch1^)" -p "$(git rev-parse new-branch2^)")" &&
+	git checkout rebased-simple-merge &&
+	cat >expected <<-\EOF &&
+	file1
+	a change in file1
+	another change in file1
+	EOF
+	test_cmp expected a &&
+	cat >expected <<-\EOF &&
+	file2
+	a change in file2
+	EOF
+	test_cmp expected b &&
+	cat >expected <<-\EOF &&
+	newfile3
+	EOF
+	test_cmp expected c
+'
+
+test_expect_success 'evil merge rebase case' '
+	git checkout -B evil-merge simple-merge &&
+	test_tick &&
+	echo "evil change to file2" >>b &&
+	git add b &&
+	git commit --amend -m "evil mergbe branch2 into branch1" &&
+	git checkout -B new-initial initial &&
+	echo "newfile3" >c &&
+	test_tick &&
+	git add c &&
+	git commit -m "a new file" &&
+	git checkout -B new-branch1 branch1 &&
+	test_tick &&
+	git rebase new-initial &&
+	test_tick &&
+	git cherry-pick -m1 --keep-redundant-commits evil-merge &&
+	git checkout -B new-branch2 branch2 &&
+	test_tick &&
+	git rebase new-initial &&
+	test_tick &&
+	git cherry-pick -m2 --keep-redundant-commits evil-merge &&
+	git checkout -B rebased-evil-merge new-branch1 &&
+	git merge --no-ff -m "rebased simple merge new-branch2 into new-branch1" new-branch2 &&
+	git reset --soft HEAD^ &&
+	git update-ref refs/heads/rebased-evil-merge "$(git commit-tree -m "finalized rebased simple merge new-branch2 into new-branch1" "$(git write-tree)" -p "$(git rev-parse new-branch1^)" -p "$(git rev-parse new-branch2^)")" &&
+	git checkout rebased-evil-merge &&
+	cat >expected <<-\EOF &&
+	file1
+	a change in file1
+	another change in file1
+	EOF
+	test_cmp expected a &&
+	cat >expected <<-\EOF &&
+	file2
+	a change in file2
+	evil change to file2
+	EOF
+	test_cmp expected b &&
+	cat >expected <<-\EOF &&
+	newfile3
+	EOF
+	test_cmp expected c
+'
+test_expect_success 'rebase add commit to branch1 case' '
+	git checkout -B new-initial initial &&
+	echo "newfile3" >c &&
+	test_tick &&
+	git add c &&
+	git commit -m "a new file" &&
+	git checkout -B new-branch1 branch1 &&
+	test_tick &&
+	git rebase new-initial &&
+	test_tick &&
+	cat >d <<-\EOF &&
+	rebasefile4
+	a new file added in rebase
+	EOF
+	git add d &&
+	git commit -m "a new commit added to branch1" &&
+	test_tick &&
+	git cherry-pick -m1 --keep-redundant-commits simple-merge &&
+	git checkout -B new-branch2 branch2 &&
+	test_tick &&
+	git rebase new-initial &&
+	test_tick &&
+	git cherry-pick -m2 --keep-redundant-commits simple-merge &&
+	git checkout -B rebased-add-commit-merge new-branch1 &&
+	git merge --no-ff -m "rebased add commit merge new-branch2 into new-branch1" new-branch2 &&
+	git reset --soft HEAD^ &&
+	git update-ref refs/heads/rebased-add-commit-merge "$(git commit-tree -m "finalized rebased add commit merge new-branch2 into new-branch1" "$(git write-tree)" -p "$(git rev-parse new-branch1^)" -p "$(git rev-parse new-branch2^)")" &&
+	git checkout rebased-add-commit-merge &&
+	cat >expected <<-\EOF &&
+	file1
+	a change in file1
+	another change in file1
+	EOF
+	test_cmp expected a &&
+	cat >expected <<-\EOF &&
+	file2
+	a change in file2
+	EOF
+	test_cmp expected b &&
+	cat >expected <<-\EOF &&
+	newfile3
+	EOF
+	test_cmp expected c &&
+	cat >expected <<-\EOF &&
+	rebasefile4
+	a new file added in rebase
+	EOF
+	test_cmp expected d
+'
+
+test_done
+
+
-- 
2.7.4