#!/bin/sh # # Copyright (c) 2007 Kristian Høgsberg # # FIXME: Test the various index usages, -i and -o, test reflog, # signoff global test_description := ''git commit'' source ./test-lib.sh source "$TEST_DIRECTORY/diff-lib.sh" global author := ''The Real Author '' test_tick test_expect_success 'initial status' ' echo bongo bongo >file && git add file && git status >actual && test_i18ngrep "Initial commit" actual ' test_expect_success 'fail initial amend' ' test_must_fail git commit --amend ' test_expect_success 'setup: initial commit' ' git commit -m initial ' test_expect_success '-m and -F do not mix' ' git checkout HEAD file && echo >>file && git add file && test_must_fail git commit -m foo -m bar -F file ' test_expect_success '-m and -C do not mix' ' git checkout HEAD file && echo >>file && git add file && test_must_fail git commit -C HEAD -m illegal ' test_expect_success 'paths and -a do not mix' ' echo King of the bongo >file && test_must_fail git commit -m foo -a file ' test_expect_success PERL 'can use paths with --interactive' ' echo bong-o-bong >file && # 2: update, 1:st path, that is all, 7: quit ( echo 2; echo 1; echo; echo 7 ) | git commit -m foo --interactive file && git reset --hard HEAD^ ' test_expect_success 'using invalid commit with -C' ' test_must_fail git commit --allow-empty -C bogus ' test_expect_success 'nothing to commit' ' git reset --hard && test_must_fail git commit -m initial ' test_expect_success '--dry-run fails with nothing to commit' ' test_must_fail git commit -m initial --dry-run ' test_expect_success '--short fails with nothing to commit' ' test_must_fail git commit -m initial --short ' test_expect_success '--porcelain fails with nothing to commit' ' test_must_fail git commit -m initial --porcelain ' test_expect_success '--long fails with nothing to commit' ' test_must_fail git commit -m initial --long ' test_expect_success 'setup: non-initial commit' ' echo bongo bongo bongo >file && git commit -m next -a ' test_expect_success '--dry-run with stuff to commit returns ok' ' echo bongo bongo bongo >>file && git commit -m next -a --dry-run ' test_expect_failure '--short with stuff to commit returns ok' ' echo bongo bongo bongo >>file && git commit -m next -a --short ' test_expect_failure '--porcelain with stuff to commit returns ok' ' echo bongo bongo bongo >>file && git commit -m next -a --porcelain ' test_expect_success '--long with stuff to commit returns ok' ' echo bongo bongo bongo >>file && git commit -m next -a --long ' test_expect_success 'commit message from non-existing file' ' echo more bongo: bongo bongo bongo bongo >file && test_must_fail git commit -F gah -a ' test_expect_success 'empty commit message' ' # Empty except stray tabs and spaces on a few lines. sed -e "s/@//g" >msg <<-\EOF && @ @ @@ @ @ @Signed-off-by: hula@ EOF test_must_fail git commit -F msg -a ' test_expect_success 'template "emptyness" check does not kick in with -F' ' git checkout HEAD file && echo >>file && git add file && git commit -t file -F file ' test_expect_success 'template "emptyness" check' ' git checkout HEAD file && echo >>file && git add file && test_must_fail git commit -t file 2>err && test_i18ngrep "did not edit" err ' test_expect_success 'setup: commit message from file' ' git checkout HEAD file && echo >>file && git add file && echo this is the commit message, coming from a file >msg && git commit -F msg -a ' test_expect_success 'amend commit' ' cat >editor <<-\EOF && #!/bin/sh sed -e "s/a file/an amend commit/g" < "$1" > "$1-" mv "$1-" "$1" EOF chmod 755 editor && EDITOR=./editor git commit --amend ' test_expect_success 'amend --only ignores staged contents' ' cp file file.expect && echo changed >file && git add file && git commit --no-edit --amend --only && git cat-file blob HEAD:file >file.actual && test_cmp file.expect file.actual && git diff --exit-code ' test_expect_success 'set up editor' ' cat >editor <<-\EOF && #!/bin/sh sed -e "s/unamended/amended/g" <"$1" >"$1-" mv "$1-" "$1" EOF chmod 755 editor ' test_expect_success 'amend without launching editor' ' echo unamended >expect && git commit --allow-empty -m "unamended" && echo needs more bongo >file && git add file && EDITOR=./editor git commit --no-edit --amend && git diff --exit-code HEAD -- file && git diff-tree -s --format=%s HEAD >msg && test_cmp expect msg ' test_expect_success '--amend --edit' ' echo amended >expect && git commit --allow-empty -m "unamended" && echo bongo again >file && git add file && EDITOR=./editor git commit --edit --amend && git diff-tree -s --format=%s HEAD >msg && test_cmp expect msg ' test_expect_success '--amend --edit of empty message' ' cat >replace <<-\EOF && #!/bin/sh echo "amended" >"$1" EOF chmod 755 replace && git commit --allow-empty --allow-empty-message -m "" && echo more bongo >file && git add file && EDITOR=./replace git commit --edit --amend && git diff-tree -s --format=%s HEAD >msg && ./replace expect && test_cmp expect msg ' test_expect_success '--amend to set message to empty' ' echo bata >file && git add file && git commit -m "unamended" && git commit --amend --allow-empty-message -m "" && git diff-tree -s --format=%s HEAD >msg && echo "" >expect && test_cmp expect msg ' test_expect_success '--amend to set empty message needs --allow-empty-message' ' echo conga >file && git add file && git commit -m "unamended" && test_must_fail git commit --amend -m "" && git diff-tree -s --format=%s HEAD >msg && echo "unamended" >expect && test_cmp expect msg ' test_expect_success '-m --edit' ' echo amended >expect && git commit --allow-empty -m buffer && echo bongo bongo >file && git add file && EDITOR=./editor git commit -m unamended --edit && git diff-tree -s --format=%s HEAD >msg && test_cmp expect msg ' test_expect_success '-m and -F do not mix' ' echo enough with the bongos >file && test_must_fail git commit -F msg -m amending . ' test_expect_success 'using message from other commit' ' git commit -C HEAD^ . ' test_expect_success 'editing message from other commit' ' cat >editor <<-\EOF && #!/bin/sh sed -e "s/amend/older/g" < "$1" > "$1-" mv "$1-" "$1" EOF chmod 755 editor && echo hula hula >file && EDITOR=./editor git commit -c HEAD^ -a ' test_expect_success 'message from stdin' ' echo silly new contents >file && echo commit message from stdin | git commit -F - -a ' test_expect_success 'overriding author from command line' ' echo gak >file && git commit -m author \ --author "Rubber Duck " -a >output 2>&1 && grep Rubber.Duck output ' test_expect_success PERL 'interactive add' ' echo 7 | git commit --interactive | grep "What now" ' test_expect_success PERL "commit --interactive doesn't change index if editor aborts" ' echo zoo >file && test_must_fail git diff --exit-code >diff1 && (echo u ; echo "*" ; echo q) | ( EDITOR=: && export EDITOR && test_must_fail git commit --interactive ) && git diff >diff2 && compare_diff_patch diff1 diff2 ' test_expect_success 'editor not invoked if -F is given' ' cat >editor <<-\EOF && #!/bin/sh sed -e s/good/bad/g <"$1" >"$1-" mv "$1-" "$1" EOF chmod 755 editor && echo A good commit message. >msg && echo moo >file && EDITOR=./editor git commit -a -F msg && git show -s --pretty=format:%s >subject && grep -q good subject && echo quack >file && echo Another good message. | EDITOR=./editor git commit -a -F - && git show -s --pretty=format:%s >subject && grep -q good subject ' test_expect_success 'partial commit that involves removal (1)' ' git rm --cached file && mv file elif && git add elif && git commit -m "Partial: add elif" elif && git diff-tree --name-status HEAD^ HEAD >current && echo "A elif" >expected && test_cmp expected current ' test_expect_success 'partial commit that involves removal (2)' ' git commit -m "Partial: remove file" file && git diff-tree --name-status HEAD^ HEAD >current && echo "D file" >expected && test_cmp expected current ' test_expect_success 'partial commit that involves removal (3)' ' git rm --cached elif && echo elif >elif && git commit -m "Partial: modify elif" elif && git diff-tree --name-status HEAD^ HEAD >current && echo "M elif" >expected && test_cmp expected current ' test_expect_success 'amend commit to fix author' ' oldtick=$GIT_AUTHOR_DATE && test_tick && git reset --hard && git cat-file -p HEAD | sed -e "s/author.*/author $author $oldtick/" \ -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \ expected && git commit --amend --author="$author" && git cat-file -p HEAD > current && test_cmp expected current ' test_expect_success 'amend commit to fix date' ' test_tick && newtick=$GIT_AUTHOR_DATE && git reset --hard && git cat-file -p HEAD | sed -e "s/author.*/author $author $newtick/" \ -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \ expected && git commit --amend --date="$newtick" && git cat-file -p HEAD > current && test_cmp expected current ' test_expect_success 'commit mentions forced date in output' ' git commit --amend --date=2010-01-02T03:04:05 >output && grep "Date: *Sat Jan 2 03:04:05 2010" output ' test_expect_success 'commit complains about completely bogus dates' ' test_must_fail git commit --amend --date=seventeen ' test_expect_success 'commit --date allows approxidate' ' git commit --amend \ --date="midnight the 12th of october, anno domini 1979" && echo "Fri Oct 12 00:00:00 1979 +0000" >expect && git log -1 --format=%ad >actual && test_cmp expect actual ' test_expect_success 'sign off (1)' ' echo 1 >positive && git add positive && git commit -s -m "thank you" && git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && ( echo thank you echo git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" ) >expected && test_cmp expected actual ' test_expect_success 'sign off (2)' ' echo 2 >positive && git add positive && existing="Signed-off-by: Watch This " && git commit -s -m "thank you $existing" && git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && ( echo thank you echo echo $existing git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" ) >expected && test_cmp expected actual ' test_expect_success 'signoff gap' ' echo 3 >positive && git add positive && alt="Alt-RFC-822-Header: Value" && git commit -s -m "welcome $alt" && git cat-file commit HEAD | sed -e "1,/^\$/d" > actual && ( echo welcome echo echo $alt git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" ) >expected && test_cmp expected actual ' test_expect_success 'signoff gap 2' ' echo 4 >positive && git add positive && alt="fixed: 34" && git commit -s -m "welcome We have now $alt" && git cat-file commit HEAD | sed -e "1,/^\$/d" > actual && ( echo welcome echo echo We have now echo $alt echo git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" ) >expected && test_cmp expected actual ' test_expect_success 'multiple -m' ' >negative && git add negative && git commit -m "one" -m "two" -m "three" && git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && ( echo one echo echo two echo echo three ) >expected && test_cmp expected actual ' test_expect_success 'amend commit to fix author' ' oldtick=$GIT_AUTHOR_DATE && test_tick && git reset --hard && git cat-file -p HEAD | sed -e "s/author.*/author $author $oldtick/" \ -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \ expected && git commit --amend --author="$author" && git cat-file -p HEAD > current && test_cmp expected current ' test_expect_success 'git commit with dirty index' ' echo tacocat > elif && echo tehlulz > chz && git add chz && git commit elif -m "tacocat is a palindrome" && git show --stat | grep elif && git diff --cached | grep chz ' test_expect_success 'same tree (single parent)' ' git reset --hard && test_must_fail git commit -m empty ' test_expect_success 'same tree (single parent) --allow-empty' ' git commit --allow-empty -m "forced empty" && git cat-file commit HEAD | grep forced ' test_expect_success 'same tree (merge and amend merge)' ' git checkout -b side HEAD^ && echo zero >zero && git add zero && git commit -m "add zero" && git checkout master && git merge -s ours side -m "empty ok" && git diff HEAD^ HEAD >actual && : >expected && test_cmp expected actual && git commit --amend -m "empty really ok" && git diff HEAD^ HEAD >actual && : >expected && test_cmp expected actual ' test_expect_success 'amend using the message from another commit' ' git reset --hard && test_tick && git commit --allow-empty -m "old commit" && old=$(git rev-parse --verify HEAD) && test_tick && git commit --allow-empty -m "new commit" && new=$(git rev-parse --verify HEAD) && test_tick && git commit --allow-empty --amend -C "$old" && git show --pretty="format:%ad %s" "$old" >expected && git show --pretty="format:%ad %s" HEAD >actual && test_cmp expected actual ' test_expect_success 'amend using the message from a commit named with tag' ' git reset --hard && test_tick && git commit --allow-empty -m "old commit" && old=$(git rev-parse --verify HEAD) && git tag -a -m "tag on old" tagged-old HEAD && test_tick && git commit --allow-empty -m "new commit" && new=$(git rev-parse --verify HEAD) && test_tick && git commit --allow-empty --amend -C tagged-old && git show --pretty="format:%ad %s" "$old" >expected && git show --pretty="format:%ad %s" HEAD >actual && test_cmp expected actual ' test_expect_success 'amend can copy notes' ' git config notes.rewrite.amend true && git config notes.rewriteRef "refs/notes/*" && test_commit foo && git notes add -m"a note" && test_tick && git commit --amend -m"new foo" && test "$(git notes show)" = "a note" ' test_expect_success 'commit a file whose name is a dash' ' git reset --hard && for i in 1 2 3 4 5 do echo $i done >./- && git add ./- && test_tick && git commit -m "add dash" >output newfile && git add newfile && git commit --only newfile -m"--only on unborn branch" && echo newfile >expected && git ls-tree -r --name-only HEAD >actual && test_cmp expected actual ' test_expect_success '--dry-run with conflicts fixed from a merge' ' # setup two branches with conflicting information # in the same file, resolve the conflict, # call commit with --dry-run echo "Initial contents, unimportant" >test-file && git add test-file && git commit -m "Initial commit" && echo "commit-1-state" >test-file && git commit -m "commit 1" -i test-file && git tag commit-1 && git checkout -b branch-2 HEAD^1 && echo "commit-2-state" >test-file && git commit -m "commit 2" -i test-file && ! $(git merge --no-commit commit-1) && echo "commit-2-state" >test-file && git add test-file && git commit --dry-run && git commit -m "conflicts fixed from merge." ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"git commit">)} spids: [20] ) ] spids: [20] ) (C {(.)} {(./test-lib.sh)}) (C {(.)} {(DQ ($ VSub_Name "$TEST_DIRECTORY") (/diff-lib.sh))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:author) op: Equal rhs: {(SQ <"The Real Author ">)} spids: [37] ) ] spids: [37] ) (C {(test_tick)}) (C {(test_expect_success)} {(SQ <"initial status">)} { (SQ <"\n"> <"\techo bongo bongo >file &&\n"> <"\tgit add file &&\n"> <"\tgit status >actual &&\n"> <"\ttest_i18ngrep \"Initial commit\" actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"fail initial amend">)} {(SQ <"\n"> <"\ttest_must_fail git commit --amend\n">)} ) (C {(test_expect_success)} {(SQ <"setup: initial commit">)} {(SQ <"\n"> <"\tgit commit -m initial\n">)} ) (C {(test_expect_success)} {(SQ <"-m and -F do not mix">)} { (SQ <"\n"> <"\tgit checkout HEAD file && echo >>file && git add file &&\n"> <"\ttest_must_fail git commit -m foo -m bar -F file\n"> ) } ) (C {(test_expect_success)} {(SQ <"-m and -C do not mix">)} { (SQ <"\n"> <"\tgit checkout HEAD file && echo >>file && git add file &&\n"> <"\ttest_must_fail git commit -C HEAD -m illegal\n"> ) } ) (C {(test_expect_success)} {(SQ <"paths and -a do not mix">)} { (SQ <"\n"> <"\techo King of the bongo >file &&\n"> <"\ttest_must_fail git commit -m foo -a file\n"> ) } ) (C {(test_expect_success)} {(PERL)} {(SQ <"can use paths with --interactive">)} { (SQ <"\n"> <"\techo bong-o-bong >file &&\n"> <"\t# 2: update, 1:st path, that is all, 7: quit\n"> <"\t( echo 2; echo 1; echo; echo 7 ) |\n"> <"\tgit commit -m foo --interactive file &&\n"> <"\tgit reset --hard HEAD^\n"> ) } ) (C {(test_expect_success)} {(SQ <"using invalid commit with -C">)} {(SQ <"\n"> <"\ttest_must_fail git commit --allow-empty -C bogus\n">)} ) (C {(test_expect_success)} {(SQ <"nothing to commit">)} {(SQ <"\n"> <"\tgit reset --hard &&\n"> <"\ttest_must_fail git commit -m initial\n">)} ) (C {(test_expect_success)} {(SQ <"--dry-run fails with nothing to commit">)} {(SQ <"\n"> <"\ttest_must_fail git commit -m initial --dry-run\n">)} ) (C {(test_expect_success)} {(SQ <"--short fails with nothing to commit">)} {(SQ <"\n"> <"\ttest_must_fail git commit -m initial --short\n">)} ) (C {(test_expect_success)} {(SQ <"--porcelain fails with nothing to commit">)} {(SQ <"\n"> <"\ttest_must_fail git commit -m initial --porcelain\n">)} ) (C {(test_expect_success)} {(SQ <"--long fails with nothing to commit">)} {(SQ <"\n"> <"\ttest_must_fail git commit -m initial --long\n">)} ) (C {(test_expect_success)} {(SQ <"setup: non-initial commit">)} {(SQ <"\n"> <"\techo bongo bongo bongo >file &&\n"> <"\tgit commit -m next -a\n">)} ) (C {(test_expect_success)} {(SQ <"--dry-run with stuff to commit returns ok">)} {(SQ <"\n"> <"\techo bongo bongo bongo >>file &&\n"> <"\tgit commit -m next -a --dry-run\n">)} ) (C {(test_expect_failure)} {(SQ <"--short with stuff to commit returns ok">)} {(SQ <"\n"> <"\techo bongo bongo bongo >>file &&\n"> <"\tgit commit -m next -a --short\n">)} ) (C {(test_expect_failure)} {(SQ <"--porcelain with stuff to commit returns ok">)} { (SQ <"\n"> <"\techo bongo bongo bongo >>file &&\n"> <"\tgit commit -m next -a --porcelain\n">) } ) (C {(test_expect_success)} {(SQ <"--long with stuff to commit returns ok">)} {(SQ <"\n"> <"\techo bongo bongo bongo >>file &&\n"> <"\tgit commit -m next -a --long\n">)} ) (C {(test_expect_success)} {(SQ <"commit message from non-existing file">)} { (SQ <"\n"> <"\techo more bongo: bongo bongo bongo bongo >file &&\n"> <"\ttest_must_fail git commit -F gah -a\n"> ) } ) (C {(test_expect_success)} {(SQ <"empty commit message">)} { (SQ <"\n"> <"\t# Empty except stray tabs and spaces on a few lines.\n"> <"\tsed -e \"s/@//g\" >msg <<-\\EOF &&\n"> <"\t\t@\t\t@\n"> <"\t\t@@\n"> <"\t\t@ @\n"> <"\t\t@Signed-off-by: hula@\n"> <"\tEOF\n"> <"\ttest_must_fail git commit -F msg -a\n"> ) } ) (C {(test_expect_success)} {(SQ <"template \"emptyness\" check does not kick in with -F">)} { (SQ <"\n"> <"\tgit checkout HEAD file && echo >>file && git add file &&\n"> <"\tgit commit -t file -F file\n"> ) } ) (C {(test_expect_success)} {(SQ <"template \"emptyness\" check">)} { (SQ <"\n"> <"\tgit checkout HEAD file && echo >>file && git add file &&\n"> <"\ttest_must_fail git commit -t file 2>err &&\n"> <"\ttest_i18ngrep \"did not edit\" err\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup: commit message from file">)} { (SQ <"\n"> <"\tgit checkout HEAD file && echo >>file && git add file &&\n"> <"\techo this is the commit message, coming from a file >msg &&\n"> <"\tgit commit -F msg -a\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend commit">)} { (SQ <"\n"> <"\tcat >editor <<-\\EOF &&\n"> <"\t#!/bin/sh\n"> <"\tsed -e \"s/a file/an amend commit/g\" < \"$1\" > \"$1-\"\n"> <"\tmv \"$1-\" \"$1\"\n"> <"\tEOF\n"> <"\tchmod 755 editor &&\n"> <"\tEDITOR=./editor git commit --amend\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend --only ignores staged contents">)} { (SQ <"\n"> <"\tcp file file.expect &&\n"> <"\techo changed >file &&\n"> <"\tgit add file &&\n"> <"\tgit commit --no-edit --amend --only &&\n"> <"\tgit cat-file blob HEAD:file >file.actual &&\n"> <"\ttest_cmp file.expect file.actual &&\n"> <"\tgit diff --exit-code\n"> ) } ) (C {(test_expect_success)} {(SQ <"set up editor">)} { (SQ <"\n"> <"\tcat >editor <<-\\EOF &&\n"> <"\t#!/bin/sh\n"> <"\tsed -e \"s/unamended/amended/g\" <\"$1\" >\"$1-\"\n"> <"\tmv \"$1-\" \"$1\"\n"> <"\tEOF\n"> <"\tchmod 755 editor\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend without launching editor">)} { (SQ <"\n"> <"\techo unamended >expect &&\n"> <"\tgit commit --allow-empty -m \"unamended\" &&\n"> <"\techo needs more bongo >file &&\n"> <"\tgit add file &&\n"> <"\tEDITOR=./editor git commit --no-edit --amend &&\n"> <"\tgit diff --exit-code HEAD -- file &&\n"> <"\tgit diff-tree -s --format=%s HEAD >msg &&\n"> <"\ttest_cmp expect msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"--amend --edit">)} { (SQ <"\n"> <"\techo amended >expect &&\n"> <"\tgit commit --allow-empty -m \"unamended\" &&\n"> <"\techo bongo again >file &&\n"> <"\tgit add file &&\n"> <"\tEDITOR=./editor git commit --edit --amend &&\n"> <"\tgit diff-tree -s --format=%s HEAD >msg &&\n"> <"\ttest_cmp expect msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"--amend --edit of empty message">)} { (SQ <"\n"> <"\tcat >replace <<-\\EOF &&\n"> <"\t#!/bin/sh\n"> <"\techo \"amended\" >\"$1\"\n"> <"\tEOF\n"> <"\tchmod 755 replace &&\n"> <"\tgit commit --allow-empty --allow-empty-message -m \"\" &&\n"> <"\techo more bongo >file &&\n"> <"\tgit add file &&\n"> <"\tEDITOR=./replace git commit --edit --amend &&\n"> <"\tgit diff-tree -s --format=%s HEAD >msg &&\n"> <"\t./replace expect &&\n"> <"\ttest_cmp expect msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"--amend to set message to empty">)} { (SQ <"\n"> <"\techo bata >file &&\n"> <"\tgit add file &&\n"> <"\tgit commit -m \"unamended\" &&\n"> <"\tgit commit --amend --allow-empty-message -m \"\" &&\n"> <"\tgit diff-tree -s --format=%s HEAD >msg &&\n"> <"\techo \"\" >expect &&\n"> <"\ttest_cmp expect msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"--amend to set empty message needs --allow-empty-message">)} { (SQ <"\n"> <"\techo conga >file &&\n"> <"\tgit add file &&\n"> <"\tgit commit -m \"unamended\" &&\n"> <"\ttest_must_fail git commit --amend -m \"\" &&\n"> <"\tgit diff-tree -s --format=%s HEAD >msg &&\n"> <"\techo \"unamended\" >expect &&\n"> <"\ttest_cmp expect msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"-m --edit">)} { (SQ <"\n"> <"\techo amended >expect &&\n"> <"\tgit commit --allow-empty -m buffer &&\n"> <"\techo bongo bongo >file &&\n"> <"\tgit add file &&\n"> <"\tEDITOR=./editor git commit -m unamended --edit &&\n"> <"\tgit diff-tree -s --format=%s HEAD >msg &&\n"> <"\ttest_cmp expect msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"-m and -F do not mix">)} { (SQ <"\n"> <"\techo enough with the bongos >file &&\n"> <"\ttest_must_fail git commit -F msg -m amending .\n"> ) } ) (C {(test_expect_success)} {(SQ <"using message from other commit">)} {(SQ <"\n"> <"\tgit commit -C HEAD^ .\n">)} ) (C {(test_expect_success)} {(SQ <"editing message from other commit">)} { (SQ <"\n"> <"\tcat >editor <<-\\EOF &&\n"> <"\t#!/bin/sh\n"> <"\tsed -e \"s/amend/older/g\" < \"$1\" > \"$1-\"\n"> <"\tmv \"$1-\" \"$1\"\n"> <"\tEOF\n"> <"\tchmod 755 editor &&\n"> <"\techo hula hula >file &&\n"> <"\tEDITOR=./editor git commit -c HEAD^ -a\n"> ) } ) (C {(test_expect_success)} {(SQ <"message from stdin">)} { (SQ <"\n"> <"\techo silly new contents >file &&\n"> <"\techo commit message from stdin |\n"> <"\tgit commit -F - -a\n"> ) } ) (C {(test_expect_success)} {(SQ <"overriding author from command line">)} { (SQ <"\n"> <"\techo gak >file &&\n"> <"\tgit commit -m author \\\n"> <"\t\t--author \"Rubber Duck \" -a >output 2>&1 &&\n"> <"\tgrep Rubber.Duck output\n"> ) } ) (C {(test_expect_success)} {(PERL)} {(SQ <"interactive add">)} {(SQ <"\n"> <"\techo 7 |\n"> <"\tgit commit --interactive |\n"> <"\tgrep \"What now\"\n">)} ) (C {(test_expect_success)} {(PERL)} {(DQ ("commit --interactive doesn't change index if editor aborts"))} { (SQ <"\n"> <"\techo zoo >file &&\n"> <"\ttest_must_fail git diff --exit-code >diff1 &&\n"> <"\t(echo u ; echo \"*\" ; echo q) |\n"> <"\t(\n"> <"\t\tEDITOR=: &&\n"> <"\t\texport EDITOR &&\n"> <"\t\ttest_must_fail git commit --interactive\n"> <"\t) &&\n"> <"\tgit diff >diff2 &&\n"> <"\tcompare_diff_patch diff1 diff2\n"> ) } ) (C {(test_expect_success)} {(SQ <"editor not invoked if -F is given">)} { (SQ <"\n"> <"\tcat >editor <<-\\EOF &&\n"> <"\t#!/bin/sh\n"> <"\tsed -e s/good/bad/g <\"$1\" >\"$1-\"\n"> <"\tmv \"$1-\" \"$1\"\n"> <"\tEOF\n"> <"\tchmod 755 editor &&\n"> <"\n"> <"\techo A good commit message. >msg &&\n"> <"\techo moo >file &&\n"> <"\n"> <"\tEDITOR=./editor git commit -a -F msg &&\n"> <"\tgit show -s --pretty=format:%s >subject &&\n"> <"\tgrep -q good subject &&\n"> <"\n"> <"\techo quack >file &&\n"> <"\techo Another good message. |\n"> <"\tEDITOR=./editor git commit -a -F - &&\n"> <"\tgit show -s --pretty=format:%s >subject &&\n"> <"\tgrep -q good subject\n"> ) } ) (C {(test_expect_success)} {(SQ <"partial commit that involves removal (1)">)} { (SQ <"\n"> <"\n"> <"\tgit rm --cached file &&\n"> <"\tmv file elif &&\n"> <"\tgit add elif &&\n"> <"\tgit commit -m \"Partial: add elif\" elif &&\n"> <"\tgit diff-tree --name-status HEAD^ HEAD >current &&\n"> <"\techo \"A\telif\" >expected &&\n"> <"\ttest_cmp expected current\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"partial commit that involves removal (2)">)} { (SQ <"\n"> <"\n"> <"\tgit commit -m \"Partial: remove file\" file &&\n"> <"\tgit diff-tree --name-status HEAD^ HEAD >current &&\n"> <"\techo \"D\tfile\" >expected &&\n"> <"\ttest_cmp expected current\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"partial commit that involves removal (3)">)} { (SQ <"\n"> <"\n"> <"\tgit rm --cached elif &&\n"> <"\techo elif >elif &&\n"> <"\tgit commit -m \"Partial: modify elif\" elif &&\n"> <"\tgit diff-tree --name-status HEAD^ HEAD >current &&\n"> <"\techo \"M\telif\" >expected &&\n"> <"\ttest_cmp expected current\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend commit to fix author">)} { (SQ <"\n"> <"\n"> <"\toldtick=$GIT_AUTHOR_DATE &&\n"> <"\ttest_tick &&\n"> <"\tgit reset --hard &&\n"> <"\tgit cat-file -p HEAD |\n"> <"\tsed -e \"s/author.*/author $author $oldtick/\" \\\n"> <"\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n"> <"\t\texpected &&\n"> <"\tgit commit --amend --author=\"$author\" &&\n"> <"\tgit cat-file -p HEAD > current &&\n"> <"\ttest_cmp expected current\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend commit to fix date">)} { (SQ <"\n"> <"\n"> <"\ttest_tick &&\n"> <"\tnewtick=$GIT_AUTHOR_DATE &&\n"> <"\tgit reset --hard &&\n"> <"\tgit cat-file -p HEAD |\n"> <"\tsed -e \"s/author.*/author $author $newtick/\" \\\n"> <"\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n"> <"\t\texpected &&\n"> <"\tgit commit --amend --date=\"$newtick\" &&\n"> <"\tgit cat-file -p HEAD > current &&\n"> <"\ttest_cmp expected current\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"commit mentions forced date in output">)} { (SQ <"\n"> <"\tgit commit --amend --date=2010-01-02T03:04:05 >output &&\n"> <"\tgrep \"Date: *Sat Jan 2 03:04:05 2010\" output\n"> ) } ) (C {(test_expect_success)} {(SQ <"commit complains about completely bogus dates">)} {(SQ <"\n"> <"\ttest_must_fail git commit --amend --date=seventeen\n">)} ) (C {(test_expect_success)} {(SQ <"commit --date allows approxidate">)} { (SQ <"\n"> <"\tgit commit --amend \\\n"> <"\t\t--date=\"midnight the 12th of october, anno domini 1979\" &&\n"> <"\techo \"Fri Oct 12 00:00:00 1979 +0000\" >expect &&\n"> <"\tgit log -1 --format=%ad >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"sign off (1)">)} { (SQ <"\n"> <"\n"> <"\techo 1 >positive &&\n"> <"\tgit add positive &&\n"> <"\tgit commit -s -m \"thank you\" &&\n"> <"\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n"> <"\t(\n"> <"\t\techo thank you\n"> <"\t\techo\n"> <"\t\tgit var GIT_COMMITTER_IDENT |\n"> <"\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n"> <"\t) >expected &&\n"> <"\ttest_cmp expected actual\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"sign off (2)">)} { (SQ <"\n"> <"\n"> <"\techo 2 >positive &&\n"> <"\tgit add positive &&\n"> <"\texisting=\"Signed-off-by: Watch This \" &&\n"> <"\tgit commit -s -m \"thank you\n"> <"\n"> <"$existing\" &&\n"> <"\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n"> <"\t(\n"> <"\t\techo thank you\n"> <"\t\techo\n"> <"\t\techo $existing\n"> <"\t\tgit var GIT_COMMITTER_IDENT |\n"> <"\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n"> <"\t) >expected &&\n"> <"\ttest_cmp expected actual\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"signoff gap">)} { (SQ <"\n"> <"\n"> <"\techo 3 >positive &&\n"> <"\tgit add positive &&\n"> <"\talt=\"Alt-RFC-822-Header: Value\" &&\n"> <"\tgit commit -s -m \"welcome\n"> <"\n"> <"$alt\" &&\n"> <"\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n"> <"\t(\n"> <"\t\techo welcome\n"> <"\t\techo\n"> <"\t\techo $alt\n"> <"\t\tgit var GIT_COMMITTER_IDENT |\n"> <"\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n"> <"\t) >expected &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"signoff gap 2">)} { (SQ <"\n"> <"\n"> <"\techo 4 >positive &&\n"> <"\tgit add positive &&\n"> <"\talt=\"fixed: 34\" &&\n"> <"\tgit commit -s -m \"welcome\n"> <"\n"> <"We have now\n"> <"$alt\" &&\n"> <"\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n"> <"\t(\n"> <"\t\techo welcome\n"> <"\t\techo\n"> <"\t\techo We have now\n"> <"\t\techo $alt\n"> <"\t\techo\n"> <"\t\tgit var GIT_COMMITTER_IDENT |\n"> <"\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n"> <"\t) >expected &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"multiple -m">)} { (SQ <"\n"> <"\n"> <"\t>negative &&\n"> <"\tgit add negative &&\n"> <"\tgit commit -m \"one\" -m \"two\" -m \"three\" &&\n"> <"\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n"> <"\t(\n"> <"\t\techo one\n"> <"\t\techo\n"> <"\t\techo two\n"> <"\t\techo\n"> <"\t\techo three\n"> <"\t) >expected &&\n"> <"\ttest_cmp expected actual\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend commit to fix author">)} { (SQ <"\n"> <"\n"> <"\toldtick=$GIT_AUTHOR_DATE &&\n"> <"\ttest_tick &&\n"> <"\tgit reset --hard &&\n"> <"\tgit cat-file -p HEAD |\n"> <"\tsed -e \"s/author.*/author $author $oldtick/\" \\\n"> <"\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n"> <"\t\texpected &&\n"> <"\tgit commit --amend --author=\"$author\" &&\n"> <"\tgit cat-file -p HEAD > current &&\n"> <"\ttest_cmp expected current\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"git commit with dirty index">)} { (SQ <"\n"> <"\techo tacocat > elif &&\n"> <"\techo tehlulz > chz &&\n"> <"\tgit add chz &&\n"> <"\tgit commit elif -m \"tacocat is a palindrome\" &&\n"> <"\tgit show --stat | grep elif &&\n"> <"\tgit diff --cached | grep chz\n"> ) } ) (C {(test_expect_success)} {(SQ <"same tree (single parent)">)} { (SQ <"\n"> <"\n"> <"\tgit reset --hard &&\n"> <"\ttest_must_fail git commit -m empty\n"> <"\n">) } ) (C {(test_expect_success)} {(SQ <"same tree (single parent) --allow-empty">)} { (SQ <"\n"> <"\n"> <"\tgit commit --allow-empty -m \"forced empty\" &&\n"> <"\tgit cat-file commit HEAD | grep forced\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"same tree (merge and amend merge)">)} { (SQ <"\n"> <"\n"> <"\tgit checkout -b side HEAD^ &&\n"> <"\techo zero >zero &&\n"> <"\tgit add zero &&\n"> <"\tgit commit -m \"add zero\" &&\n"> <"\tgit checkout master &&\n"> <"\n"> <"\tgit merge -s ours side -m \"empty ok\" &&\n"> <"\tgit diff HEAD^ HEAD >actual &&\n"> <"\t: >expected &&\n"> <"\ttest_cmp expected actual &&\n"> <"\n"> <"\tgit commit --amend -m \"empty really ok\" &&\n"> <"\tgit diff HEAD^ HEAD >actual &&\n"> <"\t: >expected &&\n"> <"\ttest_cmp expected actual\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend using the message from another commit">)} { (SQ <"\n"> <"\n"> <"\tgit reset --hard &&\n"> <"\ttest_tick &&\n"> <"\tgit commit --allow-empty -m \"old commit\" &&\n"> <"\told=$(git rev-parse --verify HEAD) &&\n"> <"\ttest_tick &&\n"> <"\tgit commit --allow-empty -m \"new commit\" &&\n"> <"\tnew=$(git rev-parse --verify HEAD) &&\n"> <"\ttest_tick &&\n"> <"\tgit commit --allow-empty --amend -C \"$old\" &&\n"> <"\tgit show --pretty=\"format:%ad %s\" \"$old\" >expected &&\n"> <"\tgit show --pretty=\"format:%ad %s\" HEAD >actual &&\n"> <"\ttest_cmp expected actual\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend using the message from a commit named with tag">)} { (SQ <"\n"> <"\n"> <"\tgit reset --hard &&\n"> <"\ttest_tick &&\n"> <"\tgit commit --allow-empty -m \"old commit\" &&\n"> <"\told=$(git rev-parse --verify HEAD) &&\n"> <"\tgit tag -a -m \"tag on old\" tagged-old HEAD &&\n"> <"\ttest_tick &&\n"> <"\tgit commit --allow-empty -m \"new commit\" &&\n"> <"\tnew=$(git rev-parse --verify HEAD) &&\n"> <"\ttest_tick &&\n"> <"\tgit commit --allow-empty --amend -C tagged-old &&\n"> <"\tgit show --pretty=\"format:%ad %s\" \"$old\" >expected &&\n"> <"\tgit show --pretty=\"format:%ad %s\" HEAD >actual &&\n"> <"\ttest_cmp expected actual\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"amend can copy notes">)} { (SQ <"\n"> <"\n"> <"\tgit config notes.rewrite.amend true &&\n"> <"\tgit config notes.rewriteRef \"refs/notes/*\" &&\n"> <"\ttest_commit foo &&\n"> <"\tgit notes add -m\"a note\" &&\n"> <"\ttest_tick &&\n"> <"\tgit commit --amend -m\"new foo\" &&\n"> <"\ttest \"$(git notes show)\" = \"a note\"\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"commit a file whose name is a dash">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\tfor i in 1 2 3 4 5\n"> <"\tdo\n"> <"\t\techo $i\n"> <"\tdone >./- &&\n"> <"\tgit add ./- &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"add dash\" >output <"\ttest_i18ngrep \" changed, 5 insertions\" output\n"> ) } ) (C {(test_expect_success)} {(SQ <"--only works on to-be-born branch">)} { (SQ <"\n"> <"\t# This test relies on having something in the index, as it\n"> <"\t# would not otherwise actually prove much. So check this.\n"> <"\ttest -n \"$(git ls-files)\" &&\n"> <"\tgit checkout --orphan orphan &&\n"> <"\techo foo >newfile &&\n"> <"\tgit add newfile &&\n"> <"\tgit commit --only newfile -m\"--only on unborn branch\" &&\n"> <"\techo newfile >expected &&\n"> <"\tgit ls-tree -r --name-only HEAD >actual &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"--dry-run with conflicts fixed from a merge">)} { (SQ <"\n"> <"\t# setup two branches with conflicting information\n"> <"\t# in the same file, resolve the conflict,\n"> <"\t# call commit with --dry-run\n"> <"\techo \"Initial contents, unimportant\" >test-file &&\n"> <"\tgit add test-file &&\n"> <"\tgit commit -m \"Initial commit\" &&\n"> <"\techo \"commit-1-state\" >test-file &&\n"> <"\tgit commit -m \"commit 1\" -i test-file &&\n"> <"\tgit tag commit-1 &&\n"> <"\tgit checkout -b branch-2 HEAD^1 &&\n"> <"\techo \"commit-2-state\" >test-file &&\n"> <"\tgit commit -m \"commit 2\" -i test-file &&\n"> <"\t! $(git merge --no-commit commit-1) &&\n"> <"\techo \"commit-2-state\" >test-file &&\n"> <"\tgit add test-file &&\n"> <"\tgit commit --dry-run &&\n"> <"\tgit commit -m \"conflicts fixed from merge.\"\n"> ) } ) (C {(test_done)}) ] )