#!/bin/sh # # Copyright (c) 2013 Ramkumar Ramachandra # global test_description := ''git rebase --autostash tests'' source ./test-lib.sh test_expect_success setup ' echo hello-world >file0 && git add . && test_tick && git commit -m "initial commit" && git checkout -b feature-branch && echo another-hello >file1 && echo goodbye >file2 && git add . && test_tick && git commit -m "second commit" && echo final-goodbye >file3 && git add . && test_tick && git commit -m "third commit" && git checkout -b unrelated-onto-branch master && echo unrelated >file4 && git add . && test_tick && git commit -m "unrelated commit" && git checkout -b related-onto-branch master && echo conflicting-change >file2 && git add . && test_tick && git commit -m "related commit" ' proc testrebase { global type := $1 global dotest := $2 test_expect_success "rebase$type: dirty worktree, --no-autostash" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && test_when_finished git checkout feature-branch && echo dirty >>file3 && test_must_fail git rebase$type --no-autostash unrelated-onto-branch ' test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && echo dirty >>file3 && git rebase$type unrelated-onto-branch && grep unrelated file4 && grep dirty file3 && git checkout feature-branch ' test_expect_success "rebase$type: dirty index, non-conflicting rebase" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && echo dirty >>file3 && git add file3 && git rebase$type unrelated-onto-branch && grep unrelated file4 && grep dirty file3 && git checkout feature-branch ' test_expect_success "rebase$type: conflicting rebase" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && echo dirty >>file3 && test_must_fail git rebase$type related-onto-branch && test_path_is_file $dotest/autostash && ! grep dirty file3 && rm -rf $dotest && git reset --hard && git checkout feature-branch ' test_expect_success "rebase$type: --continue" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && echo dirty >>file3 && test_must_fail git rebase$type related-onto-branch && test_path_is_file $dotest/autostash && ! grep dirty file3 && echo "conflicting-plus-goodbye" >file2 && git add file2 && git rebase --continue && test_path_is_missing $dotest/autostash && grep dirty file3 && git checkout feature-branch ' test_expect_success "rebase$type: --skip" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && echo dirty >>file3 && test_must_fail git rebase$type related-onto-branch && test_path_is_file $dotest/autostash && ! grep dirty file3 && git rebase --skip && test_path_is_missing $dotest/autostash && grep dirty file3 && git checkout feature-branch ' test_expect_success "rebase$type: --abort" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && echo dirty >>file3 && test_must_fail git rebase$type related-onto-branch && test_path_is_file $dotest/autostash && ! grep dirty file3 && git rebase --abort && test_path_is_missing $dotest/autostash && grep dirty file3 && git checkout feature-branch ' test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" ' test_config rebase.autostash true && git reset --hard && git checkout -b rebased-feature-branch feature-branch && test_when_finished git branch -D rebased-feature-branch && echo dirty >file4 && git add file4 && git rebase$type unrelated-onto-branch && test_path_is_missing $dotest && git reset --hard && grep unrelated file4 && ! grep dirty file4 && git checkout feature-branch && git stash pop && grep dirty file4 ' } test_expect_success "rebase: fast-forward rebase" ' test_config rebase.autostash true && git reset --hard && git checkout -b behind-feature-branch feature-branch~1 && test_when_finished git branch -D behind-feature-branch && echo dirty >>file1 && git rebase feature-branch && grep dirty file1 && git checkout feature-branch ' test_expect_success "rebase: noop rebase" ' test_config rebase.autostash true && git reset --hard && git checkout -b same-feature-branch feature-branch && test_when_finished git branch -D same-feature-branch && echo dirty >>file1 && git rebase feature-branch && grep dirty file1 && git checkout feature-branch ' testrebase "" .git/rebase-apply testrebase " --merge" .git/rebase-merge testrebase " --interactive" .git/rebase-merge test_expect_success 'abort rebase -i with --autostash' ' test_when_finished "git reset --hard" && echo uncommitted-content >file0 && ( write_script abort-editor.sh <<-\EOF && echo >"$1" EOF test_set_editor "$(pwd)/abort-editor.sh" && test_must_fail git rebase -i --autostash HEAD^ && rm -f abort-editor.sh ) && echo uncommitted-content >expected && test_cmp expected file0 ' test_expect_success 'restore autostash on editor failure' ' test_when_finished "git reset --hard" && echo uncommitted-content >file0 && ( test_set_editor "false" && test_must_fail git rebase -i --autostash HEAD^ ) && echo uncommitted-content >expected && test_cmp expected file0 ' test_expect_success 'autostash is saved on editor failure with conflict' ' test_when_finished "git reset --hard" && echo uncommitted-content >file0 && ( write_script abort-editor.sh <<-\EOF && echo conflicting-content >file0 exit 1 EOF test_set_editor "$(pwd)/abort-editor.sh" && test_must_fail git rebase -i --autostash HEAD^ && rm -f abort-editor.sh ) && echo conflicting-content >expected && test_cmp expected file0 && git checkout file0 && git stash pop && echo uncommitted-content >expected && test_cmp expected file0 ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"git rebase --autostash tests">)} spids: [13] ) ] spids: [13] ) (C {(.)} {(./test-lib.sh)}) (C {(test_expect_success)} {(setup)} { (SQ <"\n"> <"\techo hello-world >file0 &&\n"> <"\tgit add . &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"initial commit\" &&\n"> <"\tgit checkout -b feature-branch &&\n"> <"\techo another-hello >file1 &&\n"> <"\techo goodbye >file2 &&\n"> <"\tgit add . &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"second commit\" &&\n"> <"\techo final-goodbye >file3 &&\n"> <"\tgit add . &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"third commit\" &&\n"> <"\tgit checkout -b unrelated-onto-branch master &&\n"> <"\techo unrelated >file4 &&\n"> <"\tgit add . &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"unrelated commit\" &&\n"> <"\tgit checkout -b related-onto-branch master &&\n"> <"\techo conflicting-change >file2 &&\n"> <"\tgit add . &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"related commit\"\n"> ) } ) (FuncDef name: testrebase body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:type) op: Equal rhs: {($ VSub_Number "$1")} spids: [63] ) ] spids: [63] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:dotest) op: Equal rhs: {($ VSub_Number "$2")} spids: [67] ) ] spids: [67] ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": dirty worktree, --no-autostash"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\ttest_when_finished git checkout feature-branch &&\n"> <"\t\techo dirty >>file3 &&\n"> <"\t\ttest_must_fail git rebase$type --no-autostash unrelated-onto-branch\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": dirty worktree, non-conflicting rebase"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\techo dirty >>file3 &&\n"> <"\t\tgit rebase$type unrelated-onto-branch &&\n"> <"\t\tgrep unrelated file4 &&\n"> <"\t\tgrep dirty file3 &&\n"> <"\t\tgit checkout feature-branch\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": dirty index, non-conflicting rebase"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\techo dirty >>file3 &&\n"> <"\t\tgit add file3 &&\n"> <"\t\tgit rebase$type unrelated-onto-branch &&\n"> <"\t\tgrep unrelated file4 &&\n"> <"\t\tgrep dirty file3 &&\n"> <"\t\tgit checkout feature-branch\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": conflicting rebase"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\techo dirty >>file3 &&\n"> <"\t\ttest_must_fail git rebase$type related-onto-branch &&\n"> <"\t\ttest_path_is_file $dotest/autostash &&\n"> <"\t\t! grep dirty file3 &&\n"> <"\t\trm -rf $dotest &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout feature-branch\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": --continue"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\techo dirty >>file3 &&\n"> <"\t\ttest_must_fail git rebase$type related-onto-branch &&\n"> <"\t\ttest_path_is_file $dotest/autostash &&\n"> <"\t\t! grep dirty file3 &&\n"> <"\t\techo \"conflicting-plus-goodbye\" >file2 &&\n"> <"\t\tgit add file2 &&\n"> <"\t\tgit rebase --continue &&\n"> <"\t\ttest_path_is_missing $dotest/autostash &&\n"> <"\t\tgrep dirty file3 &&\n"> <"\t\tgit checkout feature-branch\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": --skip"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\techo dirty >>file3 &&\n"> <"\t\ttest_must_fail git rebase$type related-onto-branch &&\n"> <"\t\ttest_path_is_file $dotest/autostash &&\n"> <"\t\t! grep dirty file3 &&\n"> <"\t\tgit rebase --skip &&\n"> <"\t\ttest_path_is_missing $dotest/autostash &&\n"> <"\t\tgrep dirty file3 &&\n"> <"\t\tgit checkout feature-branch\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": --abort"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\techo dirty >>file3 &&\n"> <"\t\ttest_must_fail git rebase$type related-onto-branch &&\n"> <"\t\ttest_path_is_file $dotest/autostash &&\n"> <"\t\t! grep dirty file3 &&\n"> <"\t\tgit rebase --abort &&\n"> <"\t\ttest_path_is_missing $dotest/autostash &&\n"> <"\t\tgrep dirty file3 &&\n"> <"\t\tgit checkout feature-branch\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ (rebase) ($ VSub_Name "$type") (": non-conflicting rebase, conflicting stash"))} { (SQ <"\n"> <"\t\ttest_config rebase.autostash true &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit checkout -b rebased-feature-branch feature-branch &&\n"> <"\t\ttest_when_finished git branch -D rebased-feature-branch &&\n"> <"\t\techo dirty >file4 &&\n"> <"\t\tgit add file4 &&\n"> <"\t\tgit rebase$type unrelated-onto-branch &&\n"> <"\t\ttest_path_is_missing $dotest &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgrep unrelated file4 &&\n"> <"\t\t! grep dirty file4 &&\n"> <"\t\tgit checkout feature-branch &&\n"> <"\t\tgit stash pop &&\n"> <"\t\tgrep dirty file4\n"> <"\t"> ) } ) ] spids: [60] ) spids: [56 59] ) (C {(test_expect_success)} {(DQ ("rebase: fast-forward rebase"))} { (SQ <"\n"> <"\ttest_config rebase.autostash true &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b behind-feature-branch feature-branch~1 &&\n"> <"\ttest_when_finished git branch -D behind-feature-branch &&\n"> <"\techo dirty >>file1 &&\n"> <"\tgit rebase feature-branch &&\n"> <"\tgrep dirty file1 &&\n"> <"\tgit checkout feature-branch\n"> ) } ) (C {(test_expect_success)} {(DQ ("rebase: noop rebase"))} { (SQ <"\n"> <"\ttest_config rebase.autostash true &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b same-feature-branch feature-branch &&\n"> <"\ttest_when_finished git branch -D same-feature-branch &&\n"> <"\techo dirty >>file1 &&\n"> <"\tgit rebase feature-branch &&\n"> <"\tgrep dirty file1 &&\n"> <"\tgit checkout feature-branch\n"> ) } ) (C {(testrebase)} {(DQ )} {(.git/rebase-apply)}) (C {(testrebase)} {(DQ (" --merge"))} {(.git/rebase-merge)}) (C {(testrebase)} {(DQ (" --interactive"))} {(.git/rebase-merge)}) (C {(test_expect_success)} {(SQ <"abort rebase -i with --autostash">)} { (SQ <"\n"> <"\ttest_when_finished \"git reset --hard\" &&\n"> <"\techo uncommitted-content >file0 &&\n"> <"\t(\n"> <"\t\twrite_script abort-editor.sh <<-\\EOF &&\n"> <"\t\t\techo >\"$1\"\n"> <"\t\tEOF\n"> <"\t\ttest_set_editor \"$(pwd)/abort-editor.sh\" &&\n"> <"\t\ttest_must_fail git rebase -i --autostash HEAD^ &&\n"> <"\t\trm -f abort-editor.sh\n"> <"\t) &&\n"> <"\techo uncommitted-content >expected &&\n"> <"\ttest_cmp expected file0\n"> ) } ) (C {(test_expect_success)} {(SQ <"restore autostash on editor failure">)} { (SQ <"\n"> <"\ttest_when_finished \"git reset --hard\" &&\n"> <"\techo uncommitted-content >file0 &&\n"> <"\t(\n"> <"\t\ttest_set_editor \"false\" &&\n"> <"\t\ttest_must_fail git rebase -i --autostash HEAD^\n"> <"\t) &&\n"> <"\techo uncommitted-content >expected &&\n"> <"\ttest_cmp expected file0\n"> ) } ) (C {(test_expect_success)} {(SQ <"autostash is saved on editor failure with conflict">)} { (SQ <"\n"> <"\ttest_when_finished \"git reset --hard\" &&\n"> <"\techo uncommitted-content >file0 &&\n"> <"\t(\n"> <"\t\twrite_script abort-editor.sh <<-\\EOF &&\n"> <"\t\t\techo conflicting-content >file0\n"> <"\t\t\texit 1\n"> <"\t\tEOF\n"> <"\t\ttest_set_editor \"$(pwd)/abort-editor.sh\" &&\n"> <"\t\ttest_must_fail git rebase -i --autostash HEAD^ &&\n"> <"\t\trm -f abort-editor.sh\n"> <"\t) &&\n"> <"\techo conflicting-content >expected &&\n"> <"\ttest_cmp expected file0 &&\n"> <"\tgit checkout file0 &&\n"> <"\tgit stash pop &&\n"> <"\techo uncommitted-content >expected &&\n"> <"\ttest_cmp expected file0\n"> ) } ) (C {(test_done)}) ] )